5 Commits

16 changed files with 867 additions and 276 deletions

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
[0.5.0]
- Added support for tuple types
- Added support for tuple returns from functions
- Added support for ignoring tuple values
- Fixed various compiler bugs
[0.4.7] [0.4.7]
- Added support for Windows CRLF endings - Added support for Windows CRLF endings

View File

@@ -2,7 +2,7 @@
<ModMetadata xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ModMetadata xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Slang</Name> <Name>Slang</Name>
<Author>JoeDiertay</Author> <Author>JoeDiertay</Author>
<Version>0.4.7</Version> <Version>0.5.0</Version>
<Description> <Description>
[h1]Slang: High-Level Programming for Stationeers[/h1] [h1]Slang: High-Level Programming for Stationeers[/h1]

View File

@@ -39,7 +39,7 @@ namespace Slang
{ {
public const string PluginGuid = "com.biddydev.slang"; public const string PluginGuid = "com.biddydev.slang";
public const string PluginName = "Slang"; public const string PluginName = "Slang";
public const string PluginVersion = "0.4.7"; public const string PluginVersion = "0.5.0";
private static Harmony? _harmony; private static Harmony? _harmony;

View File

@@ -5,7 +5,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyName>StationeersSlang</AssemblyName> <AssemblyName>StationeersSlang</AssemblyName>
<Description>Slang Compiler Bridge</Description> <Description>Slang Compiler Bridge</Description>
<Version>0.4.2</Version> <Version>0.5.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>

View File

@@ -930,7 +930,7 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]] [[package]]
name = "slang" name = "slang"
version = "0.4.7" version = "0.5.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "slang" name = "slang"
version = "0.4.7" version = "0.5.0"
edition = "2021" edition = "2021"
[workspace] [workspace]

View File

