From ad2044b81d22477c8d56e77c508b128477553248 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 19 Apr 2025 13:46:56 +0300 Subject: [PATCH] WIP trait Eval --- src/twopass.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/src/twopass.rs b/src/twopass.rs index 9975875..83d6e16 100644 --- a/src/twopass.rs +++ b/src/twopass.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::{cell::RefCell, rc::Rc}; use crate::{ast, types}; @@ -241,6 +241,92 @@ pub fn build(code: &ast::Function) -> OpenFunction { OpenFunction(build_function(&BuildContext::new_toplevel(), &code)) } +#[derive(Debug, Clone)] +struct Variable(RefCell); + +impl Variable { + fn get(&self) -> types::Value { + self.0.borrow().clone() + } + + fn set(&self, value: types::Value) { + *self.0.borrow_mut() = value + } +} + +type VariableRef = Rc; + +struct RunContext { + args: Vec, + locals: Vec, + upvalues: Vec, +} + +impl RunContext { + fn var(&self, id: Ident) -> VariableRef { + Rc::clone(match id { + Ident::Upvalue(index) => self + .upvalues + .get(index) + .expect("upvalue index out of bounds"), + Ident::Local(index) => self.locals.get(index).expect("local index out of bounds"), + Ident::Argument(index) => self.args.get(index).expect("argument index out of bounds"), + }) + } +} + +trait Eval { + fn eval(&self, ctx: &RunContext) -> types::Value; +} + +impl Eval for ast::Constant { + fn eval(&self, _ctx: &RunContext) -> types::Value { + match self { + ast::Constant::Nil => None, + ast::Constant::Boolean(value) => Some(types::ValueInner::Boolean(*value)), + ast::Constant::Number(value) => Some(types::ValueInner::Number(*value)), + ast::Constant::String(value) => Some(types::ValueInner::String(value.clone())), + } + } +} + +impl Eval for Location { + fn eval(&self, ctx: &RunContext) -> types::Value { + match self { + Location::Variable { id } => todo!(), + Location::Field { table, index } => todo!(), + } + } +} + +impl Eval for Call { + fn eval(&self, ctx: &RunContext) -> types::Value { + let callee = self.callee.eval(ctx); + let args: Vec<_> = self.args.iter().map(|arg| arg.eval(ctx)).collect(); + let Some(types::ValueInner::Function(f)) = callee else { + panic!("attempt to call a non-function"); + }; + f.call(&args) + } +} + +impl Eval for Function { + fn eval(&self, ctx: &RunContext) -> types::Value { + todo!() + } +} + +impl Eval for Expression { + fn eval(&self, ctx: &RunContext) -> types::Value { + match self { + Expression::Constant(inner) => inner.eval(ctx), + Expression::Variable(inner) => inner.eval(ctx), + Expression::Call(inner) => inner.eval(ctx), + Expression::Function(inner) => inner.eval(ctx), + } + } +} + impl Function { fn call(&self, upvalues: &[types::Value], args: &[types::Value]) -> types::Value { assert_eq!(upvalues.len(), self.upvalues.len());