Add support for the 'while' keyword
This commit is contained in:
@@ -85,3 +85,63 @@ fn variable_declaration_negative() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolean_declaration() -> anyhow::Result<()> {
|
||||
let compiled = compile! {
|
||||
debug
|
||||
"
|
||||
let t = true;
|
||||
let f = false;
|
||||
"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
compiled,
|
||||
indoc! {
|
||||
"
|
||||
j main
|
||||
main:
|
||||
move r8 1 #t
|
||||
move r9 0 #f
|
||||
"
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolean_return() -> anyhow::Result<()> {
|
||||
let compiled = compile! {
|
||||
debug
|
||||
"
|
||||
fn getTrue() {
|
||||
return true;
|
||||
};
|
||||
|
||||
let val = getTrue();
|
||||
"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
compiled,
|
||||
indoc! {
|
||||
"
|
||||
j main
|
||||
getTrue:
|
||||
push ra
|
||||
move r15 1 #returnValue
|
||||
sub r0 sp 1
|
||||
get ra db r0
|
||||
sub sp sp 1
|
||||
j ra
|
||||
main:
|
||||
jal getTrue
|
||||
move r8 r15 #val
|
||||
"
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -110,7 +110,65 @@ fn test_math_with_logic() -> anyhow::Result<()> {
|
||||
compiled,
|
||||
indoc! {
|
||||
"
|
||||
|
||||
j main
|
||||
main:
|
||||
add r1 1 2
|
||||
sgt r2 r1 1
|
||||
move r8 r2 #logic
|
||||
"
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolean_in_logic() -> anyhow::Result<()> {
|
||||
let compiled = compile! {
|
||||
debug
|
||||
"
|
||||
let res = true && false;
|
||||
"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
compiled,
|
||||
indoc! {
|
||||
"
|
||||
j main
|
||||
main:
|
||||
and r1 1 0
|
||||
move r8 r1 #res
|
||||
"
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invert_a_boolean() -> anyhow::Result<()> {
|
||||
let compiled = compile! {
|
||||
debug
|
||||
"
|
||||
let i = true;
|
||||
let y = !i;
|
||||
|
||||
let result = y == false;
|
||||
"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
compiled,
|
||||
indoc! {
|
||||
"
|
||||
j main
|
||||
main:
|
||||
move r8 1 #i
|
||||
seq r1 r8 0
|
||||
move r9 r1 #y
|
||||
seq r2 r9 0
|
||||
move r10 r2 #result
|
||||
"
|
||||
}
|
||||
);
|
||||
|
||||
@@ -178,6 +178,16 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
||||
temp_name: Some(temp_name),
|
||||
}))
|
||||
}
|
||||
Expression::Literal(Literal::Boolean(b)) => {
|
||||
let val = if b { "1" } else { "0" };
|
||||
let temp_name = self.next_temp_name();
|
||||
let loc = scope.add_variable(&temp_name, LocationRequest::Temp)?;
|
||||
self.emit_variable_assignment(&temp_name, &loc, val)?;
|
||||
Ok(Some(CompilationResult {
|
||||
location: loc,
|
||||
temp_name: Some(temp_name),
|
||||
}))
|
||||
}
|
||||
Expression::Variable(name) => {
|
||||
let loc = scope.get_location_of(&name)?;
|
||||
Ok(Some(CompilationResult {
|
||||
@@ -258,6 +268,14 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
||||
self.emit_variable_assignment(&var_name, &var_location, num)?;
|
||||
var_location
|
||||
}
|
||||
Expression::Literal(Literal::Boolean(b)) => {
|
||||
let val = if b { "1" } else { "0" };
|
||||
let var_location =
|
||||
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
|
||||
|
||||
self.emit_variable_assignment(&var_name, &var_location, val)?;
|
||||
var_location
|
||||
}
|
||||
Expression::Invocation(invoke_expr) => {
|
||||
self.expression_function_invocation(invoke_expr, scope)?;
|
||||
|
||||
@@ -364,6 +382,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
||||
let num_str = num.to_string();
|
||||
self.write_output(format!("push {num_str}"))?;
|
||||
}
|
||||
Expression::Literal(Literal::Boolean(b)) => {
|
||||
let val = if b { "1" } else { "0" };
|
||||
self.write_output(format!("push {val}"))?;
|
||||
}
|
||||
Expression::Variable(var_name) => match stack.get_location_of(var_name)? {
|
||||
VariableLocation::Persistant(reg) | VariableLocation::Temporary(reg) => {
|
||||
self.write_output(format!("push r{reg}"))?;
|
||||
@@ -471,6 +493,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
||||
return Ok((n.to_string(), None));
|
||||
}
|
||||
|
||||
// Optimization for boolean literals
|
||||
if let Expression::Literal(Literal::Boolean(b)) = expr {
|
||||
return Ok((if b { "1".to_string() } else { "0".to_string() }, None));
|
||||
}
|
||||
|
||||
// Optimization for negated literals used as operands.
|
||||
// E.g., `1 + -2` -> return "-2" string, no register used.
|
||||
if let Expression::Negation(inner) = &expr
|
||||
@@ -705,6 +732,14 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
||||
num,
|
||||
)?;
|
||||
}
|
||||
Expression::Literal(Literal::Boolean(b)) => {
|
||||
let val = if b { "1" } else { "0" };
|
||||
self.emit_variable_assignment(
|
||||
"returnValue",
|
||||
&VariableLocation::Persistant(VariableScope::RETURN_REGISTER),
|
||||
val,
|
||||
)?;
|
||||
}
|
||||
Expression::Binary(bin_expr) => {
|
||||
let result = self.expression_binary(bin_expr, scope)?;
|
||||
let result_reg = self.resolve_register(&result.location)?;
|
||||
|
||||
Reference in New Issue
Block a user