[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.
|
LoadExternFunction(usize), // NOTE: FUNKY, might want to indirect this index.
|
||||||
Call(usize),
|
Call(usize),
|
||||||
Return,
|
Return,
|
||||||
|
StringAdd,
|
||||||
|
CompareBool,
|
||||||
|
CompareString,
|
||||||
|
CompareFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Export {
|
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 {
|
match tr.nth_token(1)?.kind {
|
||||||
TokenKind::Plus => {
|
TokenKind::Plus => {
|
||||||
compile_expression(c, tr.nth_tree(2)?);
|
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 => {
|
TokenKind::Minus => {
|
||||||
compile_expression(c, tr.nth_tree(2)?);
|
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));
|
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"),
|
_ => ice!(c, t, "Unsupported binary expression"),
|
||||||
}
|
}
|
||||||
OK
|
OK
|
||||||
|
|
|
||||||
|
|
@ -723,6 +723,11 @@ impl<'a> Semantics<'a> {
|
||||||
|
|
||||||
(TokenKind::And | TokenKind::Or, Type::Bool, Type::Bool) => Some(Type::Bool),
|
(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.
|
// This is dumb and should be punished, probably.
|
||||||
(_, _, Type::Unreachable) => {
|
(_, _, Type::Unreachable) => {
|
||||||
self.report_error(
|
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) {
|
fn push_value(&mut self, v: StackValue) {
|
||||||
self.stack.push(v)
|
self.stack.push(v)
|
||||||
}
|
}
|
||||||
|
|
@ -237,10 +244,10 @@ fn eval_one(
|
||||||
Instruction::FloatDivide => {
|
Instruction::FloatDivide => {
|
||||||
let x = f.pop_float()?;
|
let x = f.pop_float()?;
|
||||||
let y = f.pop_float()?;
|
let y = f.pop_float()?;
|
||||||
if y == 0. {
|
if x == 0. {
|
||||||
return Err(VMErrorCode::DivideByZero);
|
return Err(VMErrorCode::DivideByZero);
|
||||||
}
|
}
|
||||||
f.push_float(x / y);
|
f.push_float(y / x);
|
||||||
}
|
}
|
||||||
Instruction::FloatMultiply => {
|
Instruction::FloatMultiply => {
|
||||||
let x = f.pop_float()?;
|
let x = f.pop_float()?;
|
||||||
|
|
@ -250,7 +257,7 @@ fn eval_one(
|
||||||
Instruction::FloatSubtract => {
|
Instruction::FloatSubtract => {
|
||||||
let x = f.pop_float()?;
|
let x = f.pop_float()?;
|
||||||
let y = f.pop_float()?;
|
let y = f.pop_float()?;
|
||||||
f.push_float(x - y);
|
f.push_float(y - x);
|
||||||
}
|
}
|
||||||
Instruction::Jump(i) => {
|
Instruction::Jump(i) => {
|
||||||
*index = i;
|
*index = i;
|
||||||
|
|
@ -335,6 +342,30 @@ fn eval_one(
|
||||||
}
|
}
|
||||||
None => return Ok(Flow::Break),
|
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)
|
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