keep working on vm
This commit is contained in:
parent
f2b342a807
commit
740b14f9da
|
@ -59,12 +59,9 @@ pub fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("{}", ast);
|
println!("{}", ast);
|
||||||
|
|
||||||
let mut ctx = Ctx {
|
let mut ctx = vec![("foo", Value::Number(42.0))];
|
||||||
local_names: vec!["foo"],
|
|
||||||
local_values: vec![Value::Keyword("foo")],
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = eval(ast, &mut ctx).unwrap();
|
let result = eval(&ast, &mut ctx).unwrap();
|
||||||
|
|
||||||
println!("{}", result);
|
println!("{}", result);
|
||||||
}
|
}
|
||||||
|
|
16
src/value.rs
16
src/value.rs
|
@ -19,18 +19,18 @@ pub struct Fn<'src> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value<'src> {
|
||||||
Nil,
|
Nil,
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Keyword(&'static str),
|
Keyword(&'src str),
|
||||||
String(&'static str),
|
String(&'src str),
|
||||||
// on the heap for now
|
// on the heap for now
|
||||||
Tuple(Rc<Vec<Self>>),
|
Tuple(Rc<Vec<Self>>),
|
||||||
// ref-counted, immutable, persistent
|
// ref-counted, immutable, persistent
|
||||||
List(Rc<Vector<Self>>),
|
List(Rc<Vector<Self>>),
|
||||||
// ref-counted, immutable, persistent
|
// ref-counted, immutable, persistent
|
||||||
Dict(Rc<HashMap<&'static str, Self>>),
|
Dict(Rc<HashMap<&'src str, Self>>),
|
||||||
// Fn(Rc<Fn<'src>>),
|
// Fn(Rc<Fn<'src>>),
|
||||||
// Set(HashSet<Self>),
|
// Set(HashSet<Self>),
|
||||||
// Sets are hard
|
// Sets are hard
|
||||||
|
@ -44,8 +44,8 @@ pub enum Value {
|
||||||
// pkgs, nses, tests
|
// pkgs, nses, tests
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Clone for Value {
|
impl<'src> Clone for Value<'src> {
|
||||||
fn clone(&self) -> Value {
|
fn clone(&self) -> Value<'src> {
|
||||||
match self {
|
match self {
|
||||||
Value::Nil => Value::Nil,
|
Value::Nil => Value::Nil,
|
||||||
Value::Boolean(b) => Value::Boolean(b.clone()),
|
Value::Boolean(b) => Value::Boolean(b.clone()),
|
||||||
|
@ -59,7 +59,7 @@ impl<'src> Clone for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> fmt::Display for Value {
|
impl<'src> fmt::Display for Value<'src> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::Nil => write!(f, "nil"),
|
Value::Nil => write!(f, "nil"),
|
||||||
|
@ -89,7 +89,7 @@ impl<'src> fmt::Display for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl<'src> Value<'src> {
|
||||||
pub fn bool(&self) -> bool {
|
pub fn bool(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::Nil | Value::Boolean(false) => false,
|
Value::Nil | Value::Boolean(false) => false,
|
||||||
|
|
53
src/vm.rs
53
src/vm.rs
|
@ -18,33 +18,31 @@ pub struct LudusError {
|
||||||
// the branches for Ast::Block and Ast::If
|
// the branches for Ast::Block and Ast::If
|
||||||
// to work with a mutable borrow of ctx
|
// to work with a mutable borrow of ctx
|
||||||
pub struct Ctx<'src> {
|
pub struct Ctx<'src> {
|
||||||
locals: Vec<(&'src str, Value)>,
|
pub locals: Vec<(&'src str, Value<'src>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ctx {
|
impl<'src> Ctx<'src> {
|
||||||
pub fn resolve(&self, name: &str) -> Value {
|
pub fn resolve(&self, name: &'src str) -> Value {
|
||||||
let len = self.local_names.len();
|
if let Some((_, val)) = self.locals.iter().rev().find(|(bound, _)| *bound == name) {
|
||||||
let mut value = Value::Nil;
|
val.clone()
|
||||||
for i in (0..len).rev() {
|
} else {
|
||||||
if self.local_names[i] == name {
|
unreachable!()
|
||||||
value = self.local_values[i].clone();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(&mut self, name: &'static str, value: Value) {
|
pub fn store(&mut self, name: &'src str, value: Value<'src>) {
|
||||||
self.local_names.push(name);
|
self.locals.push((name, value));
|
||||||
self.local_values.push(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval<'src>(ast: Ast<'src>, ctx: &mut Ctx) -> Result<Value, LudusError> {
|
pub fn eval<'src, 'a>(
|
||||||
|
ast: &Ast<'src>,
|
||||||
|
ctx: &'a mut Vec<(&'src str, Value<'src>)>,
|
||||||
|
) -> Result<Value<'src>, LudusError> {
|
||||||
match ast {
|
match ast {
|
||||||
Ast::Nil => Ok(Value::Nil),
|
Ast::Nil => Ok(Value::Nil),
|
||||||
Ast::Boolean(b) => Ok(Value::Boolean(b)),
|
Ast::Boolean(b) => Ok(Value::Boolean(*b)),
|
||||||
Ast::Number(n) => Ok(Value::Number(n)),
|
Ast::Number(n) => Ok(Value::Number(*n)),
|
||||||
Ast::Keyword(k) => Ok(Value::Keyword(k.clone())),
|
Ast::Keyword(k) => Ok(Value::Keyword(k.clone())),
|
||||||
Ast::String(s) => Ok(Value::String(s.clone())),
|
Ast::String(s) => Ok(Value::String(s.clone())),
|
||||||
Ast::Block(exprs) => {
|
Ast::Block(exprs) => {
|
||||||
|
@ -55,30 +53,37 @@ pub fn eval<'src>(ast: Ast<'src>, ctx: &mut Ctx) -> Result<Value, LudusError> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
Ast::If(cond, if_true, if_false) => {
|
Ast::If(cond, if_true, if_false) => {
|
||||||
let truthy = eval((*cond).0, ctx)?.bool();
|
let truthy = eval(&cond.0, ctx)?.bool();
|
||||||
if truthy {
|
if truthy {
|
||||||
let (if_true, _) = *if_true;
|
let (if_true, _) = *if_true;
|
||||||
eval(if_true, ctx)
|
eval(&if_true, ctx)
|
||||||
} else {
|
} else {
|
||||||
let (if_false, _) = *if_false;
|
let (if_false, _) = **if_false;
|
||||||
eval(if_false, ctx)
|
eval(&if_false, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ast::List(members) => {
|
Ast::List(members) => {
|
||||||
let mut vect = Vector::new();
|
let mut vect = Vector::new();
|
||||||
for member in members {
|
for member in members {
|
||||||
vect.push_back(eval(member.0, ctx)?)
|
vect.push_back(eval(&member.0, ctx)?)
|
||||||
}
|
}
|
||||||
Ok(Value::List(Rc::new(vect)))
|
Ok(Value::List(Rc::new(vect)))
|
||||||
}
|
}
|
||||||
Ast::Tuple(members) => {
|
Ast::Tuple(members) => {
|
||||||
let mut vect = Vec::new();
|
let mut vect = Vec::new();
|
||||||
for member in members {
|
for member in members {
|
||||||
vect.push(eval(member.0, ctx)?);
|
vect.push(eval(&member.0, ctx)?);
|
||||||
}
|
}
|
||||||
Ok(Value::Tuple(Rc::new(vect)))
|
Ok(Value::Tuple(Rc::new(vect)))
|
||||||
}
|
}
|
||||||
Ast::Word(w) => Ok(ctx.resolve(w)),
|
Ast::Word(w) => {
|
||||||
|
let val = if let Some((_, value)) = ctx.iter().rev().find(|(name, _)| w == name) {
|
||||||
|
value.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user