mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-06-25 20:21:44 +02:00
Separated match arms in the interpreter into their own functions.
This commit is contained in:
parent
e29299bdfe
commit
1a56ddac45
@ -63,103 +63,139 @@ impl Unit {
|
|||||||
impl<'a> Visitor<f64, f64> for Interpreter<'a> {
|
impl<'a> Visitor<f64, f64> for Interpreter<'a> {
|
||||||
fn visit_stmt(&mut self, stmt: &Stmt) -> f64 {
|
fn visit_stmt(&mut self, stmt: &Stmt) -> f64 {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::VarDecl(identifier, _) => {
|
Stmt::VarDecl(identifier, _) => self.eval_var_decl_stmt(stmt, identifier),
|
||||||
self.symbol_table.insert(&identifier, stmt.clone());
|
Stmt::FnDecl(_, _, _) => self.eval_fn_decl_stmt(),
|
||||||
0f64
|
Stmt::Expr(expr) => self.eval_expr_stmt(&expr),
|
||||||
}
|
|
||||||
Stmt::FnDecl(_, _, _) => 0f64, // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
|
||||||
Stmt::Expr(expr) => self.visit_expr(&expr),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &Expr) -> f64 {
|
fn visit_expr(&mut self, expr: &Expr) -> f64 {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Binary(left, op, right) => {
|
Expr::Binary(left, op, right) => self.eval_binary_expr(&left, op, &right),
|
||||||
let left = self.visit_expr(&left);
|
Expr::Unary(_, expr) => self.eval_unary_expr(expr),
|
||||||
let right = self.visit_expr(&right);
|
Expr::Unit(expr, kind) => self.eval_unit_expr(expr, kind),
|
||||||
|
Expr::Var(identifier) => self.eval_var_expr(identifier),
|
||||||
match op {
|
Expr::Literal(value) => self.eval_literal_expr(value),
|
||||||
TokenKind::Plus => left + right,
|
Expr::Group(expr) => self.eval_group_expr(&expr),
|
||||||
TokenKind::Minus => left - right,
|
|
||||||
TokenKind::Star => left * right,
|
|
||||||
TokenKind::Slash => left / right,
|
|
||||||
TokenKind::Power => left.powf(right),
|
|
||||||
_ => 0f64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::Unary(_, expr) => self.visit_expr(&expr).clone(),
|
|
||||||
Expr::Unit(expr, kind) => {
|
|
||||||
let x = self.visit_expr(&expr);
|
|
||||||
|
|
||||||
// Don't do any angle conversions if the defauly angle unit is the same as the unit kind
|
|
||||||
if (kind.compare(&TokenKind::Deg) || kind.compare(&TokenKind::Rad))
|
|
||||||
&& self.angle_unit.compare(&kind.to_unit())
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
TokenKind::Deg => x.to_radians(),
|
|
||||||
TokenKind::Rad => x.to_degrees(),
|
|
||||||
_ => panic!("Invalid unit."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::Var(identifier) => {
|
|
||||||
let value = self
|
|
||||||
.symbol_table
|
|
||||||
.get(identifier)
|
|
||||||
.expect("Undefined variable.")
|
|
||||||
.clone();
|
|
||||||
if let Stmt::VarDecl(_, expr) = value {
|
|
||||||
return self.visit_expr(&expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
panic!("Unknown error.");
|
|
||||||
}
|
|
||||||
Expr::Literal(value) => value.parse().unwrap(),
|
|
||||||
Expr::Group(expr) => self.visit_expr(&expr),
|
|
||||||
Expr::FnCall(identifier, expressions) => {
|
Expr::FnCall(identifier, expressions) => {
|
||||||
let prelude_func = match expressions.len() {
|
self.eval_fn_call_expr(identifier, expressions)
|
||||||
1 => {
|
|
||||||
let x = self.visit_expr(&expressions[0]);
|
|
||||||
prelude::call_unary_func(identifier, x, &self.angle_unit)
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
let x = self.visit_expr(&expressions[0]);
|
|
||||||
let y = self.visit_expr(&expressions[1]);
|
|
||||||
prelude::call_binary_func(identifier, x, y, &self.angle_unit)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(result) = prelude_func {
|
|
||||||
result
|
|
||||||
} else {
|
|
||||||
let stmt = self
|
|
||||||
.symbol_table
|
|
||||||
.get(&format!("{}()", identifier))
|
|
||||||
.expect("Undefined function")
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
if let Stmt::FnDecl(_, arguments, fn_body) = stmt {
|
|
||||||
if arguments.len() != expressions.len() {
|
|
||||||
panic!("Incorrect amount of arguments.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Interpreter<'a> {
|
||||||
|
fn eval_var_decl_stmt(&mut self, stmt: &Stmt, identifier: &str) -> f64 {
|
||||||
|
self.symbol_table.insert(&identifier, stmt.clone());
|
||||||
|
0f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_fn_decl_stmt(&mut self) -> f64 {
|
||||||
|
0f64 // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_expr_stmt(&mut self, expr: &Expr) -> f64 {
|
||||||
|
self.visit_expr(&expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Interpreter<'a> {
|
||||||
|
fn eval_binary_expr(&mut self, left: &Expr, op: &TokenKind, right: &Expr) -> f64 {
|
||||||
|
let left = self.visit_expr(&left);
|
||||||
|
let right = self.visit_expr(&right);
|
||||||
|
|
||||||
|
match op {
|
||||||
|
TokenKind::Plus => left + right,
|
||||||
|
TokenKind::Minus => left - right,
|
||||||
|
TokenKind::Star => left * right,
|
||||||
|
TokenKind::Slash => left / right,
|
||||||
|
TokenKind::Power => left.powf(right),
|
||||||
|
_ => 0f64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_unary_expr(&mut self, expr: &Expr) -> f64 {
|
||||||
|
self.visit_expr(&expr).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_unit_expr(&mut self, expr: &Expr, kind: &TokenKind) -> f64 {
|
||||||
|
let x = self.visit_expr(&expr);
|
||||||
|
|
||||||
|
// Don't do any angle conversions if the defauly angle unit is the same as the unit kind
|
||||||
|
if (kind.compare(&TokenKind::Deg) || kind.compare(&TokenKind::Rad))
|
||||||
|
&& self.angle_unit.compare(&kind.to_unit())
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
match kind {
|
||||||
|
TokenKind::Deg => x.to_radians(),
|
||||||
|
TokenKind::Rad => x.to_degrees(),
|
||||||
|
_ => panic!("Invalid unit."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_var_expr(&mut self, identifier: &str) -> f64 {
|
||||||
|
let value = self
|
||||||
|
.symbol_table
|
||||||
|
.get(identifier)
|
||||||
|
.expect("Undefined variable.")
|
||||||
|
.clone();
|
||||||
|
if let Stmt::VarDecl(_, expr) = value {
|
||||||
|
return self.visit_expr(&expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Unknown error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_literal_expr(&mut self, value: &str) -> f64 {
|
||||||
|
value.parse().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_group_expr(&mut self, expr: &Expr) -> f64 {
|
||||||
|
self.visit_expr(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_fn_call_expr(&mut self, identifier: &str, expressions: &Vec<Expr>) -> f64 {
|
||||||
|
let prelude_func = match expressions.len() {
|
||||||
|
1 => {
|
||||||
|
let x = self.visit_expr(&expressions[0]);
|
||||||
|
prelude::call_unary_func(identifier, x, &self.angle_unit)
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
let x = self.visit_expr(&expressions[0]);
|
||||||
|
let y = self.visit_expr(&expressions[1]);
|
||||||
|
prelude::call_binary_func(identifier, x, y, &self.angle_unit)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(result) = prelude_func {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stmt = self
|
||||||
|
.symbol_table
|
||||||
|
.get(&format!("{}()", identifier))
|
||||||
|
.expect("Undefined function")
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
if let Stmt::FnDecl(_, arguments, fn_body) = stmt {
|
||||||
|
if arguments.len() != expressions.len() {
|
||||||
|
panic!("Incorrect amount of arguments.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -50,17 +50,6 @@ impl TokenKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*impl Parser {
|
|
||||||
pub fn new() -> Parser {
|
|
||||||
Parser {
|
|
||||||
tokens: Vec::new(),
|
|
||||||
pos: 0,
|
|
||||||
symbol_table: SymbolTable::new(),
|
|
||||||
angle_unit: prelude::DEFAULT_ANGLE_UNIT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
impl ParserContext {
|
impl ParserContext {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ParserContext {
|
ParserContext {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user