diff --git a/src/ast.rs b/src/ast.rs index b65f341..5cc03da 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -6,10 +6,7 @@ pub enum Statement { target: Location, source: Box, }, - Call { - callee: Ident, - args: Vec, - }, + Call(Call), Local { name: Ident, init: Option>, @@ -31,13 +28,16 @@ pub enum Location { pub enum Expression { Constant(Constant), Variable(Location), - Call { - callee: Ident, - args: Vec, - }, + Call(Call), Function(Function), } +#[derive(Debug, Clone)] +pub struct Call { + pub callee: Ident, + pub args: Vec, +} + #[derive(Debug, Clone, Default)] pub struct Function { pub name: Option, diff --git a/src/run.rs b/src/run.rs index 9061275..072dbd5 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, fmt::Debug, rc::Rc}; use crate::{ - ast::{Constant, Expression, Location, Statement}, + ast::{Call, Constant, Expression, Location, Statement}, types::{Value, ValueInner}, }; @@ -91,18 +91,23 @@ impl Eval for Location { } } +impl Eval for Call { + fn eval(&self, scope: &mut Scope) -> Value { + let Self { callee, args } = self; + let Some(function) = scope.functions.get(callee.as_str()).cloned() else { + panic!("attempt to call non-existent function {callee}") + }; + let args = args.iter().map(|arg| arg.eval(scope)).collect(); + (function.inner)(scope, args) + } +} + impl Eval for Expression { fn eval(&self, scope: &mut Scope) -> Value { match self { Expression::Constant(inner) => inner.eval(scope), Expression::Variable(inner) => inner.eval(scope), - Expression::Call { callee, args } => { - let Some(function) = scope.functions.get(callee.as_str()).cloned() else { - panic!("attempt to call non-existent function {callee}") - }; - let args = args.iter().map(|arg| arg.eval(scope)).collect(); - (function.inner)(scope, args) - } + Expression::Call(inner) => inner.eval(scope), Expression::Function { .. } => todo!(), } } @@ -134,12 +139,8 @@ impl Exec for Statement { } }; } - Statement::Call { callee, args } => { - Expression::Call { - callee: callee.clone(), - args: args.clone(), - } - .eval(scope); + Statement::Call(call) => { + call.eval(scope); } Statement::Local { .. } => todo!(), } diff --git a/src/twopass.rs b/src/twopass.rs index 8c5a6c8..9d7e093 100644 --- a/src/twopass.rs +++ b/src/twopass.rs @@ -149,7 +149,7 @@ fn build_in_scope(parent: &BuildContext<'_>, code: &ast::Function) -> Function { source: Box::new(build_expression(&scope, source)), }); } - ast::Statement::Call { callee, args } => { + ast::Statement::Call(ast::Call { callee, args }) => { body.push(Statement::Call(Call { callee: Box::new(build_expression( &scope,