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:
2020-11-09 16:50:16 -08:00
parent 357aad5306
commit c6212f5597
5 changed files with 165 additions and 28 deletions

View File

@@ -1,13 +1,15 @@
# pow = fn (n, p) {
# if p == 0 {
# 1
# } else {
# n * pow(n, p - 1)
# }
# }
pow = fn (n, p) {
if p <= 0 {
return 1
} el {
return n * pow(n, p - 1)
}
}
kilo = pow(2, 10)
mega = pow(2, 20)
giga = pow(2, 30)
tera = pow(2, 40)
peta = pow(2, 50)
println(kilo)
println(mega)
println(giga)

View File

@@ -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)
})
});

View File

@@ -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);

View File

@@ -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__");

View File

@@ -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);