[fine] More tests and also comparisons
This commit is contained in:
parent
55749af917
commit
7fb88ef199
5 changed files with 101 additions and 4 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
18
fine/tests/expression/comparisons.fine
Normal file
18
fine/tests/expression/comparisons.fine
Normal 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)
|
||||
16
fine/tests/expression/worst_fib.fine
Normal file
16
fine/tests/expression/worst_fib.fine
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue