Add functions and some clean up
This commit is contained in:
parent
df3f0bf0a7
commit
c67cbf66e6
|
@ -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> {
|
||||
|
|
|
@ -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<Value, String> {
|
||||
let (f, t) = self
|
||||
.0
|
||||
|
|
|
@ -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 = { "!=" }
|
||||
|
||||
|
|
122
src/main.rs
122
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<Box<dyn Function>> = 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);
|
||||
}
|
||||
|
|
|
@ -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<S: ToString>(source: S) -> Statement {
|
||||
pub fn parse<S: ToString>(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<String>, Vec<Statement>);
|
||||
|
||||
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<Func>);
|
||||
|
||||
// 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<String>, body: Vec<Statement>) -> Self {
|
||||
self.0.push((name, params, body));
|
||||
self
|
||||
}
|
||||
}
|
||||
fn handle_rules(mut p: pest::iterators::Pairs<Rule>) -> Statement {
|
||||
fn parse_statement(pair: Pair<Rule>) -> Statement {
|
||||
|
||||
impl Extend<Func> for FuncHolder {
|
||||
fn extend<T>(&mut self, iter: T)
|
||||
where
|
||||
T: IntoIterator<Item = Func>,
|
||||
{
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<FuncHolder> for FuncHolder {
|
||||
fn extend<T>(&mut self, iter: T)
|
||||
where
|
||||
T: IntoIterator<Item = FuncHolder>,
|
||||
{
|
||||
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<Func>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_rules(mut p: pest::iterators::Pairs<Rule>) -> (Statement, FuncHolder) {
|
||||
fn parse_statement(pair: Pair<Rule>) -> (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<Rule>) -> 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<Rule>) -> Statement {
|
|||
let z = p.next().unwrap();
|
||||
parse_statement(z)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pest::Parser;
|
||||
|
||||
use super::{LangParser, Rule};
|
||||
|
||||
#[test]
|
||||
fn foo() {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue