diff --git a/libs/compiler/src/test/syscall.rs b/libs/compiler/src/test/syscall.rs index 03f4f57..f833639 100644 --- a/libs/compiler/src/test/syscall.rs +++ b/libs/compiler/src/test/syscall.rs @@ -81,3 +81,29 @@ fn test_set_on_device() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn test_load_from_device() -> anyhow::Result<()> { + let compiled = compile! { + debug + r#" + device airCon = "d0"; + + let setting = loadFromDevice(airCon, "On"); + "# + }; + + assert_eq!( + compiled, + indoc! { + " + j main + main: + l r15 d0 On + move r8 r15 #setting + " + } + ); + + Ok(()) +} diff --git a/libs/compiler/src/v1.rs b/libs/compiler/src/v1.rs index 27c0632..370f02e 100644 --- a/libs/compiler/src/v1.rs +++ b/libs/compiler/src/v1.rs @@ -154,11 +154,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { Ok(None) } Expression::Syscall(SysCall::System(system_syscall)) => { - let res = self.expression_syscall_system(system_syscall, scope)?; - Ok(res.map(|l| CompilationResult { - location: l, - temp_name: None, - })) + self.expression_syscall_system(system_syscall, scope) } Expression::While(expr_while) => { self.expression_while(expr_while, scope)?; @@ -177,11 +173,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { Ok(None) } Expression::Declaration(var_name, expr) => { - let loc = self.expression_declaration(var_name, *expr, scope)?; - Ok(loc.map(|l| CompilationResult { - location: l, - temp_name: None, - })) + self.expression_declaration(var_name, *expr, scope) } Expression::Assignment(assign_expr) => { self.expression_assignment(assign_expr, scope)?; @@ -292,23 +284,26 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { var_name: String, expr: Expression, scope: &mut VariableScope<'v>, - ) -> Result, Error> { + ) -> Result, Error> { // optimization. Check for a negated numeric literal if let Expression::Negation(box_expr) = &expr && let Expression::Literal(Literal::Number(neg_num)) = &**box_expr { let loc = scope.add_variable(&var_name, LocationRequest::Persist)?; self.emit_variable_assignment(&var_name, &loc, format!("-{neg_num}"))?; - return Ok(Some(loc)); + return Ok(Some(CompilationResult { + location: loc, + temp_name: None, + })); } - let loc = match expr { + let (loc, temp_name) = match expr { Expression::Literal(Literal::Number(num)) => { let var_location = scope.add_variable(var_name.clone(), LocationRequest::Persist)?; self.emit_variable_assignment(&var_name, &var_location, num)?; - var_location + (var_location, None) } Expression::Literal(Literal::Boolean(b)) => { let val = if b { "1" } else { "0" }; @@ -316,7 +311,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { scope.add_variable(var_name.clone(), LocationRequest::Persist)?; self.emit_variable_assignment(&var_name, &var_location, val)?; - var_location + (var_location, None) } Expression::Invocation(invoke_expr) => { self.expression_function_invocation(invoke_expr, scope)?; @@ -327,7 +322,21 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { &loc, format!("r{}", VariableScope::RETURN_REGISTER), )?; - loc + (loc, None) + } + Expression::Syscall(SysCall::System(call)) => { + if self.expression_syscall_system(call, scope)?.is_none() { + return Err(Error::Unknown("SysCall did not return a value".into())); + }; + + let loc = scope.add_variable(&var_name, LocationRequest::Persist)?; + self.emit_variable_assignment( + &var_name, + &loc, + format!("r{}", VariableScope::RETURN_REGISTER), + )?; + + (loc, None) } // Support assigning binary expressions to variables directly Expression::Binary(bin_expr) => { @@ -342,7 +351,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { if let Some(name) = result.temp_name { scope.free_temp(name)?; } - var_loc + (var_loc, None) } Expression::Logical(log_expr) => { let result = self.expression_logical(log_expr, scope)?; @@ -356,7 +365,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { if let Some(name) = result.temp_name { scope.free_temp(name)?; } - var_loc + (var_loc, None) } Expression::Variable(name) => { let src_loc = scope.get_location_of(&name)?; @@ -380,7 +389,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } }; self.emit_variable_assignment(&var_name, &var_loc, src_str)?; - var_loc + (var_loc, None) } Expression::Priority(inner) => { return self.expression_declaration(var_name, *inner, scope); @@ -392,7 +401,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } }; - Ok(Some(loc)) + Ok(Some(CompilationResult { + location: loc, + temp_name, + })) } fn expression_assignment<'v>( @@ -998,11 +1010,13 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { Ok(VariableLocation::Persistant(VariableScope::RETURN_REGISTER)) } + // syscalls that return values will be stored in the VariableScope::RETURN_REGISTER + // register fn expression_syscall_system<'v>( &mut self, expr: System, scope: &mut VariableScope<'v>, - ) -> Result, Error> { + ) -> Result, Error> { match expr { System::Yield => { self.write_output("yield")?; @@ -1061,7 +1075,17 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { )); }; - todo!() + self.write_output(format!( + "l r{} {} {}", + VariableScope::RETURN_REGISTER, + device, + logic_type + ))?; + + Ok(Some(CompilationResult { + location: VariableLocation::Temporary(VariableScope::RETURN_REGISTER), + temp_name: None, + })) } _ => {