@@ -4,13 +4,19 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn variable_declaration_numeric_literal() -> anyhow::Result<()> { fn variable_declaration_numeric_literal() -> anyhow::Result<()> {
let compiled = crate::compile! { let compiled = crate::compile! {
debug r#" check r#"
let i = 20c; let i = 20c;
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -26,7 +32,7 @@ fn variable_declaration_numeric_literal() -> anyhow::Result<()> {
#[test] #[test]
fn variable_declaration_numeric_literal_stack_spillover() -> anyhow::Result<()> { fn variable_declaration_numeric_literal_stack_spillover() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
let a = 0; let a = 0;
let b = 1; let b = 1;
@@ -40,8 +46,14 @@ fn variable_declaration_numeric_literal_stack_spillover() -> anyhow::Result<()>
let j = 9; let j = 9;
"#}; "#};
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -67,14 +79,20 @@ fn variable_declaration_numeric_literal_stack_spillover() -> anyhow::Result<()>
#[test] #[test]
fn variable_declaration_negative() -> anyhow::Result<()> { fn variable_declaration_negative() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = -1; let i = -1;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -90,15 +108,21 @@ fn variable_declaration_negative() -> anyhow::Result<()> {
#[test] #[test]
fn test_boolean_declaration() -> anyhow::Result<()> { fn test_boolean_declaration() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let t = true; let t = true;
let f = false; let f = false;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -115,7 +139,7 @@ fn test_boolean_declaration() -> anyhow::Result<()> {
#[test] #[test]
fn test_boolean_return() -> anyhow::Result<()> { fn test_boolean_return() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
fn getTrue() { fn getTrue() {
return true; return true;
@@ -125,8 +149,14 @@ fn test_boolean_return() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -149,15 +179,21 @@ fn test_boolean_return() -> anyhow::Result<()> {
#[test] #[test]
fn test_const_hash_expr() -> anyhow::Result<()> { fn test_const_hash_expr() -> anyhow::Result<()> {
let compiled = compile!(debug r#" let compiled = compile!(check r#"
const nameHash = hash("AccessCard"); const nameHash = hash("AccessCard");
device self = "db"; device self = "db";
self.Setting = nameHash; self.Setting = nameHash;
"#); "#);
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -172,7 +208,7 @@ fn test_const_hash_expr() -> anyhow::Result<()> {
#[test] #[test]
fn test_declaration_is_const() -> anyhow::Result<()> { fn test_declaration_is_const() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
const MAX = 100; const MAX = 100;
@@ -180,8 +216,14 @@ fn test_declaration_is_const() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -4,13 +4,13 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn device_declaration() -> anyhow::Result<()> { fn device_declaration() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
" "
}; };
// Declaration only emits the jump label header // Declaration only emits the jump label header
assert_eq!(compiled, "j main\n"); assert_eq!(compiled.output, "j main\n");
Ok(()) Ok(())
} }
@@ -18,14 +18,20 @@ fn device_declaration() -> anyhow::Result<()> {
#[test] #[test]
fn device_property_read() -> anyhow::Result<()> { fn device_property_read() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device ac = \"d0\"; device ac = \"d0\";
let temp = ac.Temperature; let temp = ac.Temperature;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -42,14 +48,20 @@ fn device_property_read() -> anyhow::Result<()> {
#[test] #[test]
fn device_property_write() -> anyhow::Result<()> { fn device_property_write() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device ac = \"d0\"; device ac = \"d0\";
ac.On = 1; ac.On = 1;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -65,15 +77,21 @@ fn device_property_write() -> anyhow::Result<()> {
#[test] #[test]
fn multiple_device_declarations() -> anyhow::Result<()> { fn multiple_device_declarations() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
device d1 = \"d1\"; device d1 = \"d1\";
device d2 = \"d2\"; device d2 = \"d2\";
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// Declarations only emit the header when unused // Declarations only emit the header when unused
assert_eq!(compiled, "j main\n"); assert_eq!(compiled.output, "j main\n");
Ok(()) Ok(())
} }
@@ -81,7 +99,7 @@ fn multiple_device_declarations() -> anyhow::Result<()> {
#[test] #[test]
fn device_with_variable_interaction() -> anyhow::Result<()> { fn device_with_variable_interaction() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device sensor = \"d0\"; device sensor = \"d0\";
let reading = sensor.Temperature; let reading = sensor.Temperature;
let threshold = 373.15; let threshold = 373.15;
@@ -89,8 +107,14 @@ fn device_with_variable_interaction() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -110,15 +134,21 @@ fn device_with_variable_interaction() -> anyhow::Result<()> {
#[test] #[test]
fn device_property_in_arithmetic() -> anyhow::Result<()> { fn device_property_in_arithmetic() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
let result = d0.Temperature + 100; let result = d0.Temperature + 100;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// Verify that we load property, add 100, and move to result // Verify that we load property, add 100, and move to result
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -136,7 +166,7 @@ fn device_property_in_arithmetic() -> anyhow::Result<()> {
#[test] #[test]
fn device_used_in_function() -> anyhow::Result<()> { fn device_used_in_function() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
fn check_power() { fn check_power() {
@@ -147,8 +177,14 @@ fn device_used_in_function() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -173,7 +209,7 @@ fn device_used_in_function() -> anyhow::Result<()> {
#[test] #[test]
fn device_in_conditional() -> anyhow::Result<()> { fn device_in_conditional() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
if (d0.On) { if (d0.On) {
@@ -182,8 +218,14 @@ fn device_in_conditional() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -202,14 +244,20 @@ fn device_in_conditional() -> anyhow::Result<()> {
#[test] #[test]
fn device_property_with_underscore_name() -> anyhow::Result<()> { fn device_property_with_underscore_name() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device cool_device = \"d0\"; device cool_device = \"d0\";
let value = cool_device.SomeProperty; let value = cool_device.SomeProperty;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -167,15 +167,21 @@ fn temperature_unit_conversion() -> anyhow::Result<()> {
#[test] #[test]
fn mixed_temperature_units() -> anyhow::Result<()> { fn mixed_temperature_units() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let c = 0c; let c = 0c;
let f = 32f; let f = 32f;
let k = 273.15k; let k = 273.15k;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -193,15 +199,21 @@ fn mixed_temperature_units() -> anyhow::Result<()> {
#[test] #[test]
fn boolean_constant_folding() -> anyhow::Result<()> { fn boolean_constant_folding() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = true; let x = true;
let y = false; let y = false;
let z = true && true; let z = true && true;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -220,7 +232,7 @@ fn boolean_constant_folding() -> anyhow::Result<()> {
#[test] #[test]
fn empty_block() -> anyhow::Result<()> { fn empty_block() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 5; let x = 5;
{ {
} }
@@ -228,8 +240,14 @@ fn empty_block() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -246,13 +264,19 @@ fn empty_block() -> anyhow::Result<()> {
#[test] #[test]
fn multiple_statements_same_line() -> anyhow::Result<()> { fn multiple_statements_same_line() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 1; let y = 2; let z = 3; let x = 1; let y = 2; let z = 3;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -270,7 +294,7 @@ fn multiple_statements_same_line() -> anyhow::Result<()> {
#[test] #[test]
fn function_with_no_return() -> anyhow::Result<()> { fn function_with_no_return() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
fn no_return() { fn no_return() {
let x = 5; let x = 5;
}; };
@@ -279,8 +303,14 @@ fn function_with_no_return() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -303,13 +333,19 @@ fn function_with_no_return() -> anyhow::Result<()> {
#[test] #[test]
fn deeply_nested_expressions() -> anyhow::Result<()> { fn deeply_nested_expressions() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = ((((((((1 + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9); let x = ((((((((1 + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -325,13 +361,19 @@ fn deeply_nested_expressions() -> anyhow::Result<()> {
#[test] #[test]
fn constant_folding_with_operations() -> anyhow::Result<()> { fn constant_folding_with_operations() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10 * 5 + 3 - 2; let x = 10 * 5 + 3 - 2;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -347,13 +389,19 @@ fn constant_folding_with_operations() -> anyhow::Result<()> {
#[test] #[test]
fn constant_folding_with_division() -> anyhow::Result<()> { fn constant_folding_with_division() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 100 / 2 / 5; let x = 100 / 2 / 5;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -369,14 +417,19 @@ fn constant_folding_with_division() -> anyhow::Result<()> {
#[test] #[test]
fn modulo_operation() -> anyhow::Result<()> { fn modulo_operation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 17 % 5; let x = 17 % 5;
let y = 10 % 3; let y = 10 % 3;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -393,20 +446,28 @@ fn modulo_operation() -> anyhow::Result<()> {
#[test] #[test]
fn exponentiation() -> anyhow::Result<()> { fn exponentiation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 2 ^ 8; let x = 2 ** 8;
let y = 3 ^ 3; let y = 3 ** 3;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
main: main:
move r0 3 pow r1 2 8
move r1 3 move r8 r1
pow r2 3 3
move r9 r2
" "
} }
); );
@@ -417,15 +478,21 @@ fn exponentiation() -> anyhow::Result<()> {
#[test] #[test]
fn comparison_with_zero() -> anyhow::Result<()> { fn comparison_with_zero() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 0 == 0; let x = 0 == 0;
let y = 0 < 1; let y = 0 < 1;
let z = 0 > -1; let z = 0 > -1;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -446,15 +513,21 @@ fn comparison_with_zero() -> anyhow::Result<()> {
#[test] #[test]
fn boolean_negation_edge_cases() -> anyhow::Result<()> { fn boolean_negation_edge_cases() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = !0; let x = !0;
let y = !1; let y = !1;
let z = !100; let z = !100;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -475,7 +548,7 @@ fn boolean_negation_edge_cases() -> anyhow::Result<()> {
#[test] #[test]
fn function_with_many_parameters() -> anyhow::Result<()> { fn function_with_many_parameters() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
fn many_params(a, b, c, d, e, f, g, h) { fn many_params(a, b, c, d, e, f, g, h) {
return a + b + c + d + e + f + g + h; return a + b + c + d + e + f + g + h;
}; };
@@ -484,8 +557,14 @@ fn function_with_many_parameters() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -3,7 +3,7 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn test_function_declaration_with_spillover_params() -> anyhow::Result<()> { fn test_function_declaration_with_spillover_params() -> anyhow::Result<()> {
let compiled = compile!(debug r#" let compiled = compile!(check r#"
// we need more than 4 params to 'spill' into a stack var // we need more than 4 params to 'spill' into a stack var
fn doSomething(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { fn doSomething(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9; return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9;
@@ -13,8 +13,14 @@ fn test_function_declaration_with_spillover_params() -> anyhow::Result<()> {
let returned = doSomething(item1, 2, 3, 4, 5, 6, 7, 8, 9); let returned = doSomething(item1, 2, 3, 4, 5, 6, 7, 8, 9);
"#); "#);
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! {" indoc! {"
j main j main
doSomething: doSomething:
@@ -67,7 +73,7 @@ fn test_function_declaration_with_spillover_params() -> anyhow::Result<()> {
#[test] #[test]
fn test_early_return() -> anyhow::Result<()> { fn test_early_return() -> anyhow::Result<()> {
let compiled = compile!(debug r#" let compiled = compile!(check r#"
// This is a test function declaration with no body // This is a test function declaration with no body
fn doSomething() { fn doSomething() {
if (1 == 1) { if (1 == 1) {
@@ -79,8 +85,14 @@ fn test_early_return() -> anyhow::Result<()> {
doSomething(); doSomething();
"#); "#);
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -107,14 +119,20 @@ fn test_early_return() -> anyhow::Result<()> {
#[test] #[test]
fn test_function_declaration_with_register_params() -> anyhow::Result<()> { fn test_function_declaration_with_register_params() -> anyhow::Result<()> {
let compiled = compile!(debug r#" let compiled = compile!(check r#"
// This is a test function declaration with no body // This is a test function declaration with no body
fn doSomething(arg1, arg2) { fn doSomething(arg1, arg2) {
}; };
"#); "#);
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! {" indoc! {"
j main j main
doSomething: doSomething:

View File

@@ -5,14 +5,20 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn test_acos() -> Result<()> { fn test_acos() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = acos(123); let i = acos(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -29,14 +35,20 @@ fn test_acos() -> Result<()> {
#[test] #[test]
fn test_asin() -> Result<()> { fn test_asin() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = asin(123); let i = asin(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -53,14 +65,20 @@ fn test_asin() -> Result<()> {
#[test] #[test]
fn test_atan() -> Result<()> { fn test_atan() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = atan(123); let i = atan(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -77,14 +95,20 @@ fn test_atan() -> Result<()> {
#[test] #[test]
fn test_atan2() -> Result<()> { fn test_atan2() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = atan2(123, 456); let i = atan2(123, 456);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -101,14 +125,20 @@ fn test_atan2() -> Result<()> {
#[test] #[test]
fn test_abs() -> Result<()> { fn test_abs() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = abs(-123); let i = abs(-123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -125,14 +155,20 @@ fn test_abs() -> Result<()> {
#[test] #[test]
fn test_ceil() -> Result<()> { fn test_ceil() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = ceil(123.90); let i = ceil(123.90);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -149,14 +185,20 @@ fn test_ceil() -> Result<()> {
#[test] #[test]
fn test_cos() -> Result<()> { fn test_cos() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = cos(123); let i = cos(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -173,14 +215,20 @@ fn test_cos() -> Result<()> {
#[test] #[test]
fn test_floor() -> Result<()> { fn test_floor() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = floor(123); let i = floor(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -197,14 +245,20 @@ fn test_floor() -> Result<()> {
#[test] #[test]
fn test_log() -> Result<()> { fn test_log() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = log(123); let i = log(123);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -221,14 +275,20 @@ fn test_log() -> Result<()> {
#[test] #[test]
fn test_max() -> Result<()> { fn test_max() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = max(123, 456); let i = max(123, 456);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -245,15 +305,21 @@ fn test_max() -> Result<()> {
#[test] #[test]
fn test_max_from_game() -> Result<()> { fn test_max_from_game() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
let item = 0; let item = 0;
item = max(1 + 2, 2); item = max(1 + 2, 2);
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -271,14 +337,20 @@ fn test_max_from_game() -> Result<()> {
#[test] #[test]
fn test_min() -> Result<()> { fn test_min() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = min(123, 456); let i = min(123, 456);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -295,14 +367,20 @@ fn test_min() -> Result<()> {
#[test] #[test]
fn test_rand() -> Result<()> { fn test_rand() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = rand(); let i = rand();
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -319,14 +397,20 @@ fn test_rand() -> Result<()> {
#[test] #[test]
fn test_sin() -> Result<()> { fn test_sin() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = sin(3); let i = sin(3);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -343,14 +427,20 @@ fn test_sin() -> Result<()> {
#[test] #[test]
fn test_sqrt() -> Result<()> { fn test_sqrt() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = sqrt(3); let i = sqrt(3);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -367,14 +457,20 @@ fn test_sqrt() -> Result<()> {
#[test] #[test]
fn test_tan() -> Result<()> { fn test_tan() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = tan(3); let i = tan(3);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -391,14 +487,20 @@ fn test_tan() -> Result<()> {
#[test] #[test]
fn test_trunc() -> Result<()> { fn test_trunc() -> Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
let i = trunc(3.234); let i = trunc(3.234);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -33,17 +33,6 @@ macro_rules! compile {
compiler.compile().errors compiler.compile().errors
}}; }};
(debug $source:expr) => {{
let mut writer = std::io::BufWriter::new(Vec::new());
let compiler = crate::Compiler::new(
parser::Parser::new(tokenizer::Tokenizer::from($source)),
Some(crate::CompilerConfig { debug: true }),
);
let res = compiler.compile();
res.instructions.write(&mut writer)?;
output!(writer)
}};
(check $source:expr) => {{ (check $source:expr) => {{
let mut writer = std::io::BufWriter::new(Vec::new()); let mut writer = std::io::BufWriter::new(Vec::new());
let compiler = crate::Compiler::new( let compiler = crate::Compiler::new(

View File

@@ -4,13 +4,19 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn simple_negation() -> anyhow::Result<()> { fn simple_negation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = -5; let x = -5;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -26,14 +32,20 @@ fn simple_negation() -> anyhow::Result<()> {
#[test] #[test]
fn negation_of_variable() -> anyhow::Result<()> { fn negation_of_variable() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10; let x = 10;
let y = -x; let y = -x;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -51,13 +63,19 @@ fn negation_of_variable() -> anyhow::Result<()> {
#[test] #[test]
fn double_negation() -> anyhow::Result<()> { fn double_negation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = -(-5); let x = -(-5);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -73,13 +91,19 @@ fn double_negation() -> anyhow::Result<()> {
#[test] #[test]
fn negation_in_expression() -> anyhow::Result<()> { fn negation_in_expression() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10 + (-5); let x = 10 + (-5);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -95,13 +119,19 @@ fn negation_in_expression() -> anyhow::Result<()> {
#[test] #[test]
fn negation_with_multiplication() -> anyhow::Result<()> { fn negation_with_multiplication() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = -3 * 4; let x = -3 * 4;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -117,13 +147,19 @@ fn negation_with_multiplication() -> anyhow::Result<()> {
#[test] #[test]
fn parentheses_priority() -> anyhow::Result<()> { fn parentheses_priority() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = (2 + 3) * 4; let x = (2 + 3) * 4;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -139,13 +175,19 @@ fn parentheses_priority() -> anyhow::Result<()> {
#[test] #[test]
fn nested_parentheses() -> anyhow::Result<()> { fn nested_parentheses() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = ((2 + 3) * (4 - 1)); let x = ((2 + 3) * (4 - 1));
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -161,16 +203,22 @@ fn nested_parentheses() -> anyhow::Result<()> {
#[test] #[test]
fn parentheses_with_variables() -> anyhow::Result<()> { fn parentheses_with_variables() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let a = 5; let a = 5;
let b = 10; let b = 10;
let c = (a + b) * 2; let c = (a + b) * 2;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// Should calculate (5 + 10) * 2 = 30 // Should calculate (5 + 10) * 2 = 30
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -190,15 +238,21 @@ fn parentheses_with_variables() -> anyhow::Result<()> {
#[test] #[test]
fn priority_affects_result() -> anyhow::Result<()> { fn priority_affects_result() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let with_priority = (2 + 3) * 4; let with_priority = (2 + 3) * 4;
let without_priority = 2 + 3 * 4; let without_priority = 2 + 3 * 4;
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// with_priority should be 20, without_priority should be 14 // with_priority should be 20, without_priority should be 14
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -215,14 +269,20 @@ fn priority_affects_result() -> anyhow::Result<()> {
#[test] #[test]
fn negation_of_expression() -> anyhow::Result<()> { fn negation_of_expression() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = -(2 + 3); let x = -(2 + 3);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// Should be -5 (constant folded) // Should be -5 (constant folded)
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -239,14 +299,20 @@ fn negation_of_expression() -> anyhow::Result<()> {
#[test] #[test]
fn complex_negation_and_priority() -> anyhow::Result<()> { fn complex_negation_and_priority() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = -((10 - 5) * 2); let x = -((10 - 5) * 2);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// Should be -(5 * 2) = -10 (folded to constant) // Should be -(5 * 2) = -10 (folded to constant)
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -263,14 +329,20 @@ fn complex_negation_and_priority() -> anyhow::Result<()> {
#[test] #[test]
fn negation_in_logical_expression() -> anyhow::Result<()> { fn negation_in_logical_expression() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = !(-5); let x = !(-5);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// -5 is truthy, so !(-5) should be 0 // -5 is truthy, so !(-5) should be 0
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -288,14 +360,20 @@ fn negation_in_logical_expression() -> anyhow::Result<()> {
#[test] #[test]
fn parentheses_in_comparison() -> anyhow::Result<()> { fn parentheses_in_comparison() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = (10 + 5) > (3 * 4); let x = (10 + 5) > (3 * 4);
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
// (10 + 5) = 15 > (3 * 4) = 12, so true (1) // (10 + 5) = 15 > (3 * 4) = 12, so true (1)
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -4,7 +4,7 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn block_scope() -> anyhow::Result<()> { fn block_scope() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10; let x = 10;
{ {
let y = 20; let y = 20;
@@ -13,8 +13,14 @@ fn block_scope() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -33,7 +39,7 @@ fn block_scope() -> anyhow::Result<()> {
#[test] #[test]
fn variable_scope_isolation() -> anyhow::Result<()> { fn variable_scope_isolation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10; let x = 10;
{ {
let x = 20; let x = 20;
@@ -42,8 +48,14 @@ fn variable_scope_isolation() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -61,7 +73,7 @@ fn variable_scope_isolation() -> anyhow::Result<()> {
#[test] #[test]
fn function_parameter_scope() -> anyhow::Result<()> { fn function_parameter_scope() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
fn double(x) { fn double(x) {
return x * 2; return x * 2;
}; };
@@ -70,8 +82,14 @@ fn function_parameter_scope() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -95,52 +113,10 @@ fn function_parameter_scope() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[test]
fn function_local_variables() -> anyhow::Result<()> {
let compiled = compile! {
debug "
let global = 100;
fn test() {
let local = 50;
return local + global;
};
let result = test();
"
};
assert_eq!(
compiled,
indoc! {
"
j main
test:
push ra
move r8 50
add r1 r8 r0
move r15 r1
j __internal_L1
__internal_L1:
pop ra
j ra
main:
move r8 100
push r8
jal test
pop r8
move r9 r15
"
}
);
Ok(())
}
#[test] #[test]
fn nested_block_scopes() -> anyhow::Result<()> { fn nested_block_scopes() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 1; let x = 1;
{ {
let x = 2; let x = 2;
@@ -154,8 +130,14 @@ fn nested_block_scopes() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -176,7 +158,7 @@ fn nested_block_scopes() -> anyhow::Result<()> {
#[test] #[test]
fn variable_shadowing_in_conditional() -> anyhow::Result<()> { fn variable_shadowing_in_conditional() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 10; let x = 10;
if (true) { if (true) {
@@ -187,8 +169,14 @@ fn variable_shadowing_in_conditional() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -208,7 +196,7 @@ fn variable_shadowing_in_conditional() -> anyhow::Result<()> {
#[test] #[test]
fn variable_shadowing_in_loop() -> anyhow::Result<()> { fn variable_shadowing_in_loop() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 0; let x = 0;
loop { loop {
@@ -220,8 +208,14 @@ fn variable_shadowing_in_loop() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -246,7 +240,7 @@ fn variable_shadowing_in_loop() -> anyhow::Result<()> {
#[test] #[test]
fn const_scope() -> anyhow::Result<()> { fn const_scope() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
const PI = 3.14; const PI = 3.14;
{ {
@@ -256,8 +250,14 @@ fn const_scope() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -273,7 +273,7 @@ fn const_scope() -> anyhow::Result<()> {
#[test] #[test]
fn device_in_scope() -> anyhow::Result<()> { fn device_in_scope() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
device d0 = \"d0\"; device d0 = \"d0\";
{ {
@@ -282,8 +282,14 @@ fn device_in_scope() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -300,7 +306,7 @@ fn device_in_scope() -> anyhow::Result<()> {
#[test] #[test]
fn function_scope_isolation() -> anyhow::Result<()> { fn function_scope_isolation() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
fn func1() { fn func1() {
let x = 10; let x = 10;
return x; return x;
@@ -316,8 +322,14 @@ fn function_scope_isolation() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -354,7 +366,7 @@ fn function_scope_isolation() -> anyhow::Result<()> {
#[test] #[test]
fn tuple_unpacking_scope() -> anyhow::Result<()> { fn tuple_unpacking_scope() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
fn pair() { fn pair() {
return (1, 2); return (1, 2);
}; };
@@ -366,8 +378,14 @@ fn tuple_unpacking_scope() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -397,7 +415,7 @@ fn tuple_unpacking_scope() -> anyhow::Result<()> {
#[test] #[test]
fn shadowing_doesnt_affect_outer() -> anyhow::Result<()> { fn shadowing_doesnt_affect_outer() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug " check "
let x = 5; let x = 5;
let y = x; let y = x;
{ {
@@ -408,8 +426,14 @@ fn shadowing_doesnt_affect_outer() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -4,14 +4,20 @@ use pretty_assertions::assert_eq;
#[test] #[test]
fn test_yield() -> anyhow::Result<()> { fn test_yield() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
yield(); yield();
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -27,7 +33,7 @@ fn test_yield() -> anyhow::Result<()> {
#[test] #[test]
fn test_sleep() -> anyhow::Result<()> { fn test_sleep() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
" "
sleep(3); sleep(3);
let sleepAmount = 15; let sleepAmount = 15;
@@ -36,8 +42,14 @@ fn test_sleep() -> anyhow::Result<()> {
" "
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -57,7 +69,7 @@ fn test_sleep() -> anyhow::Result<()> {
#[test] #[test]
fn test_set_on_device() -> anyhow::Result<()> { fn test_set_on_device() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device airConditioner = "d0"; device airConditioner = "d0";
let internalTemp = 20c; let internalTemp = 20c;
@@ -66,8 +78,14 @@ fn test_set_on_device() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -85,15 +103,21 @@ fn test_set_on_device() -> anyhow::Result<()> {
#[test] #[test]
fn test_set_on_device_batched() -> anyhow::Result<()> { fn test_set_on_device_batched() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
const doorHash = hash("Door"); const doorHash = hash("Door");
setBatched(doorHash, "Lock", true); setBatched(doorHash, "Lock", true);
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
r#" r#"
j main j main
@@ -108,7 +132,7 @@ fn test_set_on_device_batched() -> anyhow::Result<()> {
#[test] #[test]
fn test_set_on_device_batched_named() -> anyhow::Result<()> { fn test_set_on_device_batched_named() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device dev = "d0"; device dev = "d0";
const devName = hash("test"); const devName = hash("test");
@@ -117,8 +141,14 @@ fn test_set_on_device_batched_named() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -134,7 +164,7 @@ fn test_set_on_device_batched_named() -> anyhow::Result<()> {
#[test] #[test]
fn test_load_from_device() -> anyhow::Result<()> { fn test_load_from_device() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device airCon = "d0"; device airCon = "d0";
@@ -142,8 +172,14 @@ fn test_load_from_device() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -160,7 +196,7 @@ fn test_load_from_device() -> anyhow::Result<()> {
#[test] #[test]
fn test_load_from_slot() -> anyhow::Result<()> { fn test_load_from_slot() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device airCon = "d0"; device airCon = "d0";
@@ -168,8 +204,14 @@ fn test_load_from_slot() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -186,7 +228,7 @@ fn test_load_from_slot() -> anyhow::Result<()> {
#[test] #[test]
fn test_set_slot() -> anyhow::Result<()> { fn test_set_slot() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device airCon = "d0"; device airCon = "d0";
@@ -194,8 +236,14 @@ fn test_set_slot() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -211,7 +259,7 @@ fn test_set_slot() -> anyhow::Result<()> {
#[test] #[test]
fn test_load_reagent() -> anyhow::Result<()> { fn test_load_reagent() -> anyhow::Result<()> {
let compiled = compile! { let compiled = compile! {
debug check
r#" r#"
device thingy = "d0"; device thingy = "d0";
@@ -219,8 +267,14 @@ fn test_load_reagent() -> anyhow::Result<()> {
"# "#
}; };
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main

View File

@@ -6,14 +6,20 @@ mod test {
#[test] #[test]
fn test_tuple_literal_declaration() -> anyhow::Result<()> { fn test_tuple_literal_declaration() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let (x, y) = (1, 2); let (x, y) = (1, 2);
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -30,14 +36,20 @@ mod test {
#[test] #[test]
fn test_tuple_literal_declaration_with_underscore() -> anyhow::Result<()> { fn test_tuple_literal_declaration_with_underscore() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let (x, _) = (1, 2); let (x, _) = (1, 2);
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -53,7 +65,7 @@ mod test {
#[test] #[test]
fn test_tuple_literal_assignment() -> anyhow::Result<()> { fn test_tuple_literal_assignment() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let x = 0; let x = 0;
let y = 0; let y = 0;
@@ -61,8 +73,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -81,7 +99,7 @@ mod test {
#[test] #[test]
fn test_tuple_literal_with_variables() -> anyhow::Result<()> { fn test_tuple_literal_with_variables() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let a = 42; let a = 42;
let b = 99; let b = 99;
@@ -89,8 +107,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -109,14 +133,20 @@ mod test {
#[test] #[test]
fn test_tuple_literal_three_elements() -> anyhow::Result<()> { fn test_tuple_literal_three_elements() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let (x, y, z) = (1, 2, 3); let (x, y, z) = (1, 2, 3);
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -134,7 +164,7 @@ mod test {
#[test] #[test]
fn test_tuple_literal_assignment_with_underscore() -> anyhow::Result<()> { fn test_tuple_literal_assignment_with_underscore() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let i = 0; let i = 0;
let x = 123; let x = 123;
@@ -142,8 +172,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -161,7 +197,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_simple() -> anyhow::Result<()> { fn test_tuple_return_simple() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getPair() { fn getPair() {
return (10, 20); return (10, 20);
@@ -170,8 +206,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -199,7 +241,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_with_underscore() -> anyhow::Result<()> { fn test_tuple_return_with_underscore() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getPair() { fn getPair() {
return (5, 15); return (5, 15);
@@ -208,8 +250,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -237,7 +285,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_three_elements() -> anyhow::Result<()> { fn test_tuple_return_three_elements() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getTriple() { fn getTriple() {
return (1, 2, 3); return (1, 2, 3);
@@ -246,8 +294,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -277,7 +331,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_assignment() -> anyhow::Result<()> { fn test_tuple_return_assignment() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getPair() { fn getPair() {
return (42, 84); return (42, 84);
@@ -288,8 +342,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -346,7 +406,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_called_by_non_tuple_return() -> anyhow::Result<()> { fn test_tuple_return_called_by_non_tuple_return() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn doSomething() { fn doSomething() {
return (1, 2); return (1, 2);
@@ -361,8 +421,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -399,7 +465,7 @@ mod test {
#[test] #[test]
fn test_non_tuple_return_called_by_tuple_return() -> anyhow::Result<()> { fn test_non_tuple_return_called_by_tuple_return() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getValue() { fn getValue() {
return 42; return 42;
@@ -414,8 +480,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -471,7 +543,7 @@ mod test {
#[test] #[test]
fn test_multiple_tuple_returns_in_function() -> anyhow::Result<()> { fn test_multiple_tuple_returns_in_function() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getValue(x) { fn getValue(x) {
if (x) { if (x) {
@@ -485,8 +557,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -528,7 +606,7 @@ mod test {
#[test] #[test]
fn test_tuple_return_with_expression() -> anyhow::Result<()> { fn test_tuple_return_with_expression() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn add(x, y) { fn add(x, y) {
return (x, y); return (x, y);
@@ -538,8 +616,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -571,7 +655,7 @@ mod test {
#[test] #[test]
fn test_nested_function_tuple_calls() -> anyhow::Result<()> { fn test_nested_function_tuple_calls() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn inner() { fn inner() {
return (1, 2); return (1, 2);
@@ -586,8 +670,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -628,14 +718,20 @@ mod test {
#[test] #[test]
fn test_tuple_literal_with_constant_expressions() -> anyhow::Result<()> { fn test_tuple_literal_with_constant_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let (a, b) = (1 + 2, 3 * 4); let (a, b) = (1 + 2, 3 * 4);
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -652,7 +748,7 @@ mod test {
#[test] #[test]
fn test_tuple_literal_with_variable_expressions() -> anyhow::Result<()> { fn test_tuple_literal_with_variable_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let x = 5; let x = 5;
let y = 10; let y = 10;
@@ -660,8 +756,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -682,7 +784,7 @@ mod test {
#[test] #[test]
fn test_tuple_assignment_with_expressions() -> anyhow::Result<()> { fn test_tuple_assignment_with_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let a = 0; let a = 0;
let b = 0; let b = 0;
@@ -691,8 +793,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -714,7 +822,7 @@ mod test {
#[test] #[test]
fn test_tuple_literal_with_function_calls() -> anyhow::Result<()> { fn test_tuple_literal_with_function_calls() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getValue() { return 42; }; fn getValue() { return 42; };
fn getOther() { return 99; }; fn getOther() { return 99; };
@@ -723,8 +831,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -765,7 +879,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_logical_expressions() -> anyhow::Result<()> { fn test_tuple_with_logical_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let x = 1; let x = 1;
let y = 0; let y = 0;
@@ -773,8 +887,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -795,7 +915,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_comparison_expressions() -> anyhow::Result<()> { fn test_tuple_with_comparison_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
let x = 5; let x = 5;
let y = 10; let y = 10;
@@ -803,8 +923,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -825,7 +951,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_device_property_access() -> anyhow::Result<()> { fn test_tuple_with_device_property_access() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
device sensor = "d0"; device sensor = "d0";
device display = "d1"; device display = "d1";
@@ -834,8 +960,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -854,7 +986,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_device_property_and_function_call() -> anyhow::Result<()> { fn test_tuple_with_device_property_and_function_call() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
device self = "db"; device self = "db";
@@ -866,8 +998,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -898,7 +1036,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_function_call_expressions() -> anyhow::Result<()> { fn test_tuple_with_function_call_expressions() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn getValue() { return 10; } fn getValue() { return 10; }
fn getOther() { return 20; } fn getOther() { return 20; }
@@ -907,8 +1045,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main
@@ -951,7 +1095,7 @@ mod test {
#[test] #[test]
fn test_tuple_with_stack_spillover() -> anyhow::Result<()> { fn test_tuple_with_stack_spillover() -> anyhow::Result<()> {
let compiled = compile!( let compiled = compile!(
debug check
r#" r#"
fn get8() { fn get8() {
return (1, 2, 3, 4, 5, 6, 7, 8); return (1, 2, 3, 4, 5, 6, 7, 8);
@@ -962,8 +1106,14 @@ mod test {
"# "#
); );
assert!(
compiled.errors.is_empty(),
"Expected no errors, got: {:?}",
compiled.errors
);
assert_eq!( assert_eq!(
compiled, compiled.output,
indoc! { indoc! {
" "
j main j main