mirror of
https://github.com/artegoser/ONLang
synced 2024-12-23 09:33:44 +03:00
feat: input, sleep
This commit is contained in:
parent
89207ca812
commit
10ebab6b90
8 changed files with 256 additions and 29 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -190,13 +190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "on"
|
||||||
version = "1.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "onlang"
|
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -206,6 +200,12 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.2.0"
|
version = "6.2.0"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "onlang"
|
name = "on"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|
29
README.md
Normal file
29
README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
![onlang logo](static/logos/OnLang-transparent.png)
|
||||||
|
|
||||||
|
# You may have questions
|
||||||
|
|
||||||
|
ONLang - Object Notation Language (js`ON`)
|
||||||
|
|
||||||
|
## 1. God, what the f\*\*\*\* is this
|
||||||
|
|
||||||
|
ONLang is an experimental, esoteric programming language, that allows you to use **json** for **PROGRAMMING**. The interpreter currently supports only json5 format.
|
||||||
|
|
||||||
|
## 2. What is it for
|
||||||
|
|
||||||
|
For writing simple scripts.
|
||||||
|
|
||||||
|
## 3. How run scripts
|
||||||
|
|
||||||
|
1. Add the executable file to the path variable
|
||||||
|
2. `on example.json5`
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
1. Clone this repo
|
||||||
|
2. `cargo run --quiet --release -- example.json5`
|
||||||
|
|
||||||
|
## 4. How to write on this
|
||||||
|
|
||||||
|
[Documentation](doc/main.md)
|
||||||
|
|
||||||
|
If you want to help create a pull request
|
12
ROADMAP.md
Normal file
12
ROADMAP.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# TODO CONCEPTS
|
||||||
|
|
||||||
|
1. Functions
|
||||||
|
2. imports
|
||||||
|
3. scopes of visibility
|
||||||
|
4. parallel tasks `{parallel:[..tasks]}`
|
||||||
|
5. types conversion
|
||||||
|
6. methods for arrays
|
||||||
|
7. writing objects to a variable
|
||||||
|
8. yaml support?
|
||||||
|
|
||||||
|
and something else
|
140
doc/main.md
Normal file
140
doc/main.md
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
# How to
|
||||||
|
|
||||||
|
`All posibilities in example.json5`
|
||||||
|
|
||||||
|
## How to print
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
"Just string in array",
|
||||||
|
["array", "of", "strings"],
|
||||||
|
{
|
||||||
|
print: ["Function"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
println: ["Function"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to calclulate values
|
||||||
|
|
||||||
|
works only with numbers (and variables with number type)
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{ calc: [2, "*", 3] }, //only 3 arguments
|
||||||
|
{ calc: [{ var: "some_variable" }, "-", 2] }, //{var:"some_var"} this is a way to get a variable
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supported operators
|
||||||
|
|
||||||
|
1. \+
|
||||||
|
2. \-
|
||||||
|
3. \*
|
||||||
|
4. \/
|
||||||
|
5. \%
|
||||||
|
6. \>\>
|
||||||
|
7. \<\<
|
||||||
|
8. \^
|
||||||
|
9. \&
|
||||||
|
10. \|
|
||||||
|
|
||||||
|
## How to compare values
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{ comp: [true, "!=", false] }, //only 3 arguments
|
||||||
|
{
|
||||||
|
comp: [
|
||||||
|
{
|
||||||
|
comp: [
|
||||||
|
{ comp: [{ calc: [1, "+", 1] }, ">", 3] },
|
||||||
|
"==",
|
||||||
|
{ var: "var_with_bool_value" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"&&",
|
||||||
|
{ comp: [{ comp: [{ calc: [1, "+", 1] }, ">", 3] }, "==", true] },
|
||||||
|
],
|
||||||
|
}, //more complex comparisons: (( 1 + 1 > 3 ) == var_with_bool_value) && (( 1 + 1 > 3 ) == true)
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supported operators for compare
|
||||||
|
|
||||||
|
1. ==
|
||||||
|
2. !=
|
||||||
|
3. \>
|
||||||
|
4. \<
|
||||||
|
5. \>=
|
||||||
|
6. \<=
|
||||||
|
7. \&\&
|
||||||
|
8. \|\|
|
||||||
|
|
||||||
|
## How to create a variable
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{
|
||||||
|
let: {
|
||||||
|
str: "A",
|
||||||
|
num: 2,
|
||||||
|
arr: ["Array", "in", "variable"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
let: {
|
||||||
|
calculated: { calc: [{ var: "num" }, "*", 4] }, //result 8
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to assign variable
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{
|
||||||
|
assign: {
|
||||||
|
calculated: { calc: [{ var: "calculated" }, "+", 1] }, // calculated = calculated + 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Loops
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{
|
||||||
|
loop: [
|
||||||
|
{
|
||||||
|
if: {
|
||||||
|
condition: { comp: [{ var: "i" }, ">=", 10] }, //if i >= 10 break loop
|
||||||
|
body: ["break"],
|
||||||
|
//else: [..commands] also work
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ assign: { i: { calc: [{ var: "i" }, "+", 1] } } }, // i += 1
|
||||||
|
{ print: ["\ri = ", { var: "i" }] },
|
||||||
|
{ sleep: 500 }, //sleep 500 ms
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Input from console
|
||||||
|
|
||||||
|
```json5
|
||||||
|
[
|
||||||
|
{
|
||||||
|
let: {
|
||||||
|
name: { input: "Your name: " },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ print: ["Bye, ", { var: "name" }, "!"] },
|
||||||
|
]
|
||||||
|
```
|
|
@ -163,6 +163,7 @@
|
||||||
["After executing calculated = ", { var: "calculated" }],
|
["After executing calculated = ", { var: "calculated" }],
|
||||||
|
|
||||||
"\nRun loop",
|
"\nRun loop",
|
||||||
|
|
||||||
{
|
{
|
||||||
loop: [
|
loop: [
|
||||||
{
|
{
|
||||||
|
@ -174,10 +175,11 @@
|
||||||
loop: [
|
loop: [
|
||||||
{
|
{
|
||||||
if: {
|
if: {
|
||||||
condition: { comp: [{ var: "num" }, ">=", 200000] },
|
condition: { comp: [{ var: "num" }, ">=", 100000] },
|
||||||
body: ["break"],
|
body: ["break"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
assign: {
|
assign: {
|
||||||
num: { calc: [{ var: "num" }, "+", 1] },
|
num: { calc: [{ var: "num" }, "+", 1] },
|
||||||
|
@ -203,7 +205,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
if: {
|
if: {
|
||||||
condition: { comp: [{ var: "calculated" }, ">=", 200000] },
|
condition: { comp: [{ var: "calculated" }, ">=", 100000] },
|
||||||
body: ["\n", "break"],
|
body: ["\n", "break"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -212,30 +214,43 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
if: {
|
if: {
|
||||||
condition: { comp: [{ var: "calculated" }, ">=", 199999] },
|
condition: { comp: [{ var: "calculated" }, ">=", 99999] },
|
||||||
body: [["Calculated is >= ", 199999]],
|
body: [["сalculated is >= ", 99999]],
|
||||||
else: [["Calculated is < ", 199999]],
|
else: [["сalculated is < ", 99999]],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
if: {
|
if: {
|
||||||
condition: { comp: [{ var: "calculated" }, ">", 200000] },
|
condition: { comp: [{ var: "calculated" }, ">", 100000] },
|
||||||
body: [["Calculated is > ", 200000]],
|
body: [["сalculated is > ", 100000]],
|
||||||
else: [["Calculated is <= ", 200000]],
|
else: [["сalculated is <= ", 100000]],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"clear",
|
{ let: { i: 0 } },
|
||||||
|
|
||||||
// //TODO CONCEPTS ##########################################################################################################################################################################################################################
|
"\nLoop with sleep",
|
||||||
|
|
||||||
// {
|
{
|
||||||
// while: {
|
loop: [
|
||||||
// cond: { comp: [1, ">=", {var: "variable"}] },
|
{
|
||||||
// body: [
|
if: {
|
||||||
// //commands
|
condition: { comp: [{ var: "i" }, ">=", 10] },
|
||||||
// ],
|
body: ["break"],
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
{ assign: { i: { calc: [{ var: "i" }, "+", 1] } } },
|
||||||
|
{ print: ["\ri = ", { var: "i" }] },
|
||||||
|
{ sleep: 500 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"\nInput a var",
|
||||||
|
{
|
||||||
|
let: {
|
||||||
|
name: { input: "Your name: " },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ print: ["Bye, ", { var: "name" }, "!"] },
|
||||||
]
|
]
|
|
@ -2,6 +2,8 @@ use colored::*;
|
||||||
use json5;
|
use json5;
|
||||||
use serde_json::{json, Map, Value};
|
use serde_json::{json, Map, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
use std::{thread, time};
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
input: String,
|
input: String,
|
||||||
vars: HashMap<String, Value>,
|
vars: HashMap<String, Value>,
|
||||||
|
@ -18,8 +20,8 @@ impl Interpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let obj = json5::from_str::<Value>(&self.input).unwrap();
|
let obj = json5::from_str::<Value>(&self.input).expect("Your json is invalid!");
|
||||||
let arr = obj.as_array().unwrap();
|
let arr = obj.as_array().expect("Json must be an array!");
|
||||||
|
|
||||||
for command in arr {
|
for command in arr {
|
||||||
self.eval_node(command);
|
self.eval_node(command);
|
||||||
|
@ -102,6 +104,22 @@ impl Interpreter {
|
||||||
self.error("Unsupported data type for the let argument");
|
self.error("Unsupported data type for the let argument");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"input" => match value {
|
||||||
|
Value::String(value) => {
|
||||||
|
return self.input(value);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.error("Unsupported data type for the input argument");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sleep" => match value {
|
||||||
|
Value::Number(value) => {
|
||||||
|
self.sleep(value);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.error("Unsupported data type for the sleep argument");
|
||||||
|
}
|
||||||
|
},
|
||||||
"if" => match value {
|
"if" => match value {
|
||||||
Value::Object(value) => {
|
Value::Object(value) => {
|
||||||
return self.if_node(value);
|
return self.if_node(value);
|
||||||
|
@ -150,10 +168,23 @@ impl Interpreter {
|
||||||
return Value::Null;
|
return Value::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sleep(&self, value: &serde_json::Number) {
|
||||||
|
let value = value.as_f64().unwrap() as u64;
|
||||||
|
thread::sleep(time::Duration::from_millis(value));
|
||||||
|
}
|
||||||
|
|
||||||
fn clear(&self) {
|
fn clear(&self) {
|
||||||
print!("{}[2J", 27 as char);
|
print!("{}[2J", 27 as char);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn input(&self, value: &String) -> Value {
|
||||||
|
let mut input = String::new();
|
||||||
|
print!("{}", value);
|
||||||
|
io::stdout().flush().unwrap_or_default();
|
||||||
|
io::stdin().read_line(&mut input).unwrap_or_default();
|
||||||
|
Value::String(input.trim_end().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
fn if_node(&mut self, value: &Map<String, Value>) -> Value {
|
fn if_node(&mut self, value: &Map<String, Value>) -> Value {
|
||||||
let condition = self.eval_node(&value["condition"]);
|
let condition = self.eval_node(&value["condition"]);
|
||||||
let nodes = &value.get("body");
|
let nodes = &value.get("body");
|
||||||
|
@ -477,6 +508,7 @@ impl Interpreter {
|
||||||
if ln == true {
|
if ln == true {
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
io::stdout().flush().unwrap_or_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_one(&mut self, arg: &Value) {
|
fn print_one(&mut self, arg: &Value) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(author, version, about, long_about = None)]
|
#[clap(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
|
Loading…
Add table
Reference in a new issue