[fine] More tests and also comparisons

This commit is contained in:
John Doty 2024-01-15 09:43:56 -08:00
parent 55749af917
commit 7fb88ef199
5 changed files with 101 additions and 4 deletions

View file

@ -36,6 +36,10 @@ pub enum Instruction {
LoadExternFunction(usize), // NOTE: FUNKY, might want to indirect this index.
Call(usize),
Return,
StringAdd,
CompareBool,
CompareString,
CompareFloat,
}
pub enum Export {
@ -366,7 +370,11 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
match tr.nth_token(1)?.kind {
TokenKind::Plus => {
compile_expression(c, tr.nth_tree(2)?);
c.push(Instruction::FloatAdd);
c.push(match c.semantics.type_of(t) {
Type::F64 => Instruction::FloatAdd,
Type::String => Instruction::StringAdd,
_ => Instruction::Panic,
});
}
TokenKind::Minus => {
compile_expression(c, tr.nth_tree(2)?);
@ -404,6 +412,25 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
c.patch(jump_end_index, |i| Instruction::Jump(i));
}
TokenKind::EqualEqual => {
let arg_tree = tr.nth_tree(2)?;
let arg_type = c.semantics.type_of(arg_tree);
compile_expression(c, tr.nth_tree(2)?);
if arg_type.compatible_with(&Type::Nothing) {
c.push(Instruction::Discard);
c.push(Instruction::Discard);
c.push(Instruction::PushTrue);
} else {
c.push(match arg_type {
Type::F64 => Instruction::CompareFloat,
Type::String => Instruction::CompareString,
Type::Bool => Instruction::CompareBool, // ?
_ => Instruction::Panic,
});
}
}
_ => ice!(c, t, "Unsupported binary expression"),
}
OK

View file

@ -723,6 +723,11 @@ impl<'a> Semantics<'a> {
(TokenKind::And | TokenKind::Or, Type::Bool, Type::Bool) => Some(Type::Bool),
(TokenKind::EqualEqual, Type::F64, Type::F64) => Some(Type::Bool),
(TokenKind::EqualEqual, Type::String, Type::String) => Some(Type::Bool),
(TokenKind::EqualEqual, Type::Bool, Type::Bool) => Some(Type::Bool),
(TokenKind::EqualEqual, Type::Nothing, Type::Nothing) => Some(Type::Bool),
// This is dumb and should be punished, probably.
(_, _, Type::Unreachable) => {
self.report_error(

View file

@ -95,6 +95,13 @@ impl Frame {
}
}
fn pop_string(&mut self) -> Result<Rc<str>> {
match self.pop_value()? {
StackValue::String(v) => Ok(v),
v => Err(VMErrorCode::StackTypeMismatch(v, Type::String)),
}
}
fn push_value(&mut self, v: StackValue) {
self.stack.push(v)
}
@ -237,10 +244,10 @@ fn eval_one(
Instruction::FloatDivide => {
let x = f.pop_float()?;
let y = f.pop_float()?;
if y == 0. {
if x == 0. {
return Err(VMErrorCode::DivideByZero);
}
f.push_float(x / y);
f.push_float(y / x);
}
Instruction::FloatMultiply => {
let x = f.pop_float()?;
@ -250,7 +257,7 @@ fn eval_one(
Instruction::FloatSubtract => {
let x = f.pop_float()?;
let y = f.pop_float()?;
f.push_float(x - y);
f.push_float(y - x);
}
Instruction::Jump(i) => {
*index = i;
@ -335,6 +342,30 @@ fn eval_one(
}
None => return Ok(Flow::Break),
},
Instruction::StringAdd => {
let x = f.pop_string()?;
let y = f.pop_string()?;
let mut new_string = x.to_string();
new_string.push_str(&y);
f.push_string(new_string.into());
}
Instruction::CompareBool => {
let x = f.pop_bool()?;
let y = f.pop_bool()?;
f.push_bool(x == y);
}
Instruction::CompareFloat => {
let x = f.pop_float()?;
let y = f.pop_float()?;
f.push_bool(x == y);
}
Instruction::CompareString => {
let x = f.pop_string()?;
let y = f.pop_string()?;
f.push_bool(x == y);
}
}
Ok(Flow::Continue)

View file

@ -0,0 +1,18 @@
fun is_hello(x:string) -> bool {
x == "hello"
}
fun is_23(x:f64) -> bool {
x == 23.0
}
fun is_false(x:bool) -> bool {
x == false
}
fun test() -> bool {
is_hello("hello") and is_23(23) and is_false(false)
}
// @no-errors
// @eval: Bool(true)

View file

@ -0,0 +1,16 @@
fun worst_fib(n: f64) -> f64 {
if n == 0 {
0
} else if n == 1 {
1
} else {
worst_fib(n-2) + worst_fib(n-1)
}
}
fun test() -> f64 {
worst_fib(10)
}
// @no-errors
// @eval: Float(55.0)