WIP trait Eval

This commit is contained in:
numzero 2025-04-19 13:46:56 +03:00
parent f3ae2b8461
commit ad2044b81d

View File

@ -1,4 +1,4 @@
use std::cell::RefCell; use std::{cell::RefCell, rc::Rc};
use crate::{ast, types}; use crate::{ast, types};
@ -241,6 +241,92 @@ pub fn build(code: &ast::Function) -> OpenFunction {
OpenFunction(build_function(&BuildContext::new_toplevel(), &code)) OpenFunction(build_function(&BuildContext::new_toplevel(), &code))
} }
#[derive(Debug, Clone)]
struct Variable(RefCell<types::Value>);
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<Variable>;
struct RunContext {
args: Vec<VariableRef>,
locals: Vec<VariableRef>,
upvalues: Vec<VariableRef>,
}
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 { impl Function {
fn call(&self, upvalues: &[types::Value], args: &[types::Value]) -> types::Value { fn call(&self, upvalues: &[types::Value], args: &[types::Value]) -> types::Value {
assert_eq!(upvalues.len(), self.upvalues.len()); assert_eq!(upvalues.len(), self.upvalues.len());