diff --git a/Cargo.lock b/Cargo.lock index 402a8a9..1018079 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,104 +3,5 @@ version = 3 [[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" -dependencies = [ - "const-random", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chumsky" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4" -dependencies = [ - "ahash", -] - -[[package]] -name = "const-random" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e" -dependencies = [ - "const-random-macro", - "proc-macro-hack", -] - -[[package]] -name = "const-random-macro" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb" -dependencies = [ - "getrandom", - "once_cell", - "proc-macro-hack", - "tiny-keccak", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "porte" -version = "0.4.0" -dependencies = [ - "chumsky", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +name = "prout" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index ad121e5..b345a3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,8 @@ [package] -name = "porte" -version = "0.4.0" +name = "prout" +version = "0.1.0" edition = "2021" -authors = ["JOLIMAITRE Matthieu "] -description = "A minimal programming language providing tools to automate file management like backups, building process or unit testing." -license = "MIT" -repository = "https://github.com/MajorBarnulf/porte" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chumsky = "0.8" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index c0f19fd..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 MajorBarnulf - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 527c8b3..2ee8839 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# PORTE +# PROUT * Programmable -* Opinionated * Repeatable +* Opinionated +* Understandable * Tiny -* Extensible ## Description -PORTE is a minimal programming language providing tools to automate file management like backups, building process or unit testing. +PROUT is a minimal programming language providing tools to automate file management like backups, building process or unit testing. ## Usage @@ -17,11 +17,11 @@ PORTE is a minimal programming language providing tools to automate file managem ```sh -$ porte hello-world.pr +$ prout hello_world.pr ``` -## Authors +## Author -- JOLIMAITRE Matthieu +- JOLIMAITRE Matthieu , developper diff --git a/examples/array.pr b/examples/array.pr deleted file mode 100644 index 2b65370..0000000 --- a/examples/array.pr +++ /dev/null @@ -1,117 +0,0 @@ - -for: (from, to, f) => { - index: from; - loop { - if not(inf(index, to)) break true; - f(index); - index <- add(index, 1) - } -}; - -array_new: () => { - r: obj(); - r <- set(r, "len", 0); - r -}; - -array_len: (self) => { - get(self, "len") -}; - -array_get: (self, index) => { - get(self, str(index)) -}; - -foreach: (arr, f) => { - l: array_len(arr); - for(0, l, (i) => { - f(array_get(arr, i)) - }) -}; - -array_push: (self, e) => { - i: array_len(self); - self <- set(self, str(i), e); - - len: add (i, 1); - self <- set(self, "len", len); - self -}; - -array_pop: (self) => { - l: array_len(self); - if eq(l, 0) return false; - - i: sub(l, 1); - e: array_get(self, i); - self <- set(self, str(i), false); - - rest: array_new(); - foreach(self, (item) => { if not(eq(item, false)) rest <- array_push(rest, item) }); - - r: obj(); - r <- set(r, "tail", e); - r <- set(r, "rest", rest); - r -}; - -array_swap: (self, i, j) => { - i_value: array_get(self, i); - j_value: array_get(self, j); - self <- set(self, str(j), i_value); - self <- set(self, str(i), j_value); - self -}; - -array_sort: (self, cmp) => { - l: array_len(self); - for(0, sub(l, 1), (i) => { - i_min: i; - for(add(i, 1), l, (j) => { - e_j: array_get(self, j); - e_min: array_get(self, i_min); - if inf(cmp(e_j, e_min), 0) i_min <- j - }); - self <- array_swap(self, i, i_min) - }); - self -}; - -array_print: (self) => { - l: array_len(self); - r: "[ "; - for(0, l, (i) => { - r <- add(r, array_get(self, i)); - if not(eq(i, sub(l, 1))) r <- add(r, ", ") - }); - r <- add(r, " ]"); - out(r) -}; - -"########################"; -"# main #"; -"########################"; - -a: array_new(); -out("new:"); -array_print(a); - -a <- array_push(a, 1); -a <- array_push(a, 4); -a <- array_push(a, 6); -a <- array_push(a, 3); -a <- array_push(a, 2); -out(""); -out("pushed:"); -array_print(a); - -r: array_pop(a); -a <- get(r, "rest"); -out(""); -out("popped:"); -array_print(a); - -a <- array_sort(a, (a, b) => { if sup(a, b) 1 else -1 }); -out(""); -out("sorted:"); -array_print(a); diff --git a/examples/hello-world.pr b/examples/hello-world.pr deleted file mode 100644 index 0b3072d..0000000 --- a/examples/hello-world.pr +++ /dev/null @@ -1,36 +0,0 @@ - -hello: "hello"; -porte: "porte"; - -line: hello; -line <- add(line, " "); -line <- add(line, porte); - -say-it: () => { - out(line) -}; - -say-it(); - - -for: (from, to, incr, fn) => { - index: from; - loop { - if not(inf(index, to)) break true; - result: fn(index); - index <- add(index, incr) - } -}; - -for(0, 3, 0.5, (index) => { - out(add("index: ", index)) -}); - - -a: 1; -b: 2; -c: 3; -a <- b <- c; -out(add("a :", a)); -out(add("b :", b)); -out(add("c :", c)); diff --git a/src/demo.rs b/src/demo.rs deleted file mode 100644 index 92c9e43..0000000 --- a/src/demo.rs +++ /dev/null @@ -1,21 +0,0 @@ -#[test] -fn ast() { - use crate::execution_tree; - use crate::syntax_tree; - - let text = r#" - a: 3; - { - a <- 4; - a: 5 - } - "#; - - let tree = syntax_tree::parser::ParserWrapper::new() - .parse(text) - .unwrap(); - dbg!(&tree); - - let executable = execution_tree::parser::Parser::parse(tree, |_| ()); - dbg!(&executable); -} diff --git a/src/execution_tree/parser.rs b/src/execution_tree/parser.rs index c504ac3..cf0c394 100644 --- a/src/execution_tree/parser.rs +++ b/src/execution_tree/parser.rs @@ -19,15 +19,6 @@ impl ParserBuilder { pub fn prelude(&mut self, name: String, value: Value) { self.prelude.push((name, value)); } - - fn append_globals(&self, body: &mut syntax_tree::Scope) { - let prelude = self.prelude.clone(); - for (name, value) in prelude.into_iter().rev() { - let value = syntax_tree::Expr::new_literal(value); - let expression = syntax_tree::Expr::new_variable_definition(name, value); - body.instructions.insert(0, expression); - } - } } pub struct Parser { @@ -35,45 +26,45 @@ pub struct Parser { } impl Parser { - fn new() -> Self { - let scopes = HashMap::new(); - Self { scopes } - } - - pub fn parse(syntax_tree: syntax_tree::Program, builder: F) -> execution_tree::Program + pub fn parse(ast: syntax_tree::Program, builder: F) -> execution_tree::Program where F: FnOnce(&mut ParserBuilder), { - let operation = builder; - let syntax_tree::Program { mut body } = syntax_tree; + let syntax_tree::Program { mut body } = ast; - let mut builder = ParserBuilder::new(); - operation(&mut builder); - builder.append_globals(&mut body); - - let mut parser = Self::new(); + let mut parser = Self { + scopes: HashMap::new(), + }; let parser_scope = ParserScope::new_root(); - let main_scope_id = parser.parse_syntax_tree_scope(body, &parser_scope); - let Self { scopes } = parser; + let mut parser_builder = ParserBuilder::new(); + builder(&mut parser_builder); + for (name, value) in parser_builder.prelude.into_iter().rev() { + let value = syntax_tree::Expr::new_literal(value); + let expression = syntax_tree::Expr::new_variable_definition(name, value); + body.instructions.insert(0, expression); + } + let body_scope_id = parser.parse_ast_scope(body, &parser_scope); + + let Self { scopes } = parser; execution_tree::Program { - main_scope_id, + main_scope_id: body_scope_id, scopes, } } - pub fn parse_syntax_tree_scope( + pub fn parse_ast_scope( &mut self, - syntax_tree_scope: syntax_tree::Scope, + ast_scope: syntax_tree::Scope, parser_scope: &ParserScope, ) -> execution_tree::Id { - let syntax_tree::Scope { instructions } = syntax_tree_scope; + let syntax_tree::Scope { instructions } = ast_scope; let scope_id = parser_scope.get_current_id(); let parent_scope_id = parser_scope.get_parent_id(); let expressions = instructions .into_iter() - .map(|expression| self.parse_expression(expression, parser_scope)) + .map(|expression| self.parse_expression(expression, &parser_scope)) .collect(); let local_variables = parser_scope.local_variable_ids(); @@ -95,8 +86,8 @@ impl Parser { let inner = expression.into_inner(); match inner { syntax_tree::ExprInner::Scope(scope) => { - let parser_scope = parser_scope.child_common(); - let scope = self.parse_syntax_tree_scope(scope, &parser_scope); + let parser_scope = parser_scope.make_child_common(); + let scope = self.parse_ast_scope(scope, &parser_scope); execution_tree::Expr::new_scope(scope) } syntax_tree::ExprInner::Literal(literal) => { @@ -196,12 +187,12 @@ impl Parser { parameter_names, } = function_definition; - let parser_scope = parser_scope.child_function(); + let parser_scope = parser_scope.make_child_common(); let parameter_ids = parameter_names .into_iter() .map(|name| parser_scope.add_name(name)) .collect(); - let body_scope_id = self.parse_syntax_tree_scope(body, &parser_scope); + let body_scope_id = self.parse_ast_scope(body, &parser_scope); execution_tree::FnDef { body_scope_id, @@ -218,7 +209,7 @@ impl Parser { let variable_id = parser_scope .get_variable_id(&name) - .unwrap_or_else(|| panic!("call of undeclared function '{name}'")); + .expect("call of undeclared function"); let parameters = arguments .into_iter() .map(|argument| self.parse_expression(argument, parser_scope)) @@ -255,8 +246,8 @@ impl Parser { ) -> execution_tree::Loop { let syntax_tree::Loop { body } = loop_; - let parser_scope = parser_scope.child_loop(); - let body_scope_id = self.parse_syntax_tree_scope(body, &parser_scope); + let parser_scope = parser_scope.make_child_loop(); + let body_scope_id = self.parse_ast_scope(body, &parser_scope); execution_tree::Loop { body_scope_id } } @@ -337,7 +328,7 @@ impl ParserScopeVariables { #[derive(Debug, Clone)] pub struct ParserScope { variables: Rc>, - next_id: Rc>, + next_global_id: Rc>, current_id: Id, parent_id: Option, current_function_scope_id: Option, @@ -347,7 +338,7 @@ pub struct ParserScope { impl ParserScope { pub fn new_root() -> Self { let current_id = Id::zero(); - let next_id = current_id.next(); + let next_global_id = current_id.next(); let variables = ParserScopeVariables { local_variables: HashMap::new(), parent_scope: None, @@ -355,21 +346,21 @@ impl ParserScope { Self { parent_id: None, current_id, - next_id: Rc::new(Mutex::new(next_id)), + next_global_id: Rc::new(Mutex::new(next_global_id)), variables: Rc::new(Mutex::new(variables)), current_function_scope_id: None, current_loop_scope_id: None, } } - pub fn child_common(&self) -> Self { + pub fn make_child_common(&self) -> Self { let variables = ParserScopeVariables { local_variables: HashMap::new(), parent_scope: Some(self.variables.clone()), }; Self { parent_id: Some(self.get_current_id()), - next_id: self.next_id.clone(), + next_global_id: self.next_global_id.clone(), variables: Rc::new(Mutex::new(variables)), current_id: self.request_new_id(), current_function_scope_id: self.get_current_function_id(), @@ -377,7 +368,7 @@ impl ParserScope { } } - pub fn child_function(&self) -> Self { + pub fn make_child_function(&self) -> Self { let variables = ParserScopeVariables { local_variables: HashMap::new(), parent_scope: Some(self.variables.clone()), @@ -387,15 +378,15 @@ impl ParserScope { Self { parent_id: Some(self.get_current_id()), - next_id: self.next_id.clone(), + next_global_id: self.next_global_id.clone(), variables: Rc::new(Mutex::new(variables)), current_id, - current_function_scope_id: Some(current_id), + current_function_scope_id: Some(current_id.clone()), current_loop_scope_id: None, } } - pub fn child_loop(&self) -> Self { + pub fn make_child_loop(&self) -> Self { let variables = ParserScopeVariables { local_variables: HashMap::new(), parent_scope: Some(self.variables.clone()), @@ -405,28 +396,28 @@ impl ParserScope { Self { parent_id: Some(self.get_current_id()), - next_id: self.next_id.clone(), + next_global_id: self.next_global_id.clone(), variables: Rc::new(Mutex::new(variables)), current_id, current_function_scope_id: self.get_current_function_id(), - current_loop_scope_id: Some(current_id), + current_loop_scope_id: Some(current_id.clone()), } } pub fn get_current_id(&self) -> Id { - self.current_id + self.current_id.clone() } pub fn get_current_function_id(&self) -> Option { - self.current_function_scope_id + self.current_function_scope_id.clone() } pub fn get_current_loop_id(&self) -> Option { - self.current_loop_scope_id + self.current_loop_scope_id.clone() } pub fn get_parent_id(&self) -> Option { - self.parent_id + self.parent_id.clone() } pub fn get_variable_id(&self, name: &str) -> Option { @@ -434,7 +425,7 @@ impl ParserScope { } fn request_new_id(&self) -> Id { - let mut next_id_ref = self.next_id.lock().unwrap(); + let mut next_id_ref = self.next_global_id.lock().unwrap(); let id = *next_id_ref; *next_id_ref = id.next(); id diff --git a/src/main.rs b/src/main.rs index bedf467..38b3733 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,3 @@ -use std::{env::args, fs}; - -pub mod demo; pub mod execution_tree; pub mod prelude; pub mod runtime; @@ -8,15 +5,7 @@ pub mod syntax_tree; pub mod value; fn main() { - use prelude::std_prelude; - - let path = args().nth(1).expect("[error]: usage 'porte '"); - let input = fs::read_to_string(path).expect("file not found"); - let ast_parser = syntax_tree::parser::ParserWrapper::new(); - let parsed = ast_parser.parse(&input).unwrap(); - let executable = execution_tree::parser::Parser::parse(parsed, std_prelude); - let mut runtime = runtime::Runtime::new(); - runtime.execute(&executable); + println!("Hello, world!"); } #[test] @@ -40,11 +29,11 @@ fn it_works() { ]), ), ), - Expr::new_function_call("my_print", vec!["hello, PORTE".into()]), + Expr::new_function_call("my_print", vec!["hello, PROUT".into()]), Expr::new_function_call("print", vec![Expr::new_variable_call("a")]), ]), }; - let exec = Parser::parse(ast, std_prelude); + let exec = Parser::parse(ast, |builder| std_prelude(builder)); println!("\n\n\n-- running: --"); let _result = Runtime::new().execute(&exec); } diff --git a/src/prelude.rs b/src/prelude.rs index 0869c9e..ac3d6bd 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,148 +1,14 @@ -use std::collections::HashMap; - use crate::{ execution_tree::parser::ParserBuilder, value::{function::Function, Value}, }; pub fn std_prelude(builder: &mut ParserBuilder) { - type FunctOper = fn(Vec) -> Value; - let functions: Vec<(_, _, FunctOper)> = vec![ - ("out", 1, out), - ("add", 2, add), - ("sub", 2, sub), - ("eq", 2, eq), - ("sup", 2, sup), - ("inf", 2, inf), - ("and", 2, and), - ("or", 2, or), - ("not", 1, not), - ("str", 2, str), - ("obj", 0, obj), - ("set", 3, set), - ("get", 2, get), - ]; - - for (name, arg_count, closure) in functions { - builder.prelude(name.into(), Function::new_native(arg_count, closure).into()); - } + builder.prelude("print".into(), Function::new_native(1, print).into()) } -fn out(args: Vec) -> Value { +fn print(args: Vec) -> Value { let to_print = args.get(0).unwrap(); - let str = value_to_string(to_print); - println!("{str}"); - to_print.clone() -} - -fn add(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Number(l), Value::Number(r)) => (l + r).into(), - (Value::String(l), Value::String(r)) => format!("{l}{r}").into(), - (Value::Number(l), Value::String(r)) => format!("{l}{r}").into(), - (Value::String(l), Value::Number(r)) => format!("{l}{r}").into(), - _ => panic!("adding incompatible types"), - } -} - -fn sub(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Number(l), Value::Number(r)) => (l - r).into(), - _ => panic!("substracting non-numbers"), - } -} - -fn eq(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Bool(l), Value::Bool(r)) => (l == r).into(), - (Value::Number(l), Value::Number(r)) => (l == r).into(), - (Value::String(l), Value::String(r)) => (l == r).into(), - _ => false.into(), - } -} - -fn sup(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Number(l), Value::Number(r)) => (l > r).into(), - _ => panic!("comparing non-numeric"), - } -} - -fn inf(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Number(l), Value::Number(r)) => (l < r).into(), - _ => panic!("comparing non-numeric"), - } -} - -fn and(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Bool(l), Value::Bool(r)) => (*l && *r).into(), - _ => panic!("intersection of non-boolean"), - } -} - -fn or(args: Vec) -> Value { - let lhs = args.get(0).unwrap(); - let rhs = args.get(1).unwrap(); - match (lhs, rhs) { - (Value::Bool(l), Value::Bool(r)) => (*l || *r).into(), - _ => panic!("union of non-boolean"), - } -} - -fn not(args: Vec) -> Value { - let input = args.get(0).unwrap(); - let result = !input.as_bool().expect("complementing non-bool"); - result.into() -} - -fn value_to_string(input: &Value) -> String { - match input { - Value::None => "None".to_string(), - Value::Bool(b) => format!("{b}"), - Value::Number(n) => format!("{n}"), - Value::String(s) => s.clone(), - Value::Object(_) => "[object]".into(), - Value::Function(_) => "[function]".into(), - } -} - -fn str(args: Vec) -> Value { - let input = args.get(0).unwrap(); - value_to_string(input).into() -} - -fn obj(_: Vec) -> Value { - Value::Object(HashMap::new()) -} - -fn set(args: Vec) -> Value { - let mut object = args.get(0).unwrap().as_object().unwrap().clone(); - let name = args.get(1).unwrap().as_string().unwrap().to_string(); - let value = args.get(2).unwrap().clone(); - if let Value::Bool(false) = value { - object.remove(&name); - } else { - object.insert(name, value); - } - object.into() -} - -fn get(args: Vec) -> Value { - let object = args.get(0).unwrap().as_object().unwrap(); - let name = args.get(1).unwrap().as_string().unwrap(); - object.get(name).cloned().unwrap_or_else(|| false.into()) + println!("{to_print:?}"); + Value::Bool(true) } diff --git a/src/runtime.rs b/src/runtime.rs index 22df2d4..a3bbcbd 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -24,12 +24,12 @@ impl FrameBuilder { } pub fn variable(&mut self, variable_id: &Id, default: Value) { - self.variables.insert(*variable_id, default); + self.variables.insert(variable_id.clone(), default); } } pub struct Frame { - _scope_id: Id, + scope_id: Id, variables: HashMap, } @@ -52,9 +52,9 @@ impl Frame { builder(&mut frame_builder); let FrameBuilder { variables } = frame_builder; - let scope_id = *scope_id; + let scope_id = scope_id.clone(); Self { - _scope_id: scope_id, + scope_id, variables, } } @@ -99,12 +99,6 @@ impl Stack { } } -impl Default for Stack { - fn default() -> Self { - Self::new() - } -} - pub struct ShortCircuit { value: Value, destination_scope_id: Id, @@ -144,9 +138,9 @@ impl ExecReturn { } } -impl From for ExecReturn { - fn from(val: Value) -> Self { - ExecReturn::new_value(val) +impl Into for Value { + fn into(self) -> ExecReturn { + ExecReturn::new_value(self) } } @@ -175,7 +169,7 @@ impl Runtime { where F: FnOnce(&mut FrameBuilder), { - let scope = program.scopes.get(scope_id).unwrap(); + let scope = program.scopes.get(&scope_id).unwrap(); let Scope { parent_scope_id: _, expressions, @@ -216,7 +210,9 @@ impl Runtime { ExprInner::FnDef(function_definition) => { self.execute_function_definition(function_definition) } - ExprInner::FnCall(function_call) => self.execute_function_call(function_call, program), + ExprInner::FnCall(function_call) => { + self.execute_function_call(function_call, program).into() + } ExprInner::FnRet(function_return) => { self.execute_function_return(function_return, program) } @@ -276,7 +272,7 @@ impl Runtime { parameter_ids: argument_ids, body_scope_id, } = function_definition; - let value = Function::new_constructed(argument_ids.clone(), *body_scope_id); + let value = Function::new_constructed(argument_ids.clone(), body_scope_id.clone()); let value = Value::Function(value); value.into() } @@ -371,7 +367,7 @@ impl Runtime { }) => value, }; - ExecReturn::new_short_circuit(value, *function_scope_id) + ExecReturn::new_short_circuit(value, function_scope_id.clone()) } pub fn execute_loop(&mut self, loop_: &Loop, program: &Program) -> ExecReturn { @@ -405,7 +401,7 @@ impl Runtime { } }; - ExecReturn::new_short_circuit(value, *loop_scope_id) + ExecReturn::new_short_circuit(value, loop_scope_id.clone()) } pub fn execute_condition(&mut self, condition: &Cond, program: &Program) -> ExecReturn { @@ -436,9 +432,3 @@ impl Runtime { } } } - -impl Default for Runtime { - fn default() -> Self { - Self::new() - } -} diff --git a/src/syntax_tree.rs b/src/syntax_tree.rs index 18f24af..d81bbb5 100644 --- a/src/syntax_tree.rs +++ b/src/syntax_tree.rs @@ -9,10 +9,6 @@ pub struct Program { pub struct Expr(pub Box); impl Expr { - pub fn new(inner: ExprInner) -> Self { - Self(Box::new(inner)) - } - pub fn inner(&self) -> &ExprInner { let Self(inner) = self; inner @@ -80,72 +76,6 @@ impl Expr { } } -impl From for Expr { - fn from(input: Scope) -> Self { - Self::new(ExprInner::Scope(input)) - } -} - -impl From for Expr { - fn from(input: Literal) -> Self { - Self::new(ExprInner::Literal(input)) - } -} - -impl From for Expr { - fn from(input: VarDef) -> Self { - Self::new(ExprInner::VarDef(input)) - } -} - -impl From for Expr { - fn from(input: VarAssign) -> Self { - Self::new(ExprInner::VarAssign(input)) - } -} - -impl From for Expr { - fn from(input: VarCall) -> Self { - Self::new(ExprInner::VarCall(input)) - } -} - -impl From for Expr { - fn from(input: FnDef) -> Self { - Self::new(ExprInner::FnDef(input)) - } -} - -impl From for Expr { - fn from(input: FnCall) -> Self { - Self::new(ExprInner::FnCall(input)) - } -} - -impl From for Expr { - fn from(input: FnRet) -> Self { - Self::new(ExprInner::FnRet(input)) - } -} - -impl From for Expr { - fn from(input: Loop) -> Self { - Self::new(ExprInner::Loop(input)) - } -} - -impl From for Expr { - fn from(input: LoopBr) -> Self { - Self::new(ExprInner::LoopBr(input)) - } -} - -impl From for Expr { - fn from(input: Cond) -> Self { - Self::new(ExprInner::Cond(input)) - } -} - impl From for Expr where T: Into, @@ -234,5 +164,3 @@ pub struct Cond { pub arm_true: Expr, pub arm_false: Option, } - -pub mod parser; diff --git a/src/syntax_tree/parser.rs b/src/syntax_tree/parser.rs deleted file mode 100644 index fbdb93f..0000000 --- a/src/syntax_tree/parser.rs +++ /dev/null @@ -1,422 +0,0 @@ -use super::*; -use chumsky::{prelude::*, text::whitespace}; - -pub trait AbstractParser: Parser> {} - -impl>> AbstractParser for U {} - -pub fn debugging_expression_parser() -> impl AbstractParser + Clone { - variable_call_parser().padded().map(|v| v.into()) -} - -pub fn scope_parser(expression: impl AbstractParser + Clone) -> impl AbstractParser { - let open_list = expression.separated_by(just(';')); - let closed_list = open_list.clone().then_ignore(just(';').then(whitespace())); - open_list - .map(|instructions| Scope { instructions }) - .or(closed_list.map(|mut instructions| { - instructions.push(Value::None.into()); - Scope { instructions } - })) - .padded() - .delimited_by(just('{'), just('}')) -} - -#[test] -fn test_scope_parser() { - let parser = scope_parser(debugging_expression_parser()); - let value = parser.parse("{ arbre }"); - dbg!(value.unwrap()); -} - -// TODO: add objects ? -pub fn literal_value() -> impl AbstractParser { - let bool = just("false") - .map(|_| false.into()) - .or(just("true").map(|_| true.into())); - - let none = just("none").map(|_| Value::None); - - let string = just('\"') - .ignore_then(none_of("\"").repeated()) - .then_ignore(just('\"')) - .map(|v| String::from_iter(&v).into()); - - let frac = just('.').chain(text::digits(10)); - let number = just('-') - .or_not() - .chain(text::int(10)) - .chain::(frac.or_not().flatten()) - .collect::() - .from_str() - .unwrapped() - .map(|n: f64| n.into()); - - bool.or(none).or(string).or(number) -} - -#[test] -fn test_literal_value() { - let parser = literal_value(); - let value = parser.parse("5"); - assert_eq!(value.unwrap().as_number().unwrap(), 5.); -} - -pub fn name() -> impl AbstractParser + Clone { - let first = one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - let rest = first.clone().or(one_of("1234567890-_+/*")); - - first.then(rest.repeated()).map(|(f, v)| { - let rest = String::from_iter(&v); - format!("{f}{rest}") - }) -} - -pub fn variable_definition_parser( - expression: impl AbstractParser, -) -> impl AbstractParser { - name() - .then_ignore(just(":").padded()) - .then(expression) - .map(|(name, value)| VarDef { name, value }) -} - -#[test] -fn test_variable_definition_parser() { - let parser = variable_definition_parser(debugging_expression_parser()); - let value = parser.parse("a : b"); - dbg!(value.unwrap()); -} - -pub fn variable_assignement_parser( - expression: impl AbstractParser, -) -> impl AbstractParser { - name() - .then_ignore(just("<-").padded()) - .then(expression) - .map(|(name, value)| VarAssign { name, value }) -} - -#[test] -fn test_variable_assignement_parser() { - let parser = variable_assignement_parser(debugging_expression_parser()); - let value = parser.parse("arbre <- expr"); - dbg!(value.unwrap()); -} - -pub fn variable_call_parser() -> impl AbstractParser + Clone { - name().map(|name| VarCall { name }) -} - -#[test] -fn test_variable_call_parser() { - let parser = variable_call_parser(); - let value = parser.parse("arbre"); - assert_eq!(value.unwrap().name, "arbre".to_string()); -} - -pub fn function_definition_parser( - expression: impl AbstractParser + Clone, -) -> impl AbstractParser { - let parameters = name().separated_by(just(',').padded()); - let body = scope_parser(expression); - parameters - .padded() - .delimited_by(just('('), just(')')) - .then_ignore(just("=>").padded()) - .then(body) - .map(|(parameter_names, body)| FnDef { - body, - parameter_names, - }) -} - -#[test] -fn test_function_definition_parser() { - let parser = function_definition_parser(debugging_expression_parser()); - let value = parser.parse("(a) => { b }"); - dbg!(value.unwrap()); -} - -pub fn function_call_parser(expression: impl AbstractParser) -> impl AbstractParser { - let parameters = expression.separated_by(just(',').padded()); - name() - .then( - parameters - .padded() - .delimited_by(just('('), just(')')) - .padded(), - ) - .map(|(name, arguments)| FnCall { arguments, name }) -} - -#[test] -fn test_function_call_parser() { - let parser = function_call_parser(debugging_expression_parser()); - let value = parser.parse("f( a , b )"); - dbg!(value.unwrap()); -} - -pub fn function_return_parser(expression: impl AbstractParser) -> impl AbstractParser { - just("return") - .ignore_then(expression.or_not()) - .map(|expr| expr.unwrap_or(From::::from(true.into()))) - .map(|value| FnRet { value }) -} - -#[test] -fn test_function_return_parser() { - let parser = function_return_parser(debugging_expression_parser()); - let value = parser.parse("return a"); - dbg!(value.unwrap()); -} - -pub fn loop_parser(expression: impl AbstractParser + Clone) -> impl AbstractParser { - just("loop") - .then(whitespace()) - .ignore_then(scope_parser(expression)) - .map(|body| Loop { body }) -} - -#[test] -fn test_loop_parser() { - let parser = loop_parser(debugging_expression_parser()); - let value = parser.parse("loop { a}"); - dbg!(value.unwrap()); -} - -pub fn loop_break_parser(expression: impl AbstractParser) -> impl AbstractParser { - just("break") - .ignore_then(just(" ").then(whitespace()).ignore_then(expression)) - .map(|value| LoopBr { value }) -} - -#[test] -fn test_loop_break_parser() { - let parser = loop_break_parser(debugging_expression_parser()); - let value = parser.parse("break a"); - dbg!(value.unwrap()); -} - -pub fn condition_parser( - expression: impl AbstractParser + Clone, -) -> impl AbstractParser { - just("if ") - .ignore_then(expression.clone()) - .then(expression.clone()) - .then(just("else ").ignore_then(expression).or_not()) - .map(|((condition, arm_true), arm_false)| Cond { - condition, - arm_true, - arm_false, - }) -} - -#[test] -fn test_condition_parser() { - let parser = condition_parser(debugging_expression_parser()); - let value = parser.parse("if a t else f"); - dbg!(value.unwrap()); -} - -fn _sugar_parser(expression: impl AbstractParser + Clone) -> impl AbstractParser { - let add = expression - .clone() - .then_ignore(just(" + ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "add".into(), - arguments: vec![l, r], - } - .into() - }); - - let sub = expression - .clone() - .then_ignore(just(" - ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "sub".into(), - arguments: vec![l, r], - } - .into() - }); - - let eq = expression - .clone() - .then_ignore(just(" == ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "eq".into(), - arguments: vec![l, r], - } - .into() - }); - - let sup = expression - .clone() - .then_ignore(just(" > ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "sup".into(), - arguments: vec![l, r], - } - .into() - }); - - let inf = expression - .clone() - .then_ignore(just(" < ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "inf".into(), - arguments: vec![l, r], - } - .into() - }); - - let or = expression - .clone() - .then_ignore(just(" || ")) - .then(expression.clone()) - .map(|(l, r)| { - FnCall { - name: "or".into(), - arguments: vec![l, r], - } - .into() - }); - - let and = expression - .clone() - .then_ignore(just(" && ")) - .then(expression) - .map(|(l, r)| { - FnCall { - name: "and".into(), - arguments: vec![l, r], - } - .into() - }); - - eq.or(add).or(sub).or(sup).or(inf).or(or).or(and) -} - -pub fn expression_parser() -> impl AbstractParser { - let expression = recursive(|expression| { - //let sugar = sugar_parser(expression.clone()); - let condition = condition_parser(expression.clone()).map(|i| i.into()); - let function_definition = function_definition_parser(expression.clone()).map(|i| i.into()); - let function_return = function_return_parser(expression.clone()).map(|i| i.into()); - let loop_ = loop_parser(expression.clone()).map(|i| i.into()); - let loop_break = loop_break_parser(expression.clone()).map(|i| i.into()); - let scope = scope_parser(expression.clone()).map(|i| i.into()); - let litteral = literal_value().map(Expr::new_literal); - let variable_definition = variable_definition_parser(expression.clone()).map(|i| i.into()); - let variable_assignment = variable_assignement_parser(expression.clone()).map(|i| i.into()); - let function_call = function_call_parser(expression.clone()).map(|i| i.into()); - let variable_call = variable_call_parser().map(|i| i.into()); - - //sugar - // .or(condition) - condition - .or(function_definition) - .or(function_return) - .or(loop_) - .or(loop_break) - .or(scope) - .or(litteral) - .or(variable_definition) - .or(variable_assignment) - .or(function_call) - .or(variable_call) - .padded() - }); - expression -} - -#[test] -fn test_expression_parser() { - let text = r##"if a b"##; - let parser = expression_parser(); - let value = parser.parse(text); - dbg!(value.unwrap()); -} - -fn parser() -> impl AbstractParser { - let scope = expression_parser() - .separated_by(just(';').padded()) - .then_ignore(just(';').padded().or_not()) - .then_ignore(end()); - - scope.map(|instructions| { - let body = Scope { instructions }; - Program { body } - }) -} - -#[test] -fn test_parser() { - let example = r##" -print(3); - -a: 3; - -b: (a) => { - print("a") -}; - -f(a) - -"##; - let parser = parser(); - let e = parser.parse(example); - dbg!(e.unwrap()); -} - -pub struct ParserWrapper { - inner: Box>, -} - -impl ParserWrapper { - pub fn new() -> Self { - let inner = Box::new(parser()); - ParserWrapper { inner } - } - - pub fn parse(&self, input: &str) -> Result>> { - self.inner.parse(input) - } -} - -impl Default for ParserWrapper { - fn default() -> Self { - Self::new() - } -} - -/* -// example - -my-print: (input) => { - concatenated: { - "now I would like to interject for a moment" + input - }; - print(input); -} - -a: 5.2; -loop { - if a <= 0 { - break true - } else { - a <- a - 1 - } -} - -*/ diff --git a/src/value.rs b/src/value.rs index 7f4b424..2a82608 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use self::function::Function; pub mod function { - use crate::execution_tree::Id; + use crate::execution_tree::{Expr, Id}; use super::Value; @@ -55,9 +55,9 @@ pub mod function { } } - impl From for Value { - fn from(val: Function) -> Self { - Value::Function(val) + impl Into for Function { + fn into(self) -> Value { + Value::Function(self) } } } @@ -72,34 +72,6 @@ pub enum Value { } impl Value { - pub fn as_bool(&self) -> Option { - match self { - Self::Bool(b) => Some(*b), - _ => None, - } - } - - pub fn as_number(&self) -> Option { - match self { - Self::Number(n) => Some(*n), - _ => None, - } - } - - pub fn as_string(&self) -> Option<&str> { - match self { - Self::String(s) => Some(s), - _ => None, - } - } - - pub fn as_object(&self) -> Option<&HashMap> { - match self { - Self::Object(h) => Some(h), - _ => None, - } - } - pub fn as_function(&self) -> Option<&Function> { match self { Self::Function(function) => Some(function), @@ -132,12 +104,6 @@ impl From<&str> for Value { } } -impl From> for Value { - fn from(value: HashMap) -> Self { - Self::Object(value) - } -} - impl From> for Value where T: Into,