Compilation errors solved

This commit is contained in:
2025-11-30 16:11:54 -07:00
parent 15603f8bbe
commit c5c4cfdc64
5 changed files with 150 additions and 93 deletions

View File

@@ -1,3 +1,4 @@
#![allow(clippy::result_large_err)]
use crate::variable_manager::{self, LocationRequest, VariableLocation, VariableScope}; use crate::variable_manager::{self, LocationRequest, VariableLocation, VariableScope};
use parser::{ use parser::{
Parser as ASTParser, Parser as ASTParser,
@@ -115,9 +116,27 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
let Some(expr) = expr else { return Ok(()) }; let Some(expr) = expr else { return Ok(()) };
// Wrap the root expression in a dummy span for consistency,
// since parse_all returns an unspanned Expression (usually Block)
// that contains spanned children.
// We know parse_all returns Expression::Block which has an internal span,
// but for type consistency we wrap it.
let span = if let Expression::Block(ref block) = expr {
block.span
} else {
Span {
start_line: 0,
end_line: 0,
start_col: 0,
end_col: 0,
}
};
let spanned_root = Spanned { node: expr, span };
self.write_output("j main")?; self.write_output("j main")?;
// We ignore the result of the root expression (usually a block) // We ignore the result of the root expression (usually a block)
let _ = self.expression(expr, &mut VariableScope::default())?; let _ = self.expression(spanned_root, &mut VariableScope::default())?;
Ok(()) Ok(())
} }
@@ -141,10 +160,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
fn expression<'v>( fn expression<'v>(
&mut self, &mut self,
expr: Expression, expr: Spanned<Expression>,
scope: &mut VariableScope<'v>, scope: &mut VariableScope<'v>,
) -> Result<Option<CompilationResult>, Error> { ) -> Result<Option<CompilationResult>, Error> {
match expr { match expr.node {
Expression::Function(expr_func) => { Expression::Function(expr_func) => {
self.expression_function(expr_func, scope)?; self.expression_function(expr_func, scope)?;
Ok(None) Ok(None)
@@ -161,9 +180,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.expression_loop(expr_loop.node, scope)?; self.expression_loop(expr_loop.node, scope)?;
Ok(None) Ok(None)
} }
Expression::Syscall(spanned_syscall) => { Expression::Syscall(Spanned {
self.expression_syscall_system(spanned_syscall.node, spanned_syscall.span, scope) node: SysCall::System(system),
} span,
}) => self.expression_syscall_system(system, span, scope),
Expression::While(expr_while) => { Expression::While(expr_while) => {
self.expression_while(expr_while.node, scope)?; self.expression_while(expr_while.node, scope)?;
Ok(None) Ok(None)
@@ -180,8 +200,9 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.expression_device(expr_dev.node, expr_dev.span)?; self.expression_device(expr_dev.node, expr_dev.span)?;
Ok(None) Ok(None)
} }
Expression::Declaration(var_name, expr) => { Expression::Declaration(var_name, decl_expr) => {
self.expression_declaration(var_name, **expr, scope) // decl_expr is Box<Spanned<Expression>>
self.expression_declaration(var_name, *decl_expr, scope)
} }
Expression::Assignment(assign_expr) => { Expression::Assignment(assign_expr) => {
self.expression_assignment(assign_expr.node, scope)?; self.expression_assignment(assign_expr.node, scope)?;
@@ -204,11 +225,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
})) }))
} }
Expression::Binary(bin_expr) => { Expression::Binary(bin_expr) => {
let result = self.expression_binary(bin_expr.node, scope)?; let result = self.expression_binary(bin_expr, scope)?;
Ok(Some(result)) Ok(Some(result))
} }
Expression::Logical(log_expr) => { Expression::Logical(log_expr) => {
let result = self.expression_logical(log_expr.node, scope)?; let result = self.expression_logical(log_expr, scope)?;
Ok(Some(result)) Ok(Some(result))
} }
Expression::Literal(spanned_lit) => match spanned_lit.node { Expression::Literal(spanned_lit) => match spanned_lit.node {
@@ -242,7 +263,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
temp_name: None, // User variable, do not free temp_name: None, // User variable, do not free
})) }))
} }
Expression::Priority(inner_expr) => self.expression(**inner_expr, scope), Expression::Priority(inner_expr) => self.expression(*inner_expr, scope),
Expression::Negation(inner_expr) => { Expression::Negation(inner_expr) => {
// Compile negation as 0 - inner // Compile negation as 0 - inner
let (inner_str, cleanup) = self.compile_operand(*inner_expr, scope)?; let (inner_str, cleanup) = self.compile_operand(*inner_expr, scope)?;
@@ -264,9 +285,9 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
_ => Err(Error::Unknown( _ => Err(Error::Unknown(
format!( format!(
"Expression type not yet supported in general expression context: {:?}", "Expression type not yet supported in general expression context: {:?}",
expr expr.node
), ),
None, Some(expr.span),
)), )),
} }
} }
@@ -298,15 +319,15 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
fn expression_declaration<'v>( fn expression_declaration<'v>(
&mut self, &mut self,
var_name: Spanned<String>, var_name: Spanned<String>,
expr: Expression, expr: Spanned<Expression>,
scope: &mut VariableScope<'v>, scope: &mut VariableScope<'v>,
) -> Result<Option<CompilationResult>, Error> { ) -> Result<Option<CompilationResult>, Error> {
let name_str = var_name.node; let name_str = var_name.node;
let name_span = var_name.span; let name_span = var_name.span;
// optimization. Check for a negated numeric literal // optimization. Check for a negated numeric literal
if let Expression::Negation(box_expr) = &expr if let Expression::Negation(box_expr) = &expr.node
&& let Expression::Literal(spanned_lit) = &**box_expr && let Expression::Literal(spanned_lit) = &box_expr.node
&& let Literal::Number(neg_num) = &spanned_lit.node && let Literal::Number(neg_num) = &spanned_lit.node
{ {
let loc = scope.add_variable(&name_str, LocationRequest::Persist)?; let loc = scope.add_variable(&name_str, LocationRequest::Persist)?;
@@ -317,7 +338,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
})); }));
} }
let (loc, temp_name) = match expr { let (loc, temp_name) = match expr.node {
Expression::Literal(spanned_lit) => match spanned_lit.node { Expression::Literal(spanned_lit) => match spanned_lit.node {
Literal::Number(num) => { Literal::Number(num) => {
let var_location = let var_location =
@@ -379,7 +400,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
} }
// Support assigning binary expressions to variables directly // Support assigning binary expressions to variables directly
Expression::Binary(bin_expr) => { Expression::Binary(bin_expr) => {
let result = self.expression_binary(bin_expr.node, scope)?; let result = self.expression_binary(bin_expr, scope)?;
let var_loc = scope.add_variable(&name_str, LocationRequest::Persist)?; let var_loc = scope.add_variable(&name_str, LocationRequest::Persist)?;
// Move result from temp to new persistent variable // Move result from temp to new persistent variable
@@ -393,7 +414,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
(var_loc, None) (var_loc, None)
} }
Expression::Logical(log_expr) => { Expression::Logical(log_expr) => {
let result = self.expression_logical(log_expr.node, scope)?; let result = self.expression_logical(log_expr, scope)?;
let var_loc = scope.add_variable(&name_str, LocationRequest::Persist)?; let var_loc = scope.add_variable(&name_str, LocationRequest::Persist)?;
// Move result from temp to new persistent variable // Move result from temp to new persistent variable
@@ -530,7 +551,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.write_output(format!("push r{register}"))?; self.write_output(format!("push r{register}"))?;
} }
for arg in arguments { for arg in arguments {
match arg { match arg.node {
Expression::Literal(spanned_lit) => match spanned_lit.node { Expression::Literal(spanned_lit) => match spanned_lit.node {
Literal::Number(num) => { Literal::Number(num) => {
let num_str = num.to_string(); let num_str = num.to_string();
@@ -569,7 +590,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
} }
Expression::Binary(bin_expr) => { Expression::Binary(bin_expr) => {
// Compile the binary expression to a temp register // Compile the binary expression to a temp register
let result = self.expression_binary(bin_expr.node, stack)?; let result = self.expression_binary(bin_expr, stack)?;
let reg_str = self.resolve_register(&result.location)?; let reg_str = self.resolve_register(&result.location)?;
self.write_output(format!("push {reg_str}"))?; self.write_output(format!("push {reg_str}"))?;
if let Some(name) = result.temp_name { if let Some(name) = result.temp_name {
@@ -578,7 +599,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
} }
Expression::Logical(log_expr) => { Expression::Logical(log_expr) => {
// Compile the logical expression to a temp register // Compile the logical expression to a temp register
let result = self.expression_logical(log_expr.node, stack)?; let result = self.expression_logical(log_expr, stack)?;
let reg_str = self.resolve_register(&result.location)?; let reg_str = self.resolve_register(&result.location)?;
self.write_output(format!("push {reg_str}"))?; self.write_output(format!("push {reg_str}"))?;
if let Some(name) = result.temp_name { if let Some(name) = result.temp_name {
@@ -603,7 +624,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
for register in active_registers { for register in active_registers {
let VariableLocation::Stack(stack_offset) = stack let VariableLocation::Stack(stack_offset) = stack
.get_location_of(format!("temp_{register}")) .get_location_of(format!("temp_{register}"))
.map_err(|e| Error::ScopeError(e))? .map_err(Error::ScopeError)?
else { else {
// This shouldn't happen if we just added it // This shouldn't happen if we just added it
return Err(Error::Unknown( return Err(Error::Unknown(
@@ -672,7 +693,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.write_output(format!("j {end_label}"))?; self.write_output(format!("j {end_label}"))?;
self.write_output(format!("{else_label}:"))?; self.write_output(format!("{else_label}:"))?;
match *expr.else_branch.unwrap() { match expr.else_branch.unwrap().node {
Expression::Block(block) => self.expression_block(block.node, scope)?, Expression::Block(block) => self.expression_block(block.node, scope)?,
Expression::If(if_expr) => self.expression_if(if_expr.node, scope)?, Expression::If(if_expr) => self.expression_if(if_expr.node, scope)?,
_ => unreachable!("Parser ensures else branch is Block or If"), _ => unreachable!("Parser ensures else branch is Block or If"),
@@ -789,11 +810,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
/// so the caller can free it. /// so the caller can free it.
fn compile_operand( fn compile_operand(
&mut self, &mut self,
expr: Expression, expr: Spanned<Expression>,
scope: &mut VariableScope, scope: &mut VariableScope,
) -> Result<(String, Option<String>), Error> { ) -> Result<(String, Option<String>), Error> {
// Optimization for literals // Optimization for literals
if let Expression::Literal(spanned_lit) = &expr { if let Expression::Literal(spanned_lit) = &expr.node {
if let Literal::Number(n) = spanned_lit.node { if let Literal::Number(n) = spanned_lit.node {
return Ok((n.to_string(), None)); return Ok((n.to_string(), None));
} }
@@ -804,8 +825,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
// Optimization for negated literals used as operands. // Optimization for negated literals used as operands.
// E.g., `1 + -2` -> return "-2" string, no register used. // E.g., `1 + -2` -> return "-2" string, no register used.
if let Expression::Negation(inner) = &expr if let Expression::Negation(inner) = &expr.node
&& let Expression::Literal(spanned_lit) = &**inner && let Expression::Literal(spanned_lit) = &inner.node
&& let Literal::Number(n) = spanned_lit.node && let Literal::Number(n) = spanned_lit.node
{ {
return Ok((format!("-{}", n), None)); return Ok((format!("-{}", n), None));
@@ -848,36 +869,35 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
val: LiteralOrVariable, val: LiteralOrVariable,
scope: &mut VariableScope, scope: &mut VariableScope,
) -> Result<(String, Option<String>), Error> { ) -> Result<(String, Option<String>), Error> {
let expr = match val {
LiteralOrVariable::Literal(l) => {
// We need to manufacture a spanned literal
// Since this method is usually called from contexts where we lost the original span
// (Syscall enums don't keep span on inner literals usually, but we passed span to expression_syscall_system)
// Actually, LiteralOrVariable stores Spanned<String> for variables, but Literals are just Literal.
// We'll create a dummy span for the Literal if we have to wrap it back in Expression.
// Or better, just handle logic here.
let dummy_span = Span { let dummy_span = Span {
start_line: 0, start_line: 0,
start_col: 0, start_col: 0,
end_line: 0, end_line: 0,
end_col: 0, end_col: 0,
}; };
Expression::Literal(Spanned {
let expr = match val {
LiteralOrVariable::Literal(l) => Expression::Literal(Spanned {
node: l, node: l,
span: dummy_span, span: dummy_span,
}) }),
}
LiteralOrVariable::Variable(v) => Expression::Variable(v), LiteralOrVariable::Variable(v) => Expression::Variable(v),
}; };
self.compile_operand(expr, scope) self.compile_operand(
Spanned {
node: expr,
span: dummy_span,
},
scope,
)
} }
fn expression_binary<'v>( fn expression_binary<'v>(
&mut self, &mut self,
expr: BinaryExpression, expr: Spanned<BinaryExpression>,
scope: &mut VariableScope<'v>, scope: &mut VariableScope<'v>,
) -> Result<CompilationResult, Error> { ) -> Result<CompilationResult, Error> {
let (op_str, left_expr, right_expr) = match expr { let (op_str, left_expr, right_expr) = match expr.node {
BinaryExpression::Add(l, r) => ("add", l, r), BinaryExpression::Add(l, r) => ("add", l, r),
BinaryExpression::Multiply(l, r) => ("mul", l, r), BinaryExpression::Multiply(l, r) => ("mul", l, r),
BinaryExpression::Divide(l, r) => ("div", l, r), BinaryExpression::Divide(l, r) => ("div", l, r),
@@ -915,10 +935,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
fn expression_logical<'v>( fn expression_logical<'v>(
&mut self, &mut self,
expr: LogicalExpression, expr: Spanned<LogicalExpression>,
scope: &mut VariableScope<'v>, scope: &mut VariableScope<'v>,
) -> Result<CompilationResult, Error> { ) -> Result<CompilationResult, Error> {
match expr { match expr.node {
LogicalExpression::Not(inner) => { LogicalExpression::Not(inner) => {
let (inner_str, cleanup) = self.compile_operand(*inner, scope)?; let (inner_str, cleanup) = self.compile_operand(*inner, scope)?;
@@ -939,7 +959,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
}) })
} }
_ => { _ => {
let (op_str, left_expr, right_expr) = match expr { let (op_str, left_expr, right_expr) = match expr.node {
LogicalExpression::And(l, r) => ("and", l, r), LogicalExpression::And(l, r) => ("and", l, r),
LogicalExpression::Or(l, r) => ("or", l, r), LogicalExpression::Or(l, r) => ("or", l, r),
LogicalExpression::Equal(l, r) => ("seq", l, r), LogicalExpression::Equal(l, r) => ("seq", l, r),
@@ -1012,7 +1032,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.expression_return(*ret_expr, scope)?; self.expression_return(*ret_expr, scope)?;
} }
_ => { _ => {
let result = self.expression(expr.node, scope)?; let result = self.expression(expr, scope)?;
// If the expression was a statement that returned a temp result (e.g. `1 + 2;` line), // If the expression was a statement that returned a temp result (e.g. `1 + 2;` line),
// we must free it to avoid leaking registers. // we must free it to avoid leaking registers.
if let Some(comp_res) = result if let Some(comp_res) = result
@@ -1030,11 +1050,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
/// Takes the result of the expression and stores it in VariableScope::RETURN_REGISTER /// Takes the result of the expression and stores it in VariableScope::RETURN_REGISTER
fn expression_return<'v>( fn expression_return<'v>(
&mut self, &mut self,
expr: Expression, expr: Spanned<Expression>,
scope: &mut VariableScope<'v>, scope: &mut VariableScope<'v>,
) -> Result<VariableLocation, Error> { ) -> Result<VariableLocation, Error> {
if let Expression::Negation(neg_expr) = &expr if let Expression::Negation(neg_expr) = &expr.node
&& let Expression::Literal(spanned_lit) = &**neg_expr && let Expression::Literal(spanned_lit) = &neg_expr.node
&& let Literal::Number(neg_num) = &spanned_lit.node && let Literal::Number(neg_num) = &spanned_lit.node
{ {
let loc = VariableLocation::Persistant(VariableScope::RETURN_REGISTER); let loc = VariableLocation::Persistant(VariableScope::RETURN_REGISTER);
@@ -1042,7 +1062,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
return Ok(loc); return Ok(loc);
}; };
match expr { match expr.node {
Expression::Variable(var_name) => match scope Expression::Variable(var_name) => match scope
.get_location_of(&var_name.node) .get_location_of(&var_name.node)
.map_err(|_| Error::UnknownIdentifier(var_name.node, var_name.span))? .map_err(|_| Error::UnknownIdentifier(var_name.node, var_name.span))?
@@ -1085,7 +1105,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
_ => {} _ => {}
}, },
Expression::Binary(bin_expr) => { Expression::Binary(bin_expr) => {
let result = self.expression_binary(bin_expr.node, scope)?; let result = self.expression_binary(bin_expr, scope)?;
let result_reg = self.resolve_register(&result.location)?; let result_reg = self.resolve_register(&result.location)?;
self.write_output(format!( self.write_output(format!(
"move r{} {}", "move r{} {}",
@@ -1097,7 +1117,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
} }
} }
Expression::Logical(log_expr) => { Expression::Logical(log_expr) => {
let result = self.expression_logical(log_expr.node, scope)?; let result = self.expression_logical(log_expr, scope)?;
let result_reg = self.resolve_register(&result.location)?; let result_reg = self.resolve_register(&result.location)?;
self.write_output(format!( self.write_output(format!(
"move r{} {}", "move r{} {}",
@@ -1336,7 +1356,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
self.expression_return(*ret_expr, &mut block_scope)?; self.expression_return(*ret_expr, &mut block_scope)?;
} }
_ => { _ => {
let result = self.expression(expr.node, &mut block_scope)?; let result = self.expression(expr, &mut block_scope)?;
// Free unused statement results // Free unused statement results
if let Some(comp_res) = result if let Some(comp_res) = result
&& let Some(name) = comp_res.temp_name && let Some(name) = comp_res.temp_name
@@ -1350,7 +1370,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
// Get the saved return address and save it back into `ra` // Get the saved return address and save it back into `ra`
let VariableLocation::Stack(ra_stack_offset) = block_scope let VariableLocation::Stack(ra_stack_offset) = block_scope
.get_location_of(format!("{}_ra", name.node)) .get_location_of(format!("{}_ra", name.node))
.map_err(|e| Error::ScopeError(e))? .map_err(Error::ScopeError)?
else { else {
return Err(Error::Unknown( return Err(Error::Unknown(
"Stored return address not in stack as expected".into(), "Stored return address not in stack as expected".into(),
@@ -1375,4 +1395,3 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
Ok(()) Ok(())
} }
} }

View File

@@ -934,7 +934,7 @@ impl<'a> Parser<'a> {
)); ));
} }
let mut arguments = Vec::<Expression>::new(); let mut arguments = Vec::<Spanned<Expression>>::new();
while !token_matches!( while !token_matches!(
self.get_next()?.ok_or(Error::UnexpectedEOF)?, self.get_next()?.ok_or(Error::UnexpectedEOF)?,
@@ -949,7 +949,7 @@ impl<'a> Parser<'a> {
)); ));
} }
arguments.push(expression.node); arguments.push(expression);
if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma)) if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma))
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen)) && !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
@@ -1308,7 +1308,7 @@ impl<'a> Parser<'a> {
fn syscall(&mut self) -> Result<SysCall, Error> { fn syscall(&mut self) -> Result<SysCall, Error> {
fn check_length( fn check_length(
parser: &Parser, parser: &Parser,
arguments: &[Expression], arguments: &[Spanned<Expression>],
length: usize, length: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
if arguments.len() != length { if arguments.len() != length {
@@ -1323,10 +1323,18 @@ impl<'a> Parser<'a> {
macro_rules! literal_or_variable { macro_rules! literal_or_variable {
($iter:expr) => { ($iter:expr) => {
match $iter { match $iter {
Some(Expression::Literal(literal)) => { Some(expr) => match &expr.node {
Expression::Literal(literal) => {
LiteralOrVariable::Literal(literal.node.clone()) LiteralOrVariable::Literal(literal.node.clone())
} }
Some(Expression::Variable(ident)) => LiteralOrVariable::Variable(ident), Expression::Variable(ident) => LiteralOrVariable::Variable(ident.clone()),
_ => {
return Err(Error::UnexpectedToken(
self.current_span(),
self.current_token.clone().unwrap(),
))
}
},
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
self.current_span(), self.current_span(),
@@ -1360,18 +1368,8 @@ impl<'a> Parser<'a> {
} }
"sleep" => { "sleep" => {
check_length(self, &invocation.arguments, 1)?; check_length(self, &invocation.arguments, 1)?;
// arguments is Vec<Expression>.
let mut arg = invocation.arguments.into_iter(); let mut arg = invocation.arguments.into_iter();
let expr = arg.next().unwrap(); let expr = arg.next().unwrap();
// We need to wrap `expr` into a `Box<Spanned<Expression>>`?
// Wait, System::Sleep takes Box<Expression>.
// Expression variants are Spanned.
// But Expression IS NOT Spanned<Expression>.
// Expression enum contains Spanned<BinaryExpression>, etc.
// But `Expression` itself is the node.
// The issue: `expr` is `Expression` (which is Spanned internally).
// `System::Sleep(Box<Expression>)`.
Ok(SysCall::System(System::Sleep(boxed!(expr)))) Ok(SysCall::System(System::Sleep(boxed!(expr))))
} }
"hash" => { "hash" => {
@@ -1396,7 +1394,8 @@ impl<'a> Parser<'a> {
let next_arg = args.next(); let next_arg = args.next();
let variable = match next_arg { let variable = match next_arg {
Some(Expression::Literal(spanned_lit)) => match spanned_lit.node { Some(expr) => match expr.node {
Expression::Literal(spanned_lit) => match spanned_lit.node {
Literal::String(s) => s, Literal::String(s) => s,
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
@@ -1411,6 +1410,13 @@ impl<'a> Parser<'a> {
self.current_token.clone().unwrap(), self.current_token.clone().unwrap(),
)); ));
} }
},
_ => {
return Err(Error::UnexpectedToken(
self.current_span(),
self.current_token.clone().unwrap(),
));
}
}; };
Ok(SysCall::System(sys_call::System::LoadFromDevice( Ok(SysCall::System(sys_call::System::LoadFromDevice(
@@ -1431,11 +1437,35 @@ impl<'a> Parser<'a> {
boxed!(variable), boxed!(variable),
))) )))
} }
// Fallback for brevity in this response "setOnDeviceBatched" => {
_ => Err(Error::UnsupportedKeyword( check_length(self, &invocation.arguments, 3)?;
let mut args = invocation.arguments.into_iter();
let device_hash = literal_or_variable!(args.next());
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
let variable = args.next().unwrap();
Ok(SysCall::System(sys_call::System::SetOnDeviceBatched(
device_hash,
Literal::String(logic_type.to_string().replace("\"", "")),
boxed!(variable),
)))
}
_ => {
// For Math functions or unknown functions
if SysCall::is_syscall(&invocation.name.node) {
// Attempt to parse as math if applicable, or error if strict
// Here we are falling back to simple handling or error.
// Since Math isn't fully expanded in this snippet, we return Unsupported.
Err(Error::UnsupportedKeyword(
self.current_span(), self.current_span(),
self.current_token.clone().unwrap(), self.current_token.clone().unwrap(),
)), ))
} else {
Err(Error::UnsupportedKeyword(
self.current_span(),
self.current_token.clone().unwrap(),
))
}
}
} }
} }
} }

View File

@@ -1,4 +1,4 @@
use crate::tree_node::{Expression, Literal}; use crate::tree_node::{Expression, Literal, Spanned};
use super::LiteralOrVariable; use super::LiteralOrVariable;
@@ -102,7 +102,7 @@ pub enum System {
/// Represents a function that can be called to sleep for a certain amount of time. /// Represents a function that can be called to sleep for a certain amount of time.
/// ## In Game /// ## In Game
/// `sleep a(r?|num)` /// `sleep a(r?|num)`
Sleep(Box<Expression>), Sleep(Box<Spanned<Expression>>),
/// Gets the in-game hash for a specific prefab name. /// Gets the in-game hash for a specific prefab name.
/// ## In Game /// ## In Game
/// `HASH("prefabName")` /// `HASH("prefabName")`
@@ -120,7 +120,12 @@ pub enum System {
/// lbn r? deviceHash nameHash logicType batchMode /// lbn r? deviceHash nameHash logicType batchMode
/// ## Examples /// ## Examples
/// lbn r0 HASH("StructureWallLight") HASH("wallLight") On Minimum /// lbn r0 HASH("StructureWallLight") HASH("wallLight") On Minimum
LoadBatchNamed(LiteralOrVariable, Box<Expression>, Literal, Literal), LoadBatchNamed(
LiteralOrVariable,
Box<Spanned<Expression>>,
Literal,
Literal,
),
/// Loads a LogicType from all connected network devices, aggregating them via a /// Loads a LogicType from all connected network devices, aggregating them via a
/// batchMode /// batchMode
/// ## In Game /// ## In Game
@@ -133,14 +138,14 @@ pub enum System {
/// `s d? logicType r?` /// `s d? logicType r?`
/// ## Example /// ## Example
/// `s d0 Setting r0` /// `s d0 Setting r0`
SetOnDevice(LiteralOrVariable, Literal, Box<Expression>), SetOnDevice(LiteralOrVariable, Literal, Box<Spanned<Expression>>),
/// Represents a function which stores a setting to all devices that match /// Represents a function which stores a setting to all devices that match
/// the given deviceHash /// the given deviceHash
/// ## In Game /// ## In Game
/// `sb deviceHash logicType r?` /// `sb deviceHash logicType r?`
/// ## Example /// ## Example
/// `sb HASH("Doors") Lock 1` /// `sb HASH("Doors") Lock 1`
SetOnDeviceBatched(LiteralOrVariable, Literal, Box<Expression>), SetOnDeviceBatched(LiteralOrVariable, Literal, Box<Spanned<Expression>>),
/// Represents a function which stores a setting to all devices that match /// Represents a function which stores a setting to all devices that match
/// both the given deviceHash AND the given nameHash /// both the given deviceHash AND the given nameHash
/// ## In Game /// ## In Game
@@ -151,7 +156,7 @@ pub enum System {
LiteralOrVariable, LiteralOrVariable,
LiteralOrVariable, LiteralOrVariable,
Literal, Literal,
Box<Expression>, Box<Spanned<Expression>>,
), ),
} }
@@ -224,3 +229,4 @@ impl SysCall {
) )
} }
} }

View File

@@ -127,7 +127,7 @@ impl std::fmt::Display for BlockExpression {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct InvocationExpression { pub struct InvocationExpression {
pub name: Spanned<String>, pub name: Spanned<String>,
pub arguments: Vec<Expression>, pub arguments: Vec<Spanned<Expression>>,
} }
impl std::fmt::Display for InvocationExpression { impl std::fmt::Display for InvocationExpression {

View File

@@ -1,3 +1,5 @@
#![allow(clippy::result_large_err)]
#[macro_use] #[macro_use]
extern crate quick_error; extern crate quick_error;