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:
@@ -1,13 +1,15 @@
|
|||||||
# pow = fn (n, p) {
|
pow = fn (n, p) {
|
||||||
# if p == 0 {
|
if p <= 0 {
|
||||||
# 1
|
return 1
|
||||||
# } else {
|
} el {
|
||||||
# n * pow(n, p - 1)
|
return n * pow(n, p - 1)
|
||||||
# }
|
}
|
||||||
# }
|
}
|
||||||
|
|
||||||
kilo = pow(2, 10)
|
kilo = pow(2, 10)
|
||||||
mega = pow(2, 20)
|
mega = pow(2, 20)
|
||||||
giga = pow(2, 30)
|
giga = pow(2, 30)
|
||||||
tera = pow(2, 40)
|
|
||||||
peta = pow(2, 50)
|
println(kilo)
|
||||||
|
println(mega)
|
||||||
|
println(giga)
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ impl Int {
|
|||||||
DIV_OP_NAME.sym => Method::new_obj(obj_ref.clone(), INT_DIV_METH.clone()),
|
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()),
|
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()),
|
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)
|
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_ne, NE_OP_NAME);
|
||||||
obj_attr!(get_lt, LT_OP_NAME);
|
obj_attr!(get_lt, LT_OP_NAME);
|
||||||
obj_attr!(get_gt, GT_OP_NAME);
|
obj_attr!(get_gt, GT_OP_NAME);
|
||||||
obj_attr!(get_le, LT_EQ_OP_NAME);
|
obj_attr!(get_le, LE_OP_NAME);
|
||||||
obj_attr!(get_ge, GT_EQ_OP_NAME);
|
obj_attr!(get_ge, GE_OP_NAME);
|
||||||
obj_attr!(get_plus, PLUS_OP_NAME);
|
obj_attr!(get_plus, PLUS_OP_NAME);
|
||||||
obj_attr!(get_minus, MINUS_OP_NAME);
|
obj_attr!(get_minus, MINUS_OP_NAME);
|
||||||
obj_attr!(get_mul, TIMES_OP_NAME);
|
obj_attr!(get_mul, TIMES_OP_NAME);
|
||||||
|
|||||||
@@ -48,17 +48,9 @@ name!(STR_MEMBER_NAME, "__str__");
|
|||||||
name!(INT_MEMBER_NAME, "__int__");
|
name!(INT_MEMBER_NAME, "__int__");
|
||||||
name!(BOOL_MEMBER_NAME, "__bool__");
|
name!(BOOL_MEMBER_NAME, "__bool__");
|
||||||
|
|
||||||
//
|
|
||||||
// Predefined VM-aware symbols
|
|
||||||
//
|
|
||||||
//name!(SCOPE_NAME, "__scope__");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Builtin functions
|
// 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!(PRINTLN_BUILTIN_NAME, "println");
|
||||||
name!(PRINT_BUILTIN_NAME, "print");
|
name!(PRINT_BUILTIN_NAME, "print");
|
||||||
|
|
||||||
@@ -71,9 +63,9 @@ name!(NIL_NAME, "nil");
|
|||||||
name!(EQ_OP_NAME, "__eq__");
|
name!(EQ_OP_NAME, "__eq__");
|
||||||
name!(NE_OP_NAME, "__ne__");
|
name!(NE_OP_NAME, "__ne__");
|
||||||
name!(LT_OP_NAME, "__lt__");
|
name!(LT_OP_NAME, "__lt__");
|
||||||
|
name!(LE_OP_NAME, "__le__");
|
||||||
name!(GT_OP_NAME, "__gt__");
|
name!(GT_OP_NAME, "__gt__");
|
||||||
name!(LT_EQ_OP_NAME, "__le__");
|
name!(GE_OP_NAME, "__ge__");
|
||||||
name!(GT_EQ_OP_NAME, "__ge__");
|
|
||||||
name!(PLUS_OP_NAME, "__add__");
|
name!(PLUS_OP_NAME, "__add__");
|
||||||
name!(MINUS_OP_NAME, "__sub__");
|
name!(MINUS_OP_NAME, "__sub__");
|
||||||
name!(TIMES_OP_NAME, "__mul__");
|
name!(TIMES_OP_NAME, "__mul__");
|
||||||
|
|||||||
@@ -337,13 +337,76 @@ impl<'c> Vm<'c> {
|
|||||||
};
|
};
|
||||||
signal = Some(Signal::Call(fun, vec![rhs]));
|
signal = Some(Signal::Call(fun, vec![rhs]));
|
||||||
}
|
}
|
||||||
Inst::BinNeq => todo!(),
|
Inst::BinNeq => {
|
||||||
Inst::BinLt => todo!(),
|
let rhs = self.pop().unwrap();
|
||||||
Inst::BinLe => todo!(),
|
let lhs = self.pop().unwrap();
|
||||||
Inst::BinGt => todo!(),
|
let fun = {
|
||||||
Inst::BinGe => todo!(),
|
read_obj!(let lhs = lhs);
|
||||||
Inst::BinAnd => todo!(),
|
lhs.get_ne()
|
||||||
Inst::BinOr => todo!(),
|
.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);
|
self.set_pc(next_pc);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user