1
0
This commit is contained in:
Jeff 2023-11-30 09:48:56 -05:00
parent e90a4d7353
commit 21099a4092
19 changed files with 2952 additions and 3066 deletions

View File

@ -1,7 +1,5 @@
(output "This will print first.")
create_random_numbers = |count <int>| {
numbers = [];
create_random_numbers <fn int> |count| {
mnumbers = [];
while (length numbers) < count {
numbers += (random_integer)
@ -10,6 +8,8 @@ create_random_numbers = |count <int>| {
(output "Made " + count + " numbers.")
}
(output "This will print first.")
async {
(create_random_numbers 1000)
(create_random_numbers 100)

View File

@ -4,25 +4,25 @@ all_cards = {
weapons = ['Rope' 'Lead_Pipe' 'Knife']
}
is_ready_to_solve = |cards <map>| <bool> {
is_ready_to_solve <fn map -> bool> |cards| {
((length cards:suspects) == 1)
&& ((length cards:rooms) == 1)
&& ((length cards:weapons) == 1)
}
take_turn = |opponent_card <str>, current_room <str>, cards <map>| <map> {
take_turn <fn str str map -> map> |opponent_card current_room cards| {
(remove_card opponent_card cards)
(make_guess current_room cards)
cards
}
remove_card = |opponent_card <str>, cards <map>| {
remove_card <fn str map> |opponent_card cards| {
cards:rooms -= opponent_card
cards:suspects -= opponent_card
cards:weapons -= opponent_card
}
make_guess = |current_room <str>, cards <map>| {
make_guess <fn str map> |current_room cards| {
if (is_ready_to_solve cards) {
(output 'It was '
+ cards:suspects:0

View File

@ -1,4 +1,4 @@
fib <fn int -> int> = |i| {
fib <fn int -> int> |i| {
if i <= 1 {
1
} else {

View File

@ -1,15 +0,0 @@
my_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]
]
test_table = table |text bool| [
["a", true]
["b", true]
["a", true]
]
test_select = select |text bool| from my_table;
(assert_equal test_select, test_table)

View File

@ -1,43 +0,0 @@
my_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]
]
test_table = table |text bool| [
["a", true]
["b", true]
["a", true]
]
test_select = select |text bool| from my_table;
(assert_equal test_select, test_table)
test_table = table |number bool| [
[1, true]
[3, true]
]
test_select_where = select |number, bool| from my_table {
text == "a"
}
(assert_equal test_select_where, test_table)
test_table = table |text number bool| [
["a", 1, true]
["b", 2, true]
["a", 3, true]
["c", 4, true]
["d", 5, true]
["e", 6, true]
]
insert into my_table [
["c", 4, true]
["d", 5, true]
["e", 6, true]
]
(assert_equal test_table, my_table)

View File

@ -1,6 +1,6 @@
1 -> (output)
add_one = |numbers <list>| <list> {
add_one <fn [int] -> [int]> |numbers| {
new_numbers = []
for number in numbers {

View File

@ -186,23 +186,10 @@ mod tests {
x <list int> = []
x += 1
x
",
",
)
.unwrap();
assert_eq!(Value::List(List::with_items(vec![Value::Integer(1)])), test);
}
#[test]
fn function_assignment() {
let test = evaluate(
"
foobar <fn str -> str> = |text| { 'hi' }
foobar
",
)
.unwrap();
assert_eq!(Value::String("hi".to_string()), test);
}
}

View File

@ -91,3 +91,26 @@ impl AbstractTree for FunctionCall {
self.function.expected_type(context)
}
}
#[cfg(test)]
mod tests {
use crate::{evaluate, Value};
#[test]
fn evaluate_function_call() {
assert_eq!(
evaluate(
"
foobar <fn str -> str> |message| { message }
(foobar 'Hiya')
",
),
Ok(Value::String("Hiya".to_string()))
);
}
#[test]
fn evaluate_built_in_function_call() {
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));
}
}

View File

@ -100,7 +100,7 @@ mod tests {
fn simple_function_declaration() {
let test = evaluate(
"
fn foo <fn int -> int> = |x| { x }
foo <fn int -> int> |x| { x }
(foo 42)
",
)

View File

@ -85,3 +85,65 @@ impl AbstractTree for IfElse {
self.if_block.expected_type(context)
}
}
#[cfg(test)]
mod tests {
use crate::{evaluate, Value};
#[test]
fn evaluate_if() {
assert_eq!(
evaluate("if true { 'true' }"),
Ok(Value::String("true".to_string()))
);
}
#[test]
fn evaluate_if_else() {
assert_eq!(evaluate("if false { 1 } else { 2 }"), Ok(Value::Integer(2)));
assert_eq!(
evaluate("if true { 1.0 } else { 42.0 }"),
Ok(Value::Float(1.0))
);
}
#[test]
fn evaluate_if_else_else_if_else() {
assert_eq!(
evaluate(
"
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!(
evaluate(
"
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()))
);
}
}

View File

@ -147,6 +147,12 @@ impl AbstractTree for Type {
let type_node = node.child(0).unwrap();
let r#type = match type_node.kind() {
"[" => {
let item_type_node = node.child(1).unwrap();
let item_type = Type::from_syntax_node(source, item_type_node, context)?;
Type::List(Box::new(item_type))
}
"any" => Type::Any,
"bool" => Type::Boolean,
"float" => Type::Float,
@ -171,12 +177,6 @@ impl AbstractTree for Type {
}
}
"int" => Type::Integer,
"list" => {
let item_type_node = node.child(1).unwrap();
let item_type = Type::from_syntax_node(source, item_type_node, context)?;
Type::List(Box::new(item_type))
}
"map" => Type::Map,
"num" => Type::Number,
"str" => Type::String,

View File

@ -215,3 +215,68 @@ impl AbstractTree for ValueNode {
Ok(type_definition)
}
}
#[cfg(test)]
mod tests {
use crate::{evaluate, List};
use super::*;
#[test]
fn evaluate_empty() {
assert_eq!(evaluate("x = 9"), Ok(Value::Empty));
assert_eq!(evaluate("x = 1 + 1"), Ok(Value::Empty));
}
#[test]
fn evaluate_integer() {
assert_eq!(evaluate("1"), Ok(Value::Integer(1)));
assert_eq!(evaluate("123"), Ok(Value::Integer(123)));
assert_eq!(evaluate("-666"), Ok(Value::Integer(-666)));
}
#[test]
fn evaluate_float() {
assert_eq!(evaluate("0.1"), Ok(Value::Float(0.1)));
assert_eq!(evaluate("12.3"), Ok(Value::Float(12.3)));
assert_eq!(evaluate("-6.66"), Ok(Value::Float(-6.66)));
}
#[test]
fn evaluate_string() {
assert_eq!(evaluate("\"one\""), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("'one'"), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("`one`"), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("`'one'`"), Ok(Value::String("'one'".to_string())));
assert_eq!(evaluate("'`one`'"), Ok(Value::String("`one`".to_string())));
assert_eq!(
evaluate("\"'one'\""),
Ok(Value::String("'one'".to_string()))
);
}
#[test]
fn evaluate_list() {
assert_eq!(
evaluate("[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();
{
let mut variables = map.variables_mut().unwrap();
variables.insert("x".to_string(), Value::Integer(1));
variables.insert("foo".to_string(), Value::String("bar".to_string()));
}
assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
}
}

View File

@ -84,144 +84,3 @@ impl<'c, 's> Interpreter<'c, 's> {
self.syntax_tree.root_node().to_sexp()
}
}
#[cfg(test)]
mod tests {
use crate::{List, Table};
use super::*;
#[test]
fn evaluate_empty() {
assert_eq!(evaluate("x = 9"), Ok(Value::Empty));
assert_eq!(evaluate("x = 1 + 1"), Ok(Value::Empty));
}
#[test]
fn evaluate_integer() {
assert_eq!(evaluate("1"), Ok(Value::Integer(1)));
assert_eq!(evaluate("123"), Ok(Value::Integer(123)));
assert_eq!(evaluate("-666"), Ok(Value::Integer(-666)));
}
#[test]
fn evaluate_float() {
assert_eq!(evaluate("0.1"), Ok(Value::Float(0.1)));
assert_eq!(evaluate("12.3"), Ok(Value::Float(12.3)));
assert_eq!(evaluate("-6.66"), Ok(Value::Float(-6.66)));
}
#[test]
fn evaluate_string() {
assert_eq!(evaluate("\"one\""), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("'one'"), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("`one`"), Ok(Value::String("one".to_string())));
assert_eq!(evaluate("`'one'`"), Ok(Value::String("'one'".to_string())));
assert_eq!(evaluate("'`one`'"), Ok(Value::String("`one`".to_string())));
assert_eq!(
evaluate("\"'one'\""),
Ok(Value::String("'one'".to_string()))
);
}
#[test]
fn evaluate_list() {
assert_eq!(
evaluate("[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();
{
let mut variables = map.variables_mut().unwrap();
variables.insert("x".to_string(), Value::Integer(1));
variables.insert("foo".to_string(), Value::String("bar".to_string()));
}
assert_eq!(evaluate("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
}
#[test]
fn evaluate_if() {
assert_eq!(
evaluate("if true { 'true' }"),
Ok(Value::String("true".to_string()))
);
}
#[test]
fn evaluate_if_else() {
assert_eq!(evaluate("if false { 1 } else { 2 }"), Ok(Value::Integer(2)));
assert_eq!(
evaluate("if true { 1.0 } else { 42.0 }"),
Ok(Value::Float(1.0))
);
}
#[test]
fn evaluate_if_else_else_if_else() {
assert_eq!(
evaluate(
"
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!(
evaluate(
"
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()))
);
}
#[test]
fn evaluate_function_call() {
assert_eq!(
evaluate(
"
foobar <fn str -> str> = |message| { message }
(foobar 'Hiya')
",
),
Ok(Value::String("Hiya".to_string()))
);
}
#[test]
fn evaluate_built_in_function_call() {
assert_eq!(evaluate("(output 'Hiya')"), Ok(Value::Empty));
}
}

View File

@ -95,20 +95,6 @@ fn sea_creatures() {
evaluate(&file_contents).unwrap();
}
#[test]
fn select() {
let file_contents = read_to_string("examples/select.ds").unwrap();
evaluate(&file_contents).unwrap();
}
#[test]
fn table() {
let file_contents = read_to_string("examples/table.ds").unwrap();
evaluate(&file_contents).unwrap();
}
#[test]
fn variables() {
let file_contents = read_to_string("examples/variables.ds").unwrap();

View File

@ -341,7 +341,7 @@ module.exports = grammar({
optional(seq('->', $.type)),
),
'int',
seq('list', $.type),
seq('[', $.type, ']'),
'map',
'num',
'str',

View File

@ -1096,11 +1096,15 @@
"members": [
{
"type": "STRING",
"value": "list"
"value": "["
},
{
"type": "SYMBOL",
"name": "type"
},
{
"type": "STRING",
"value": "]"
}
]
},

View File

@ -748,10 +748,6 @@
"type": "integer",
"named": true
},
{
"type": "list",
"named": false
},
{
"type": "map",
"named": false

File diff suppressed because it is too large Load Diff