Prepared for supporting multiple function arguments. The types now support several arguments, and the only thing left is to parse this.

This commit is contained in:
PaddiM8 2020-05-29 00:27:08 +02:00
parent 94722ed27e
commit 6d67797565
3 changed files with 64 additions and 24 deletions

View File

@ -75,11 +75,16 @@ impl Visitor<f64, f64> for Interpreter {
self.symbol_table.insert(identifier.clone(), stmt.clone()); self.symbol_table.insert(identifier.clone(), stmt.clone());
0f64 0f64
} }
Stmt::FnDecl(identifier, argument, _) => { Stmt::FnDecl(identifier, arguments, _) => {
self.visit_stmt(&Stmt::VarDecl( // Initialise each of the arguments as their own variable.
argument.clone(), for argument in arguments {
Box::new(Expr::Literal(String::from("0"))), self.visit_stmt(&Stmt::VarDecl(
)); argument.clone(),
Box::new(Expr::Literal(String::from("0"))),
));
}
// Add the function to the symbol table.
self.symbol_table self.symbol_table
.insert(format!("{}()", identifier.clone()), stmt.clone()); .insert(format!("{}()", identifier.clone()), stmt.clone());
0f64 0f64
@ -134,9 +139,16 @@ impl Visitor<f64, f64> for Interpreter {
} }
Expr::Literal(value) => value.parse().unwrap(), Expr::Literal(value) => value.parse().unwrap(),
Expr::Group(expr) => self.visit_expr(&expr), Expr::Group(expr) => self.visit_expr(&expr),
Expr::FnCall(identifier, expr) => { Expr::FnCall(identifier, expressions) => {
let x = self.visit_expr(&expr); let prelude_func = match expressions.len() {
if let Some(result) = self.prelude.call_unary_func(identifier, x) { 1 => {
let x = self.visit_expr(&expressions[0]);
self.prelude.call_unary_func(identifier, x)
}
_ => None,
};
if let Some(result) = prelude_func {
result result
} else { } else {
let stmt = self let stmt = self
@ -144,13 +156,24 @@ impl Visitor<f64, f64> for Interpreter {
.get(&format!("{}()", identifier)) .get(&format!("{}()", identifier))
.expect("Undefined function") .expect("Undefined function")
.clone(); .clone();
match stmt {
Stmt::FnDecl(_, argument, fn_body) => { if let Stmt::FnDecl(_, arguments, fn_body) = stmt {
self.visit_stmt(&Stmt::VarDecl(argument.clone(), expr.clone())); if arguments.len() != expressions.len() {
self.visit_expr(&*fn_body) panic!("Incorrect amount of arguments.");
} }
_ => panic!(),
// Initialise the arguments as their own variables.
for (i, argument) in arguments.iter().enumerate() {
self.visit_stmt(&Stmt::VarDecl(
argument.clone(),
Box::new(expressions[i].clone()),
));
}
return self.visit_expr(&*fn_body);
} }
panic!("Unexpected error.");
} }
} }
} }

View File

@ -5,17 +5,22 @@ pub enum TokenKind {
Unknown, Unknown,
Literal, Literal,
Identifier, Identifier,
Plus, Plus,
Minus, Minus,
Star, Star,
Slash, Slash,
Power, Power,
Equals, Equals,
Deg, Deg,
Rad, Rad,
Pipe, Pipe,
OpenParenthesis, OpenParenthesis,
ClosedParenthesis, ClosedParenthesis,
Comma,
EOF, EOF,
} }
@ -101,6 +106,10 @@ impl<'a> Lexer<'a> {
self.advance(); self.advance();
self.build(TokenKind::Equals, "") self.build(TokenKind::Equals, "")
} }
',' => {
self.advance();
self.build(TokenKind::Comma, "")
}
_ => { _ => {
if c.is_digit(10) { if c.is_digit(10) {
self.next_number_literal() self.next_number_literal()

View File

@ -5,7 +5,7 @@ use crate::lexer::{Token, TokenKind};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Stmt { pub enum Stmt {
VarDecl(String, Box<Expr>), VarDecl(String, Box<Expr>),
FnDecl(String, String, Box<Expr>), FnDecl(String, Vec<String>, Box<Expr>),
Expr(Box<Expr>), Expr(Box<Expr>),
} }
@ -16,7 +16,7 @@ pub enum Expr {
Unit(Box<Expr>, TokenKind), Unit(Box<Expr>, TokenKind),
Var(String), Var(String),
Group(Box<Expr>), Group(Box<Expr>),
FnCall(String, Box<Expr>), FnCall(String, Vec<Expr>),
Literal(String), Literal(String),
} }
@ -85,15 +85,23 @@ impl Parser {
self.advance(); self.advance();
let expr = self.parse_expr(); let expr = self.parse_expr();
match primary { // Use the "function call" expression that was parsed, and put its values into a function declaration statement instead.
Expr::FnCall(identifier, argument) => match *argument { if let Expr::FnCall(identifier, parameters) = primary {
Expr::Var(argument_identifier) => { let mut parameter_identifiers = Vec::new();
Stmt::FnDecl(identifier, argument_identifier, Box::new(expr))
// All the "arguments" are expected to be parsed as variables,
// since parameter definitions look the same as variable references.
// Extract these.
for parameter in parameters {
if let Expr::Var(parameter_identifier) = parameter {
parameter_identifiers.push(parameter_identifier);
} }
_ => panic!("Unexpected error."), }
},
_ => panic!("Unexpected error."), return Stmt::FnDecl(identifier, parameter_identifiers, Box::new(expr));
} }
panic!("Unexpected error.");
} else { } else {
// It is a function call, not a function declaration. // It is a function call, not a function declaration.
// Redo the parsing for this specific part. // Redo the parsing for this specific part.
@ -199,7 +207,7 @@ impl Parser {
let group_expr = Expr::Group(Box::new(self.parse_expr())); let group_expr = Expr::Group(Box::new(self.parse_expr()));
self.consume(TokenKind::Pipe); self.consume(TokenKind::Pipe);
Expr::FnCall(String::from("abs"), Box::new(group_expr)) Expr::FnCall(String::from("abs"), vec![group_expr])
} }
fn parse_identifier(&mut self) -> Expr { fn parse_identifier(&mut self) -> Expr {
@ -210,7 +218,7 @@ impl Parser {
let parameter = self.parse_expr(); let parameter = self.parse_expr();
self.consume(TokenKind::ClosedParenthesis); self.consume(TokenKind::ClosedParenthesis);
Expr::FnCall(identifier.value, Box::new(parameter)) Expr::FnCall(identifier.value, vec![parameter])
} else { } else {
Expr::Var(identifier.value) Expr::Var(identifier.value)
} }