Implement inefficient and not useful functions

- Function calls are inefficient
- Function parameters are passed in the global vartable (which is pretty
  bad)
This commit is contained in:
Daniel M 2022-02-03 13:17:06 +01:00
parent 85339db25e
commit 638610d310
3 changed files with 65 additions and 4 deletions

View File

@ -118,7 +118,7 @@ pub enum Statement {
Loop(Loop), Loop(Loop),
If(If), If(If),
Print(Expression), Print(Expression),
FunDecl(Vec<(String, Expression)>), FunDecl(String, Vec<String>, Ast),
} }
#[derive(Debug, PartialEq, Eq, Clone, Default)] #[derive(Debug, PartialEq, Eq, Clone, Default)]

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, fmt::Display, rc::Rc}; use std::{collections::HashMap, fmt::Display, rc::Rc, cell::RefCell};
use crate::{ast::{Expression, BinOpType, UnOpType, Ast, Statement, If}, parser::parse, lexer::lex}; use crate::{ast::{Expression, BinOpType, UnOpType, Ast, Statement, If}, parser::parse, lexer::lex};
@ -11,12 +11,14 @@ pub enum Value {
pub struct Interpreter { pub struct Interpreter {
// Variable table stores the runtime values of variables // Variable table stores the runtime values of variables
vartable: HashMap<String, Value>, vartable: HashMap<String, Value>,
funtable: HashMap<String, RefCell<(Vec<String>, Ast)>>,
} }
impl Interpreter { impl Interpreter {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
vartable: HashMap::new(), vartable: HashMap::new(),
funtable: HashMap::new(),
} }
} }
@ -68,7 +70,9 @@ impl Interpreter {
self.run(body_true); self.run(body_true);
} }
} }
Statement::FunDecl(_) => todo!(), Statement::FunDecl(name, args, body) => {
self.funtable.insert(name.clone(), (args.clone(), body.clone()).into());
}
} }
} }
@ -81,7 +85,21 @@ impl Interpreter {
Expression::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, lhs, rhs), Expression::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, lhs, rhs),
Expression::UnOp(uo, operand) => self.resolve_unop(uo, operand), Expression::UnOp(uo, operand) => self.resolve_unop(uo, operand),
Expression::Var(name) => self.resolve_var(name), Expression::Var(name) => self.resolve_var(name),
Expression::FunCall(_, _) => todo!(), Expression::FunCall(name, args) => {
let fun = self.funtable.get(name).expect("Function not declared").clone();
for i in 0 .. args.len() {
let val = self.resolve_expr(&args[i]);
self.vartable.insert(fun.borrow().0[i].clone(), val);
}
if fun.borrow().0.len() != args.len() {
panic!("Invalid number of arguments for function");
}
self.run(&fun.borrow().1);
Value::I64(0)
}
} }
} }

View File

@ -54,6 +54,49 @@ impl<T: Iterator<Item = Token>> Parser<T> {
Token::If => Statement::If(self.parse_if()), Token::If => Statement::If(self.parse_if()),
Token::Fun => {
self.next();
let name = match self.next() {
Token::Ident(name) => name,
_ => panic!("Error lexing function: Expected ident token"),
};
let mut args = Vec::new();
if !matches!(self.next(), Token::LParen) {
panic!("Expected opening parenthesis");
}
while self.peek() != &Token::RParen {
let argname = match self.next() {
Token::Ident(argname) => argname,
_ => panic!("Error lexing function: Expected ident token for argname"),
};
args.push(argname);
if self.peek() == &Token::Comma {
self.next();
}
}
self.next();
if !matches!(self.next(), Token::LBraces) {
panic!("Expected opening braces");
}
let body = self.parse();
if !matches!(self.next(), Token::RBraces) {
panic!("Expected closing braces");
}
Statement::FunDecl(name, args, body)
}
// If it is not a loop, try to lex as an expression // If it is not a loop, try to lex as an expression
_ => { _ => {
let stmt = Statement::Expr(self.parse_expr()); let stmt = Statement::Expr(self.parse_expr());