feat: input, sleep

This commit is contained in:
Artemy 2022-08-04 19:05:56 +03:00
parent 89207ca812
commit 10ebab6b90
8 changed files with 256 additions and 29 deletions

14
Cargo.lock generated
View file

@ -190,13 +190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "onlang"
name = "on"
version = "0.1.0"
dependencies = [
"clap",
@ -206,6 +200,12 @@ dependencies = [
"serde_json",
]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "os_str_bytes"
version = "6.2.0"

View file

@ -1,5 +1,5 @@
[package]
name = "onlang"
name = "on"
version = "0.1.0"
edition = "2021"

29
README.md Normal file
View 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
View 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
View 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" }, "!"] },
]
```

View file

@ -163,6 +163,7 @@
["After executing calculated = ", { var: "calculated" }],
"\nRun loop",
{
loop: [
{
@ -174,10 +175,11 @@
loop: [
{
if: {
condition: { comp: [{ var: "num" }, ">=", 200000] },
condition: { comp: [{ var: "num" }, ">=", 100000] },
body: ["break"],
},
},
{
assign: {
num: { calc: [{ var: "num" }, "+", 1] },
@ -203,7 +205,7 @@
},
{
if: {
condition: { comp: [{ var: "calculated" }, ">=", 200000] },
condition: { comp: [{ var: "calculated" }, ">=", 100000] },
body: ["\n", "break"],
},
},
@ -212,30 +214,43 @@
{
if: {
condition: { comp: [{ var: "calculated" }, ">=", 199999] },
body: [["Calculated is >= ", 199999]],
else: [["Calculated is < ", 199999]],
condition: { comp: [{ var: "calculated" }, ">=", 99999] },
body: [["сalculated is >= ", 99999]],
else: [["сalculated is < ", 99999]],
},
},
{
if: {
condition: { comp: [{ var: "calculated" }, ">", 200000] },
body: [["Calculated is > ", 200000]],
else: [["Calculated is <= ", 200000]],
condition: { comp: [{ var: "calculated" }, ">", 100000] },
body: [["сalculated is > ", 100000]],
else: [["сalculated is <= ", 100000]],
},
},
"clear",
{ let: { i: 0 } },
// //TODO CONCEPTS ##########################################################################################################################################################################################################################
"\nLoop with sleep",
// {
// while: {
// cond: { comp: [1, ">=", {var: "variable"}] },
// body: [
// //commands
// ],
// },
// },
{
loop: [
{
if: {
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" }, "!"] },
]

View file

@ -2,6 +2,8 @@ use colored::*;
use json5;
use serde_json::{json, Map, Value};
use std::collections::HashMap;
use std::io::{self, Write};
use std::{thread, time};
pub struct Interpreter {
input: String,
vars: HashMap<String, Value>,
@ -18,8 +20,8 @@ impl Interpreter {
}
pub fn run(&mut self) {
let obj = json5::from_str::<Value>(&self.input).unwrap();
let arr = obj.as_array().unwrap();
let obj = json5::from_str::<Value>(&self.input).expect("Your json is invalid!");
let arr = obj.as_array().expect("Json must be an array!");
for command in arr {
self.eval_node(command);
@ -102,6 +104,22 @@ impl Interpreter {
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 {
Value::Object(value) => {
return self.if_node(value);
@ -150,10 +168,23 @@ impl Interpreter {
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) {
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 {
let condition = self.eval_node(&value["condition"]);
let nodes = &value.get("body");
@ -477,6 +508,7 @@ impl Interpreter {
if ln == true {
println!();
}
io::stdout().flush().unwrap_or_default();
}
fn print_one(&mut self, arg: &Value) {

View file

@ -1,7 +1,6 @@
use clap::Parser;
use std::fs;
use std::time::Instant;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {