Clean up
This commit is contained in:
parent
f486d87976
commit
1d26b0b418
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "dust-lang"
|
||||
description = "Data-Oriented Programming Language"
|
||||
description = "General purpose programming language"
|
||||
version = "0.3.92"
|
||||
repository = "https://git.jeffa.io/jeff/dust.git"
|
||||
edition = "2021"
|
||||
|
@ -152,51 +152,3 @@ impl AbstractTree for Assignment {
|
||||
Ok(Type::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, Error, List, Type, Value};
|
||||
|
||||
#[test]
|
||||
fn simple_assignment() {
|
||||
let test = interpret("x = 1 x").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(1), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_assignment_with_type() {
|
||||
let test = interpret("x <int> = 1 x").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(1), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_add_assign() {
|
||||
let test = interpret(
|
||||
"
|
||||
x <[int]> = []
|
||||
x += 1
|
||||
x
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::List(List::with_items(vec![Value::Integer(1)])), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_add_wrong_type() {
|
||||
let result = interpret(
|
||||
"
|
||||
x <[str]> = []
|
||||
x += 1
|
||||
",
|
||||
);
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::String,
|
||||
actual: Type::Integer
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -162,41 +162,3 @@ impl AbstractTree for FunctionCall {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, Value};
|
||||
|
||||
#[test]
|
||||
fn evaluate_function_call() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
foobar = (message <str>) -> <str> { message }
|
||||
foobar('Hiya')
|
||||
",
|
||||
),
|
||||
Ok(Value::String("Hiya".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_callback() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
foobar = (cb <() -> str>) <str> {
|
||||
cb()
|
||||
}
|
||||
foobar(() <str> { 'Hiya' })
|
||||
",
|
||||
),
|
||||
Ok(Value::String("Hiya".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_built_in_function_call() {
|
||||
assert_eq!(interpret("output('Hiya')"), Ok(Value::Option(None)));
|
||||
}
|
||||
}
|
||||
|
@ -85,68 +85,3 @@ impl AbstractTree for IfElse {
|
||||
self.if_block.expected_type(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, Value};
|
||||
|
||||
#[test]
|
||||
fn evaluate_if() {
|
||||
assert_eq!(
|
||||
interpret("if true { 'true' }"),
|
||||
Ok(Value::String("true".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_if_else() {
|
||||
assert_eq!(
|
||||
interpret("if false { 1 } else { 2 }"),
|
||||
Ok(Value::Integer(2))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("if true { 1.0 } else { 42.0 }"),
|
||||
Ok(Value::Float(1.0))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_if_else_else_if_else() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
if false {
|
||||
'no'
|
||||
} else if 1 + 1 == 3 {
|
||||
'nope'
|
||||
} else {
|
||||
'ok'
|
||||
}
|
||||
"
|
||||
),
|
||||
Ok(Value::String("ok".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_if_else_if_else_if_else_if_else() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
if false {
|
||||
'no'
|
||||
} else if 1 + 1 == 1 {
|
||||
'nope'
|
||||
} else if 9 / 2 == 4 {
|
||||
'nope'
|
||||
} else if 'foo' == 'bar' {
|
||||
'nope'
|
||||
} else {
|
||||
'ok'
|
||||
}
|
||||
"
|
||||
),
|
||||
Ok(Value::String("ok".to_string()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -98,37 +98,3 @@ impl AbstractTree for Index {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpret;
|
||||
|
||||
#[test]
|
||||
fn list_index() {
|
||||
let test = interpret("x = [1 [2] 3] x:1:0").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(2), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_index() {
|
||||
let test = interpret("x = {y = {z = 2}} x:y:z").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(2), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex_index() {
|
||||
let test = interpret(
|
||||
"
|
||||
x = [1 2 3]
|
||||
y = () -> <int> { 0 }
|
||||
x:y()
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(1), test);
|
||||
}
|
||||
}
|
||||
|
@ -82,41 +82,3 @@ impl AbstractTree for Match {
|
||||
first_statement.expected_type(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, Value};
|
||||
|
||||
#[test]
|
||||
fn evaluate_match() {
|
||||
let test = interpret(
|
||||
"
|
||||
match 1 {
|
||||
3 => false
|
||||
2 => { false }
|
||||
1 => true
|
||||
}
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Boolean(true), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_match_assignment() {
|
||||
let test = interpret(
|
||||
"
|
||||
x = match 1 {
|
||||
3 => false
|
||||
2 => { false }
|
||||
1 => true
|
||||
}
|
||||
x
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Boolean(true), test);
|
||||
}
|
||||
}
|
||||
|
@ -258,43 +258,3 @@ impl Display for Type {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::interpret;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn simple_type_check() {
|
||||
let result = interpret("x <bool> = 1");
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Boolean,
|
||||
actual: Type::Integer
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn callback_type_check() {
|
||||
let result = interpret(
|
||||
"
|
||||
x = (cb <() -> bool>) <bool> {
|
||||
cb()
|
||||
}
|
||||
x(() <int> { 1 })
|
||||
",
|
||||
);
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Function {
|
||||
parameter_types: vec![],
|
||||
return_type: Box::new(Type::Boolean),
|
||||
},
|
||||
actual: Type::Function {
|
||||
parameter_types: vec![],
|
||||
return_type: Box::new(Type::Integer),
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -245,121 +245,3 @@ impl AbstractTree for ValueNode {
|
||||
Ok(type_definition)
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, List};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn evaluate_empty() {
|
||||
assert_eq!(interpret("x = 9"), Ok(Value::Option(None)));
|
||||
assert_eq!(interpret("x = 1 + 1"), Ok(Value::Option(None)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_integer() {
|
||||
assert_eq!(interpret("1"), Ok(Value::Integer(1)));
|
||||
assert_eq!(interpret("123"), Ok(Value::Integer(123)));
|
||||
assert_eq!(interpret("-666"), Ok(Value::Integer(-666)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_float() {
|
||||
assert_eq!(interpret("0.1"), Ok(Value::Float(0.1)));
|
||||
assert_eq!(interpret("12.3"), Ok(Value::Float(12.3)));
|
||||
assert_eq!(interpret("-6.66"), Ok(Value::Float(-6.66)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_string() {
|
||||
assert_eq!(interpret("\"one\""), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("'one'"), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("`one`"), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("`'one'`"), Ok(Value::String("'one'".to_string())));
|
||||
assert_eq!(interpret("'`one`'"), Ok(Value::String("`one`".to_string())));
|
||||
assert_eq!(
|
||||
interpret("\"'one'\""),
|
||||
Ok(Value::String("'one'".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_list() {
|
||||
assert_eq!(
|
||||
interpret("[1, 2, 'foobar']"),
|
||||
Ok(Value::List(List::with_items(vec![
|
||||
Value::Integer(1),
|
||||
Value::Integer(2),
|
||||
Value::String("foobar".to_string()),
|
||||
])))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_map() {
|
||||
let map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
||||
map.set("foo".to_string(), Value::String("bar".to_string()), None)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_map_types() {
|
||||
let map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
|
||||
.unwrap();
|
||||
map.set(
|
||||
"foo".to_string(),
|
||||
Value::String("bar".to_string()),
|
||||
Some(Type::String),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
||||
Ok(Value::Map(map))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_map_type_errors() {
|
||||
assert!(interpret("{ foo <bool> = 'bar' }")
|
||||
.unwrap_err()
|
||||
.is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Boolean,
|
||||
actual: Type::String
|
||||
}))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_function() {
|
||||
let result = interpret("() -> <int> { 1 }");
|
||||
let value = result.unwrap();
|
||||
let function = value.as_function().unwrap();
|
||||
|
||||
assert_eq!(&Vec::<Identifier>::with_capacity(0), function.parameters());
|
||||
assert_eq!(Ok(&Type::Integer), function.return_type());
|
||||
|
||||
let result = interpret("(x <bool>) -> <bool> {true}");
|
||||
let value = result.unwrap();
|
||||
let function = value.as_function().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&vec![Identifier::new("x".to_string())],
|
||||
function.parameters()
|
||||
);
|
||||
assert_eq!(Ok(&Type::Boolean), function.return_type());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate_option() {
|
||||
let result = interpret("x <option(int)> = some(1); x").unwrap();
|
||||
|
||||
assert_eq!(Value::Option(Some(Box::new(Value::Integer(1)))), result);
|
||||
}
|
||||
}
|
||||
|
@ -37,13 +37,3 @@ impl AbstractTree for While {
|
||||
self.block.expected_type(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{interpret, Value};
|
||||
|
||||
#[test]
|
||||
fn evalualate_while_loop() {
|
||||
assert_eq!(interpret("while false { 'foo' }"), Ok(Value::Option(None)))
|
||||
}
|
||||
}
|
||||
|
400
tests/interpret.rs
Normal file
400
tests/interpret.rs
Normal file
@ -0,0 +1,400 @@
|
||||
mod assignment {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn simple_assignment() {
|
||||
let test = interpret("x = 1 x");
|
||||
|
||||
assert_eq!(Ok(Value::Integer(1)), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_assignment_with_type() {
|
||||
let test = interpret("x <int> = 1 x");
|
||||
|
||||
assert_eq!(Ok(Value::Integer(1)), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_add_assign() {
|
||||
let test = interpret(
|
||||
"
|
||||
x <[int]> = []
|
||||
x += 1
|
||||
x
|
||||
",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ok(Value::List(List::with_items(vec![Value::Integer(1)]))),
|
||||
test
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_add_wrong_type() {
|
||||
let result = interpret(
|
||||
"
|
||||
x <[str]> = []
|
||||
x += 1
|
||||
",
|
||||
);
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::String,
|
||||
actual: Type::Integer
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
mod logic {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn complex_logic_sequence() {
|
||||
let result =
|
||||
interpret("(length([0]) == 1) && (length([0 0]) == 2) && (length([0 0 0]) == 3)");
|
||||
|
||||
assert_eq!(Ok(Value::Boolean(true)), result);
|
||||
}
|
||||
}
|
||||
|
||||
mod value {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn interpret_empty() {
|
||||
assert_eq!(interpret("x = 9"), Ok(Value::Option(None)));
|
||||
assert_eq!(interpret("x = 1 + 1"), Ok(Value::Option(None)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_integer() {
|
||||
assert_eq!(interpret("1"), Ok(Value::Integer(1)));
|
||||
assert_eq!(interpret("123"), Ok(Value::Integer(123)));
|
||||
assert_eq!(interpret("-666"), Ok(Value::Integer(-666)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_float() {
|
||||
assert_eq!(interpret("0.1"), Ok(Value::Float(0.1)));
|
||||
assert_eq!(interpret("12.3"), Ok(Value::Float(12.3)));
|
||||
assert_eq!(interpret("-6.66"), Ok(Value::Float(-6.66)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_string() {
|
||||
assert_eq!(interpret("\"one\""), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("'one'"), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("`one`"), Ok(Value::String("one".to_string())));
|
||||
assert_eq!(interpret("`'one'`"), Ok(Value::String("'one'".to_string())));
|
||||
assert_eq!(interpret("'`one`'"), Ok(Value::String("`one`".to_string())));
|
||||
assert_eq!(
|
||||
interpret("\"'one'\""),
|
||||
Ok(Value::String("'one'".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_list() {
|
||||
assert_eq!(
|
||||
interpret("[1, 2, 'foobar']"),
|
||||
Ok(Value::List(List::with_items(vec![
|
||||
Value::Integer(1),
|
||||
Value::Integer(2),
|
||||
Value::String("foobar".to_string()),
|
||||
])))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_map() {
|
||||
let map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
||||
map.set("foo".to_string(), Value::String("bar".to_string()), None)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_map_types() {
|
||||
let map = Map::new();
|
||||
|
||||
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
|
||||
.unwrap();
|
||||
map.set(
|
||||
"foo".to_string(),
|
||||
Value::String("bar".to_string()),
|
||||
Some(Type::String),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
||||
Ok(Value::Map(map))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_map_type_errors() {
|
||||
assert!(interpret("{ foo <bool> = 'bar' }")
|
||||
.unwrap_err()
|
||||
.is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Boolean,
|
||||
actual: Type::String
|
||||
}))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_function() {
|
||||
let result = interpret("() -> <int> { 1 }");
|
||||
let value = result.unwrap();
|
||||
let function = value.as_function().unwrap();
|
||||
|
||||
assert_eq!(&Vec::<Identifier>::with_capacity(0), function.parameters());
|
||||
assert_eq!(Ok(&Type::Integer), function.return_type());
|
||||
|
||||
let result = interpret("(x <bool>) -> <bool> {true}");
|
||||
let value = result.unwrap();
|
||||
let function = value.as_function().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&vec![Identifier::new("x".to_string())],
|
||||
function.parameters()
|
||||
);
|
||||
assert_eq!(Ok(&Type::Boolean), function.return_type());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_option() {
|
||||
let result = interpret("x <option(int)> = some(1); x").unwrap();
|
||||
|
||||
assert_eq!(Value::Option(Some(Box::new(Value::Integer(1)))), result);
|
||||
}
|
||||
}
|
||||
|
||||
mod function_call {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn interpret_function_call() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
foobar = (message <str>) -> <str> { message }
|
||||
foobar('Hiya')
|
||||
",
|
||||
),
|
||||
Ok(Value::String("Hiya".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_callback() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
foobar = (cb <() -> str>) <str> {
|
||||
cb()
|
||||
}
|
||||
foobar(() <str> { 'Hiya' })
|
||||
",
|
||||
),
|
||||
Ok(Value::String("Hiya".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_built_in_function_call() {
|
||||
assert_eq!(interpret("output('Hiya')"), Ok(Value::Option(None)));
|
||||
}
|
||||
}
|
||||
|
||||
mod if_else {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn interpret_if() {
|
||||
assert_eq!(
|
||||
interpret("if true { 'true' }"),
|
||||
Ok(Value::String("true".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_if_else() {
|
||||
assert_eq!(
|
||||
interpret("if false { 1 } else { 2 }"),
|
||||
Ok(Value::Integer(2))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("if true { 1.0 } else { 42.0 }"),
|
||||
Ok(Value::Float(1.0))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_if_else_else_if_else() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
if false {
|
||||
'no'
|
||||
} else if 1 + 1 == 3 {
|
||||
'nope'
|
||||
} else {
|
||||
'ok'
|
||||
}
|
||||
"
|
||||
),
|
||||
Ok(Value::String("ok".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_if_else_if_else_if_else_if_else() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"
|
||||
if false {
|
||||
'no'
|
||||
} else if 1 + 1 == 1 {
|
||||
'nope'
|
||||
} else if 9 / 2 == 4 {
|
||||
'nope'
|
||||
} else if 'foo' == 'bar' {
|
||||
'nope'
|
||||
} else {
|
||||
'ok'
|
||||
}
|
||||
"
|
||||
),
|
||||
Ok(Value::String("ok".to_string()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod index {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn list_index() {
|
||||
let test = interpret("x = [1 [2] 3] x:1:0").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(2), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_index() {
|
||||
let test = interpret("x = {y = {z = 2}} x:y:z").unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(2), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex_index() {
|
||||
let test = interpret(
|
||||
"
|
||||
x = [1 2 3]
|
||||
y = () -> <int> { 0 }
|
||||
x:y()
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Integer(1), test);
|
||||
}
|
||||
}
|
||||
|
||||
mod r#match {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn interpret_match() {
|
||||
let test = interpret(
|
||||
"
|
||||
match 1 {
|
||||
3 => false
|
||||
2 => { false }
|
||||
1 => true
|
||||
}
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Boolean(true), test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpret_match_assignment() {
|
||||
let test = interpret(
|
||||
"
|
||||
x = match 1 {
|
||||
3 => false
|
||||
2 => { false }
|
||||
1 => true
|
||||
}
|
||||
x
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Value::Boolean(true), test);
|
||||
}
|
||||
}
|
||||
|
||||
mod r#while {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn interpret_while_loop() {
|
||||
assert_eq!(interpret("while false { 'foo' }"), Ok(Value::Option(None)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_loop_iteration_count() {
|
||||
assert_eq!(
|
||||
interpret("i = 0; while i < 3 { i += 1 }; i"),
|
||||
Ok(Value::Integer(3))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mod type_definition {
|
||||
use dust_lang::*;
|
||||
|
||||
#[test]
|
||||
fn simple_type_check() {
|
||||
let result = interpret("x <bool> = 1");
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Boolean,
|
||||
actual: Type::Integer
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn callback_type_check() {
|
||||
let result = interpret(
|
||||
"
|
||||
x = (cb <() -> bool>) <bool> {
|
||||
cb()
|
||||
}
|
||||
x(() <int> { 1 })
|
||||
",
|
||||
);
|
||||
|
||||
assert!(result.unwrap_err().is_type_check_error(&Error::TypeCheck {
|
||||
expected: Type::Function {
|
||||
parameter_types: vec![],
|
||||
return_type: Box::new(Type::Boolean),
|
||||
},
|
||||
actual: Type::Function {
|
||||
parameter_types: vec![],
|
||||
return_type: Box::new(Type::Integer),
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
@ -101,99 +101,3 @@ Complex Logic Sequence
|
||||
(expression
|
||||
(value
|
||||
(integer)))))))))
|
||||
|
||||
================================================================================
|
||||
\==
|
||||
================================================================================
|
||||
|
||||
3 == 1 + 1 + 1
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(root
|
||||
(statement
|
||||
(expression
|
||||
(math
|
||||
(expression
|
||||
(math
|
||||
(expression
|
||||
(logic
|
||||
(expression
|
||||
(value
|
||||
(integer)))
|
||||
(logic_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(math_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(math_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))))
|
||||
|
||||
================================================================================
|
||||
&&
|
||||
================================================================================
|
||||
|
||||
4 + 2 == 42 && true
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(root
|
||||
(statement
|
||||
(expression
|
||||
(logic
|
||||
(expression
|
||||
(logic
|
||||
(expression
|
||||
(math
|
||||
(expression
|
||||
(value
|
||||
(integer)))
|
||||
(math_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(logic_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(logic_operator)
|
||||
(expression
|
||||
(value
|
||||
(boolean)))))))
|
||||
|
||||
================================================================================
|
||||
\||
|
||||
================================================================================
|
||||
|
||||
4 + 2 == 42 || true
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(root
|
||||
(statement
|
||||
(expression
|
||||
(logic
|
||||
(expression
|
||||
(logic
|
||||
(expression
|
||||
(math
|
||||
(expression
|
||||
(value
|
||||
(integer)))
|
||||
(math_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(logic_operator)
|
||||
(expression
|
||||
(value
|
||||
(integer)))))
|
||||
(logic_operator)
|
||||
(expression
|
||||
(value
|
||||
(boolean)))))))
|
||||
|
Loading…
Reference in New Issue
Block a user