Add functions and some clean up
This commit is contained in:
parent
df3f0bf0a7
commit
c67cbf66e6
|
@ -47,14 +47,6 @@ impl Env<'_> {
|
||||||
false
|
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> {
|
impl<'env> Env<'env> {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, marker::PhantomData};
|
||||||
use crate::{
|
use crate::{
|
||||||
env::Env,
|
env::Env,
|
||||||
statement::Statement,
|
statement::Statement,
|
||||||
value::{FromValue, Value},
|
value::{FromValue, Value}, pest_parser::FuncHolder,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod function_impl;
|
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> {
|
pub fn call(&self, name: &str, env: &Env, args: &[Value]) -> Result<Value, String> {
|
||||||
let (f, t) = self
|
let (f, t) = self
|
||||||
.0
|
.0
|
||||||
|
|
|
@ -49,7 +49,7 @@ root_statement = {
|
||||||
SOI ~ statement* ~ EOI
|
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* ~ "}" }
|
block = { "{" ~ statement* ~ "}" }
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ while_block = { "while" ~ expression ~ block }
|
||||||
|
|
||||||
if_block = { "if" ~ expression ~ block ~ ("else if" ~ expression ~ block)* ~ ("else" ~ block)? }
|
if_block = { "if" ~ expression ~ block ~ ("else if" ~ expression ~ block)* ~ ("else" ~ block)? }
|
||||||
|
|
||||||
|
def_params = { "(" ~ (identifier ~ ","?)* ~ ")" }
|
||||||
|
|
||||||
|
def = { "def" ~ identifier ~ def_params ~ block }
|
||||||
|
|
||||||
equals = { "==" }
|
equals = { "==" }
|
||||||
not_equals = { "!=" }
|
not_equals = { "!=" }
|
||||||
|
|
||||||
|
|
120
src/main.rs
120
src/main.rs
|
@ -1,9 +1,7 @@
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
|
|
||||||
use env::Env;
|
use env::Env;
|
||||||
use expression::{BinaryOperation, Expression};
|
use function::FunctionMap;
|
||||||
use function::{Function, FunctionMap, NativeFunction};
|
|
||||||
use pest::Parser;
|
|
||||||
use statement::Statement;
|
use statement::Statement;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
|
@ -17,125 +15,19 @@ mod value;
|
||||||
// mod parser;
|
// mod parser;
|
||||||
mod pest_parser;
|
mod pest_parser;
|
||||||
|
|
||||||
fn run(functions: FunctionMap, statements: &[Statement]) {
|
fn run(functions: FunctionMap, statement: Statement) {
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
for statement in statements {
|
|
||||||
statement.eval(&env, &functions);
|
statement.eval(&env, &functions);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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 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| {
|
m.insert_native("print", |a: &Value| {
|
||||||
println!("{}", a);
|
println!("{}", a);
|
||||||
});
|
});
|
||||||
m.insert_native("waluigi", || "Waluigi");
|
m.insert_native("waluigi", || "Waluigi");
|
||||||
let res = pest_parser::parse(f);
|
run(m, res);
|
||||||
let env = &Env::new();
|
|
||||||
res.eval(env, &m);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,77 +1,72 @@
|
||||||
use pest::{iterators::Pair, Parser};
|
use pest::{iterators::Pair, Parser};
|
||||||
use pest_derive::Parser;
|
use pest_derive::Parser;
|
||||||
|
|
||||||
use crate::{
|
use crate::{expression::Expression, statement::Statement, value::Value};
|
||||||
expression::{BinaryOperation, Expression},
|
|
||||||
statement::Statement,
|
|
||||||
value::Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[grammar = "grammar.pest"]
|
#[grammar = "grammar.pest"]
|
||||||
pub struct LangParser;
|
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 source = source.to_string();
|
||||||
let pairs = LangParser::parse(Rule::root_statement, &source).unwrap();
|
let pairs = LangParser::parse(Rule::root_statement, &source).unwrap();
|
||||||
handle_rules(pairs)
|
handle_rules(pairs)
|
||||||
}
|
}
|
||||||
|
type Func = (String, Vec<String>, Vec<Statement>);
|
||||||
|
|
||||||
pub fn parser_test() {
|
#[derive(Default)]
|
||||||
// let p = LangParser::parse(Rule::number, "-273.15").unwrap();
|
pub struct FuncHolder(Vec<Func>);
|
||||||
// println!("{:?}", p);
|
|
||||||
// let p = LangParser::parse(Rule::number, "25565");
|
|
||||||
// println!("{:?}", p);
|
|
||||||
|
|
||||||
// let str_test = LangParser::parse(Rule::string, "\"hello\"").unwrap();
|
impl FuncHolder {
|
||||||
// println!("{:?}", str_test);
|
fn insert(mut self, name: String, params: Vec<String>, body: Vec<Statement>) -> Self {
|
||||||
|
self.0.push((name, params, body));
|
||||||
// let str_test = LangParser::parse(Rule::char, "'a'").unwrap();
|
self
|
||||||
// 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());
|
|
||||||
}
|
}
|
||||||
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() {
|
match pair.as_rule() {
|
||||||
Rule::root_statement => {
|
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 => {
|
Rule::while_block => {
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let expr = inner.next().unwrap();
|
let expr = inner.next().unwrap();
|
||||||
let body = 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 => {
|
Rule::if_block => {
|
||||||
let mut inner = pair.into_inner().into_iter();
|
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() {
|
while let Some(expr) = inner.next() {
|
||||||
if expr.as_rule() == Rule::expression {
|
if expr.as_rule() == Rule::expression {
|
||||||
let body = inner.next().unwrap();
|
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 {
|
} 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 => {
|
Rule::assignment => {
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let name = inner.next().unwrap();
|
let name = inner.next().unwrap();
|
||||||
let expr = 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 => {
|
Rule::assignment_let => {
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let name = inner.next().unwrap();
|
let name = inner.next().unwrap();
|
||||||
let expr = 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 => {
|
Rule::statement => {
|
||||||
let inner = pair.into_inner().next().unwrap();
|
let inner = pair.into_inner().next().unwrap();
|
||||||
parse_statement(inner)
|
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),
|
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();
|
let z = p.next().unwrap();
|
||||||
parse_statement(z)
|
parse_statement(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use pest::Parser;
|
|
||||||
|
|
||||||
use super::{LangParser, Rule};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn foo() {}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue