diff --git a/src/env.rs b/src/env.rs index 68f989d..e6911b1 100644 --- a/src/env.rs +++ b/src/env.rs @@ -47,14 +47,6 @@ impl Env<'_> { false } } - - pub fn update(&self, name: &str, f: impl FnOnce(&Value) -> Value) { - if let Some(v) = self.values.write().unwrap().get_mut(name) { - *v = f(v); - } else if let Some(parent) = self.parent { - parent.update(name, f); - } - } } impl<'env> Env<'env> { diff --git a/src/function/mod.rs b/src/function/mod.rs index 55ca1ec..ceb36e9 100644 --- a/src/function/mod.rs +++ b/src/function/mod.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, marker::PhantomData}; use crate::{ env::Env, statement::Statement, - value::{FromValue, Value}, + value::{FromValue, Value}, pest_parser::FuncHolder, }; mod function_impl; @@ -44,6 +44,12 @@ impl FunctionMap { ); } + pub fn insert_holder(&mut self, holder:FuncHolder) { + for f in holder { + self.insert_interpreter(&f.0, f.1, f.2); + } + } + pub fn call(&self, name: &str, env: &Env, args: &[Value]) -> Result { let (f, t) = self .0 diff --git a/src/grammar.pest b/src/grammar.pest index 0587eba..7aa27d1 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -49,7 +49,7 @@ root_statement = { SOI ~ statement* ~ EOI } -statement = { ( assignment | assignment_let | expression ) ~ ";" | while_block | if_block | block } +statement = { ( assignment | assignment_let | expression ) ~ ";" | def | while_block | if_block | block } block = { "{" ~ statement* ~ "}" } @@ -61,6 +61,10 @@ while_block = { "while" ~ expression ~ block } if_block = { "if" ~ expression ~ block ~ ("else if" ~ expression ~ block)* ~ ("else" ~ block)? } +def_params = { "(" ~ (identifier ~ ","?)* ~ ")" } + +def = { "def" ~ identifier ~ def_params ~ block } + equals = { "==" } not_equals = { "!=" } diff --git a/src/main.rs b/src/main.rs index daea01e..8b594c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,7 @@ use std::fs::read_to_string; use env::Env; -use expression::{BinaryOperation, Expression}; -use function::{Function, FunctionMap, NativeFunction}; -use pest::Parser; +use function::FunctionMap; use statement::Statement; use value::Value; @@ -17,125 +15,19 @@ mod value; // mod parser; mod pest_parser; -fn run(functions: FunctionMap, statements: &[Statement]) { +fn run(functions: FunctionMap, statement: Statement) { let env = Env::new(); - for statement in statements { - statement.eval(&env, &functions); - } + statement.eval(&env, &functions); } fn main() { - // let statements = vec![ - // Statement::Assignment("a".to_string(), Expression::from(1)), - // Statement::Assignment("b".to_string(), Expression::from(2)), - // Statement::Assignment("c".to_string(), Expression::from(3)), - // Statement::Print(Expression::Binary( - // Box::new(Expression::Variable("a".to_string())), - // BinaryOperation::Add, - // Box::new(Expression::Variable("b".to_string())), - // )), - // Statement::Print(Expression::Binary( - // Box::new(Expression::Variable("a".to_string())), - // BinaryOperation::Add, - // Box::new(Expression::Variable("c".to_string())), - // )), - // Statement::Print(Expression::Binary( - // Box::new(Expression::Variable("b".to_string())), - // BinaryOperation::Add, - // Box::new(Expression::Variable("c".to_string())), - // )), - // ]; - // run(FunctionMap::new(), &statements); - - // let while_test = vec![ - // Statement::Print("while test".to_string().into()), - // Statement::Assignment("a".to_string(), Expression::from(1)), - // Statement::While( - // Expression::Binary( - // Box::new(Expression::Variable("a".to_string())), - // BinaryOperation::LessThan, - // Box::new(10.into()), - // ), - // vec![ - // Statement::Assignment( - // "a".to_string(), - // Expression::Binary( - // Box::new(Expression::Variable("a".to_string())), - // BinaryOperation::Add, - // Box::new(1.into()), - // ), - // ), - // Statement::Print(Expression::Variable("a".to_string())), - // ], - // ), - // ]; - // run(FunctionMap::new(), &while_test); - - // { - // let env = Env::new(); - - // let res = (|arg: &i32| arg + 1).native_execute(&env, &[Value::Int(1)]); - // println!("{:?}", res); - // } - - // { - // let z = || 100; - // let env = Env::new(); - // let res = z.native_execute(&env, &[]); - // println!("{:?}", res); - // } - - // { - // let z = |a: &Value| a.clone(); - // let env = Env::new(); - // let res = z.into_function().execute(&env, &FunctionMap::new(), &[]); - // println!("{:?}", res); - // } - - // { - // let z = |a: &String| a.clone(); - // let env = Env::new(); - // let res = z.native_execute(&env, &[100.into()]); - // println!("{:?}", res); - // } - - // { - // let v: Vec> = vec![ - // Box::new((|| 100).into_function()), - // Box::new((|a: &i32| a + 1).into_function()), - // ]; - // for f in v { - // let r = f.execute(&Env::new(), &FunctionMap::new(), &[100.into()]); - // println!("{:?}", r); - // } - // } - - // let mut m: FunctionMap = Default::default(); - // m.insert_native("print", |a: &Value| { - // println!("{}", a); - // }); - - // m.insert_native("waluigi", || "Waluigi"); - - // m.insert_interpreter("call_print", vec!["what".to_string()], vec![ - // Statement::Expression(Expression::Call("print".to_string(), vec![Expression::Variable("what".to_string())])), - // ]); - - // run( - // m, - // &vec![Statement::Expression(Expression::Call( - // "call_print".to_string(), - // vec![Expression::Call("waluigi".to_string(), vec![])], - // ))], - // ); - let f = read_to_string("./test.foo").unwrap(); - let mut m: FunctionMap = Default::default(); + let (res, funcs) = pest_parser::parse(f); + let mut m = FunctionMap::new(); + m.insert_holder(funcs); m.insert_native("print", |a: &Value| { println!("{}", a); }); m.insert_native("waluigi", || "Waluigi"); - let res = pest_parser::parse(f); - let env = &Env::new(); - res.eval(env, &m); + run(m, res); } diff --git a/src/pest_parser.rs b/src/pest_parser.rs index 5c3758c..e3d7d9c 100644 --- a/src/pest_parser.rs +++ b/src/pest_parser.rs @@ -1,77 +1,72 @@ use pest::{iterators::Pair, Parser}; use pest_derive::Parser; -use crate::{ - expression::{BinaryOperation, Expression}, - statement::Statement, - value::Value, -}; +use crate::{expression::Expression, statement::Statement, value::Value}; #[derive(Parser)] #[grammar = "grammar.pest"] pub struct LangParser; -pub fn parse(source: S) -> Statement { +pub fn parse(source: S) -> (Statement, FuncHolder) { let source = source.to_string(); let pairs = LangParser::parse(Rule::root_statement, &source).unwrap(); handle_rules(pairs) } +type Func = (String, Vec, Vec); -pub fn parser_test() { - // let p = LangParser::parse(Rule::number, "-273.15").unwrap(); - // println!("{:?}", p); - // let p = LangParser::parse(Rule::number, "25565"); - // println!("{:?}", p); +#[derive(Default)] +pub struct FuncHolder(Vec); - // let str_test = LangParser::parse(Rule::string, "\"hello\"").unwrap(); - // println!("{:?}", str_test); - - // let str_test = LangParser::parse(Rule::char, "'a'").unwrap(); - // println!("{:?}", str_test); - - // let foo = LangParser::parse(Rule::statement, "10 + foo + bar(20) * 40;").unwrap(); - // println!("{:?}", foo); - - // let bar = " - // let x = 10; - // let y = 20; - // let z = x + y; - // print(z); - // while (x < y) { - // x = x + 1; - // } - // let x = x + \"lmao\"; - // "; - // let bar = LangParser::parse(Rule::root_statement, bar); - // println!("{:?}", bar); - - let baz = " - if x { - a; - } else if y { - b; - } else { - c; - }"; - - let baz = LangParser::parse(Rule::root_statement, baz); - println!("{:?}", baz); - - let x = "x == 10;"; - let x = LangParser::parse(Rule::statement, x); - handle_rules(x.unwrap()); +impl FuncHolder { + fn insert(mut self, name: String, params: Vec, body: Vec) -> Self { + self.0.push((name, params, body)); + self + } } -fn handle_rules(mut p: pest::iterators::Pairs) -> Statement { - fn parse_statement(pair: Pair) -> Statement { + +impl Extend for FuncHolder { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + self.0.extend(iter); + } +} + +impl Extend for FuncHolder { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + self.0 + .extend(iter.into_iter().flat_map(|h| h.0.into_iter())); + } +} + +impl IntoIterator for FuncHolder { + type Item = Func; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +fn handle_rules(mut p: pest::iterators::Pairs) -> (Statement, FuncHolder) { + fn parse_statement(pair: Pair) -> (Statement, FuncHolder) { match pair.as_rule() { Rule::root_statement => { - Statement::Body(pair.into_inner().map(parse_statement).collect()) + let (z, f) = pair.into_inner().map(parse_statement).unzip(); + (Statement::Body(z), f) } Rule::while_block => { let mut inner = pair.into_inner(); let expr = inner.next().unwrap(); let body = inner.next().unwrap(); - Statement::While(parse_expression(expr), Box::new(parse_statement(body))) + ( + Statement::While(parse_expression(expr), Box::new(parse_statement(body).0)), + FuncHolder::default(), + ) } Rule::if_block => { let mut inner = pair.into_inner().into_iter(); @@ -80,31 +75,61 @@ fn handle_rules(mut p: pest::iterators::Pairs) -> Statement { while let Some(expr) = inner.next() { if expr.as_rule() == Rule::expression { let body = inner.next().unwrap(); - the_list.push((parse_expression(expr), parse_statement(body))); + the_list.push((parse_expression(expr), parse_statement(body).0)); } else { - the_else = Some(Box::new(parse_statement(expr))); + the_else = Some(Box::new(parse_statement(expr).0)); } } - Statement::If(the_list, the_else) + (Statement::If(the_list, the_else), FuncHolder::default()) } Rule::assignment => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let expr = inner.next().unwrap(); - Statement::Assignment(name.as_str().to_string(), parse_expression(expr), false) + ( + Statement::Assignment(name.as_str().to_string(), parse_expression(expr), false), + FuncHolder::default(), + ) } Rule::assignment_let => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let expr = inner.next().unwrap(); - Statement::Assignment(name.as_str().to_string(), parse_expression(expr), true) + ( + Statement::Assignment(name.as_str().to_string(), parse_expression(expr), true), + FuncHolder::default(), + ) } - Rule::expression => Statement::Expression(parse_expression(pair)), + Rule::expression => ( + Statement::Expression(parse_expression(pair)), + FuncHolder::default(), + ), Rule::statement => { let inner = pair.into_inner().next().unwrap(); parse_statement(inner) } - Rule::EOI => Statement::Body(vec![]), + Rule::block => { + let (z, _): (_, FuncHolder) = pair.into_inner().map(parse_statement).unzip(); + (Statement::Body(z), FuncHolder::default()) + } + Rule::def => { + let mut inner = pair.into_inner(); + let name = inner.next().unwrap(); + let args = inner + .next() + .unwrap() + .into_inner() + .map(|a| a.to_string()) + .collect(); + + let body = inner.next().unwrap(); + let body = parse_statement(body); + ( + Statement::Body(vec![]), + FuncHolder::default().insert(name.as_str().to_string(), args, vec![body.0]), + ) + } + Rule::EOI => (Statement::Body(vec![]), FuncHolder::default()), x => unreachable!("How did we get to {:?}", x), } } @@ -209,13 +234,3 @@ fn handle_rules(mut p: pest::iterators::Pairs) -> Statement { let z = p.next().unwrap(); parse_statement(z) } - -#[cfg(test)] -mod tests { - use pest::Parser; - - use super::{LangParser, Rule}; - - #[test] - fn foo() {} -} diff --git a/test.foo b/test.foo index dc2c189..895d1e5 100644 --- a/test.foo +++ b/test.foo @@ -1,4 +1,11 @@ + +foo(); + +def foo() { + print("hello, world!"); +} + let x = 10; let y = x-5; -print(y); \ No newline at end of file +print(y);