use Value
This commit is contained in:
parent
61c42ae790
commit
8559220aa3
|
|
@ -1,6 +1,9 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{ast, types};
|
use crate::{
|
||||||
|
ast,
|
||||||
|
types::{self, Nil, Value},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct OpenFunction(Function);
|
pub struct OpenFunction(Function);
|
||||||
|
|
@ -273,14 +276,14 @@ pub fn build(code: &ast::Function) -> OpenFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Variable(RefCell<types::Value>);
|
struct Variable(RefCell<Value>);
|
||||||
|
|
||||||
impl Variable {
|
impl Variable {
|
||||||
fn get(&self) -> types::Value {
|
fn get(&self) -> Value {
|
||||||
self.0.borrow().clone()
|
self.0.borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&self, value: types::Value) {
|
fn set(&self, value: Value) {
|
||||||
*self.0.borrow_mut() = value
|
*self.0.borrow_mut() = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,28 +310,28 @@ impl RunContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Eval {
|
trait Eval {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value;
|
fn eval(&self, ctx: &RunContext) -> Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for ast::Constant {
|
impl Eval for ast::Constant {
|
||||||
fn eval(&self, _ctx: &RunContext) -> types::Value {
|
fn eval(&self, _ctx: &RunContext) -> Value {
|
||||||
match self {
|
match self {
|
||||||
ast::Constant::Nil => types::Value::Nil,
|
ast::Constant::Nil => Nil,
|
||||||
ast::Constant::Boolean(value) => types::Value::Boolean(*value),
|
ast::Constant::Boolean(value) => Value::Boolean(*value),
|
||||||
ast::Constant::Number(value) => types::Value::Number(*value),
|
ast::Constant::Number(value) => Value::Number(*value),
|
||||||
ast::Constant::String(value) => types::Value::String(value.clone()),
|
ast::Constant::String(value) => Value::String(value.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Location {
|
impl Eval for Location {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
match self {
|
match self {
|
||||||
Location::Variable { id } => ctx.var(*id).get(),
|
Location::Variable { id } => ctx.var(*id).get(),
|
||||||
Location::Field { table, index } => {
|
Location::Field { table, index } => {
|
||||||
let table = table.eval(ctx);
|
let table = table.eval(ctx);
|
||||||
let index = index.eval(ctx);
|
let index = index.eval(ctx);
|
||||||
let types::Value::Table(table) = table else {
|
let Value::Table(table) = table else {
|
||||||
panic!("attempt to index a non-table");
|
panic!("attempt to index a non-table");
|
||||||
};
|
};
|
||||||
table.get(index)
|
table.get(index)
|
||||||
|
|
@ -338,10 +341,10 @@ impl Eval for Location {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Call {
|
impl Eval for Call {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
let callee = self.callee.eval(ctx);
|
let callee = self.callee.eval(ctx);
|
||||||
let args: Vec<_> = self.args.iter().map(|arg| arg.eval(ctx)).collect();
|
let args: Vec<_> = self.args.iter().map(|arg| arg.eval(ctx)).collect();
|
||||||
let types::Value::Function(f) = callee else {
|
let Value::Function(f) = callee else {
|
||||||
panic!("attempt to call a non-function");
|
panic!("attempt to call a non-function");
|
||||||
};
|
};
|
||||||
f.call(&args)
|
f.call(&args)
|
||||||
|
|
@ -349,7 +352,7 @@ impl Eval for Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Function {
|
impl Eval for Function {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
let upvalues: Vec<_> = self
|
let upvalues: Vec<_> = self
|
||||||
.upvalues
|
.upvalues
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -361,7 +364,7 @@ impl Eval for Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Table {
|
impl Eval for Table {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
let table = types::Table::default();
|
let table = types::Table::default();
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
let key = field.key.eval(ctx);
|
let key = field.key.eval(ctx);
|
||||||
|
|
@ -373,7 +376,7 @@ impl Eval for Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Expression {
|
impl Eval for Expression {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
match self {
|
match self {
|
||||||
Expression::Constant(inner) => inner.eval(ctx),
|
Expression::Constant(inner) => inner.eval(ctx),
|
||||||
Expression::Variable(inner) => inner.eval(ctx),
|
Expression::Variable(inner) => inner.eval(ctx),
|
||||||
|
|
@ -385,7 +388,7 @@ impl Eval for Expression {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for Statement {
|
impl Eval for Statement {
|
||||||
fn eval(&self, ctx: &RunContext) -> types::Value {
|
fn eval(&self, ctx: &RunContext) -> Value {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assign { target, source } => {
|
Statement::Assign { target, source } => {
|
||||||
let source = source.eval(ctx);
|
let source = source.eval(ctx);
|
||||||
|
|
@ -394,7 +397,7 @@ impl Eval for Statement {
|
||||||
Location::Field { table, index } => {
|
Location::Field { table, index } => {
|
||||||
let table = table.eval(ctx);
|
let table = table.eval(ctx);
|
||||||
let index = index.eval(ctx);
|
let index = index.eval(ctx);
|
||||||
let types::Value::Table(table) = table else {
|
let Value::Table(table) = table else {
|
||||||
panic!("attempt to index a non-table");
|
panic!("attempt to index a non-table");
|
||||||
};
|
};
|
||||||
table.set(index, source)
|
table.set(index, source)
|
||||||
|
|
@ -405,23 +408,21 @@ impl Eval for Statement {
|
||||||
call.eval(ctx);
|
call.eval(ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
types::Value::Nil
|
Nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_var(value: &types::Value) -> VariableRef {
|
fn new_var(value: &Value) -> VariableRef {
|
||||||
Rc::new(Variable(RefCell::new(value.clone())))
|
Rc::new(Variable(RefCell::new(value.clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
fn call(&self, upvalues: &[VariableRef], args: &[types::Value]) -> types::Value {
|
fn call(&self, upvalues: &[VariableRef], args: &[Value]) -> Value {
|
||||||
assert_eq!(upvalues.len(), self.upvalues.len());
|
assert_eq!(upvalues.len(), self.upvalues.len());
|
||||||
assert_eq!(args.len(), self.args.len());
|
assert_eq!(args.len(), self.args.len());
|
||||||
let ctx = RunContext {
|
let ctx = RunContext {
|
||||||
args: args.iter().map(new_var).collect(),
|
args: args.iter().map(new_var).collect(),
|
||||||
locals: (0..self.locals.len())
|
locals: (0..self.locals.len()).map(|_| new_var(&Nil)).collect(),
|
||||||
.map(|_| new_var(&types::Value::Nil))
|
|
||||||
.collect(),
|
|
||||||
upvalues: upvalues.to_vec(),
|
upvalues: upvalues.to_vec(),
|
||||||
};
|
};
|
||||||
for statement in &self.body {
|
for statement in &self.body {
|
||||||
|
|
@ -432,7 +433,7 @@ impl Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpenFunction {
|
impl OpenFunction {
|
||||||
pub fn call(&self, env: types::Value, args: &[types::Value]) -> types::Value {
|
pub fn call(&self, env: Value, args: &[Value]) -> Value {
|
||||||
match self.0.upvalues.as_slice() {
|
match self.0.upvalues.as_slice() {
|
||||||
[] => self.0.call(&[], args),
|
[] => self.0.call(&[], args),
|
||||||
[up] if up.0 == "_ENV" => self.0.call(&[new_var(&env)], args),
|
[up] if up.0 == "_ENV" => self.0.call(&[new_var(&env)], args),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user