Finish up old example that shows off basic expressions and funcalls
The VM now supports the various int comparison methods. An example of a "pow" method is given to show off recursion, which means we're now TURING COMPLETE! Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -36,6 +36,10 @@ impl Int {
|
||||
DIV_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_DIV_METH.clone()),
|
||||
EQ_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_EQ_METH.clone()),
|
||||
NE_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_NE_METH.clone()),
|
||||
LT_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_LT_METH.clone()),
|
||||
LE_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_LE_METH.clone()),
|
||||
GT_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_GT_METH.clone()),
|
||||
GE_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_GE_METH.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,3 +214,79 @@ static INT_NE_METH: Lazy<NativeFunRef> = Lazy::new(|| {
|
||||
Ok(crate::vm::signal::Signal::Return)
|
||||
})
|
||||
});
|
||||
|
||||
/// Int.__lt__(self, Int) impl
|
||||
static INT_LT_METH: Lazy<NativeFunRef> = Lazy::new(|| {
|
||||
NativeFun::new_obj(2, |_callee, vm, args| {
|
||||
read_obj_downcast!(let lhs: Option<&Int> = &args[0]);
|
||||
let lhs = lhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for LHS".to_string(),
|
||||
})?;
|
||||
|
||||
read_obj_downcast!(let rhs: Option<&Int> = &args[1]);
|
||||
let rhs = rhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for RHS".to_string(),
|
||||
})?;
|
||||
|
||||
let result = lhs.value < rhs.value;
|
||||
vm.push(BoolRef::from(result));
|
||||
Ok(crate::vm::signal::Signal::Return)
|
||||
})
|
||||
});
|
||||
|
||||
/// Int.__le__(self, Int) impl
|
||||
static INT_LE_METH: Lazy<NativeFunRef> = Lazy::new(|| {
|
||||
NativeFun::new_obj(2, |_callee, vm, args| {
|
||||
read_obj_downcast!(let lhs: Option<&Int> = &args[0]);
|
||||
let lhs = lhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for LHS".to_string(),
|
||||
})?;
|
||||
|
||||
read_obj_downcast!(let rhs: Option<&Int> = &args[1]);
|
||||
let rhs = rhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for RHS".to_string(),
|
||||
})?;
|
||||
|
||||
let result = lhs.value <= rhs.value;
|
||||
vm.push(BoolRef::from(result));
|
||||
Ok(crate::vm::signal::Signal::Return)
|
||||
})
|
||||
});
|
||||
|
||||
/// Int.__gt__(self, Int) impl
|
||||
static INT_GT_METH: Lazy<NativeFunRef> = Lazy::new(|| {
|
||||
NativeFun::new_obj(2, |_callee, vm, args| {
|
||||
read_obj_downcast!(let lhs: Option<&Int> = &args[0]);
|
||||
let lhs = lhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for LHS".to_string(),
|
||||
})?;
|
||||
|
||||
read_obj_downcast!(let rhs: Option<&Int> = &args[1]);
|
||||
let rhs = rhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for RHS".to_string(),
|
||||
})?;
|
||||
|
||||
let result = lhs.value > rhs.value;
|
||||
vm.push(BoolRef::from(result));
|
||||
Ok(crate::vm::signal::Signal::Return)
|
||||
})
|
||||
});
|
||||
|
||||
/// Int.__ge__(self, Int) impl
|
||||
static INT_GE_METH: Lazy<NativeFunRef> = Lazy::new(|| {
|
||||
NativeFun::new_obj(2, |_callee, vm, args| {
|
||||
read_obj_downcast!(let lhs: Option<&Int> = &args[0]);
|
||||
let lhs = lhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for LHS".to_string(),
|
||||
})?;
|
||||
|
||||
read_obj_downcast!(let rhs: Option<&Int> = &args[1]);
|
||||
let rhs = rhs.ok_or_else(|| Error::ValueError {
|
||||
error: "expected int for RHS".to_string(),
|
||||
})?;
|
||||
|
||||
let result = lhs.value >= rhs.value;
|
||||
vm.push(BoolRef::from(result));
|
||||
Ok(crate::vm::signal::Signal::Return)
|
||||
})
|
||||
});
|
||||
|
||||
@@ -72,8 +72,8 @@ pub trait Obj: Scan + GcDrop + Debug {
|
||||
obj_attr!(get_ne, NE_OP_NAME);
|
||||
obj_attr!(get_lt, LT_OP_NAME);
|
||||
obj_attr!(get_gt, GT_OP_NAME);
|
||||
obj_attr!(get_le, LT_EQ_OP_NAME);
|
||||
obj_attr!(get_ge, GT_EQ_OP_NAME);
|
||||
obj_attr!(get_le, LE_OP_NAME);
|
||||
obj_attr!(get_ge, GE_OP_NAME);
|
||||
obj_attr!(get_plus, PLUS_OP_NAME);
|
||||
obj_attr!(get_minus, MINUS_OP_NAME);
|
||||
obj_attr!(get_mul, TIMES_OP_NAME);
|
||||
|
||||
@@ -48,17 +48,9 @@ name!(STR_MEMBER_NAME, "__str__");
|
||||
name!(INT_MEMBER_NAME, "__int__");
|
||||
name!(BOOL_MEMBER_NAME, "__bool__");
|
||||
|
||||
//
|
||||
// Predefined VM-aware symbols
|
||||
//
|
||||
//name!(SCOPE_NAME, "__scope__");
|
||||
|
||||
//
|
||||
// Builtin functions
|
||||
//
|
||||
//name!(REPR_FUN_NAME, REPR_FUN_SYM, "repr");
|
||||
//name!(GET_LOCAL_FUN_NAME, GET_LOCAL_FUN_SYM, "get_local");
|
||||
//name!(SET_LOCAL_FUN_NAME, SET_LOCAL_FUN_SYM, "set_local");
|
||||
name!(PRINTLN_BUILTIN_NAME, "println");
|
||||
name!(PRINT_BUILTIN_NAME, "print");
|
||||
|
||||
@@ -71,9 +63,9 @@ name!(NIL_NAME, "nil");
|
||||
name!(EQ_OP_NAME, "__eq__");
|
||||
name!(NE_OP_NAME, "__ne__");
|
||||
name!(LT_OP_NAME, "__lt__");
|
||||
name!(LE_OP_NAME, "__le__");
|
||||
name!(GT_OP_NAME, "__gt__");
|
||||
name!(LT_EQ_OP_NAME, "__le__");
|
||||
name!(GT_EQ_OP_NAME, "__ge__");
|
||||
name!(GE_OP_NAME, "__ge__");
|
||||
name!(PLUS_OP_NAME, "__add__");
|
||||
name!(MINUS_OP_NAME, "__sub__");
|
||||
name!(TIMES_OP_NAME, "__mul__");
|
||||
|
||||
@@ -337,13 +337,76 @@ impl<'c> Vm<'c> {
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinNeq => todo!(),
|
||||
Inst::BinLt => todo!(),
|
||||
Inst::BinLe => todo!(),
|
||||
Inst::BinGt => todo!(),
|
||||
Inst::BinGe => todo!(),
|
||||
Inst::BinAnd => todo!(),
|
||||
Inst::BinOr => todo!(),
|
||||
Inst::BinNeq => {
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_ne()
|
||||
.expect("TODO: throw an error for missing __ne__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinLt => {
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_lt()
|
||||
.expect("TODO: throw an error for missing __lt__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinLe => {
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_le()
|
||||
.expect("TODO: throw an error for missing __le__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinGt => {
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_gt()
|
||||
.expect("TODO: throw an error for missing __gt__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinGe => {
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_ge()
|
||||
.expect("TODO: throw an error for missing __ge__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}
|
||||
Inst::BinAnd => todo!(), /*{
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_and()
|
||||
.expect("TODO: throw an error for missing __and__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}*/
|
||||
Inst::BinOr => todo!(), /*{
|
||||
let rhs = self.pop().unwrap();
|
||||
let lhs = self.pop().unwrap();
|
||||
let fun = {
|
||||
read_obj!(let lhs = lhs);
|
||||
lhs.get_or()
|
||||
.expect("TODO: throw an error for missing __or__ attr")
|
||||
};
|
||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||
}*/
|
||||
}
|
||||
self.set_pc(next_pc);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user