mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-09 06:58:12 +01:00
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:
parent
94722ed27e
commit
6d67797565
@ -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, _) => {
|
||||||
|
// Initialise each of the arguments as their own variable.
|
||||||
|
for argument in arguments {
|
||||||
self.visit_stmt(&Stmt::VarDecl(
|
self.visit_stmt(&Stmt::VarDecl(
|
||||||
argument.clone(),
|
argument.clone(),
|
||||||
Box::new(Expr::Literal(String::from("0"))),
|
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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user