wip
This commit is contained in:
@@ -104,8 +104,8 @@ impl<'a> Compiler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_output(&mut self, output: impl Into<String>) -> Result<(), CompileError> {
|
fn write_output(&mut self, output: impl Into<String>) -> Result<(), CompileError> {
|
||||||
self.output.write(output.into().as_bytes())?;
|
self.output.write_all(output.into().as_bytes())?;
|
||||||
self.output.write(b"\n")?;
|
self.output.write_all(b"\n")?;
|
||||||
self.current_line += 1;
|
self.current_line += 1;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -206,7 +206,7 @@ impl<'a> Compiler<'a> {
|
|||||||
compiler.push_stack(&format!("{op}ExpressionLeft"))?;
|
compiler.push_stack(&format!("{op}ExpressionLeft"))?;
|
||||||
}
|
}
|
||||||
Expression::Variable(var_name) => {
|
Expression::Variable(var_name) => {
|
||||||
let var_offset = compiler.get_variable_index(&var_name)?;
|
let var_offset = compiler.get_variable_index(&var_name)? + 1;
|
||||||
compiler.write_output(format!("sub r15 sp {var_offset}"))?;
|
compiler.write_output(format!("sub r15 sp {var_offset}"))?;
|
||||||
compiler.write_output("get r15 db r15")?;
|
compiler.write_output("get r15 db r15")?;
|
||||||
compiler.write_output("push r15")?;
|
compiler.write_output("push r15")?;
|
||||||
@@ -232,7 +232,7 @@ impl<'a> Compiler<'a> {
|
|||||||
compiler.push_stack(&format!("{op}ExpressionRight"))?;
|
compiler.push_stack(&format!("{op}ExpressionRight"))?;
|
||||||
}
|
}
|
||||||
Expression::Variable(var_name) => {
|
Expression::Variable(var_name) => {
|
||||||
let var_offset = compiler.get_variable_index(&var_name)?;
|
let var_offset = compiler.get_variable_index(&var_name)? + 1;
|
||||||
compiler.write_output(format!("sub r15 sp {}", var_offset))?;
|
compiler.write_output(format!("sub r15 sp {}", var_offset))?;
|
||||||
compiler.write_output("get r15 db r15")?;
|
compiler.write_output("get r15 db r15")?;
|
||||||
compiler.write_output("push r15")?;
|
compiler.write_output("push r15")?;
|
||||||
@@ -283,18 +283,16 @@ impl<'a> Compiler<'a> {
|
|||||||
fn invocation_expression(&mut self, expr: InvocationExpression) -> Result<(), CompileError> {
|
fn invocation_expression(&mut self, expr: InvocationExpression) -> Result<(), CompileError> {
|
||||||
let function_name = expr.name;
|
let function_name = expr.name;
|
||||||
|
|
||||||
let function_line = self
|
let function_line = *self
|
||||||
.function_locations
|
.function_locations
|
||||||
.get(&function_name)
|
.get(&function_name)
|
||||||
.ok_or(CompileError::MissingFunction(function_name.clone()))?
|
.ok_or(CompileError::MissingFunction(function_name.clone()))?;
|
||||||
.clone();
|
|
||||||
|
|
||||||
let mut to_write = String::new();
|
let mut to_write = String::new();
|
||||||
|
|
||||||
self.push_stack(&format!("{function_name}ReturnAddress"))?;
|
self.push_stack(&format!("{function_name}ReturnAddress"))?;
|
||||||
|
|
||||||
let mut iter_index = 0;
|
for (iter_index, arg) in expr.arguments.into_iter().enumerate() {
|
||||||
for arg in expr.arguments {
|
|
||||||
match arg {
|
match arg {
|
||||||
Expression::Literal(Literal::Number(num)) => {
|
Expression::Literal(Literal::Number(num)) => {
|
||||||
to_write.push_str(&format!("push {}\n", num));
|
to_write.push_str(&format!("push {}\n", num));
|
||||||
@@ -313,14 +311,12 @@ impl<'a> Compiler<'a> {
|
|||||||
_ => todo!("something is up with the arguments"),
|
_ => todo!("something is up with the arguments"),
|
||||||
}
|
}
|
||||||
self.push_stack(&format!("{function_name}Invocation{iter_index}"))?;
|
self.push_stack(&format!("{function_name}Invocation{iter_index}"))?;
|
||||||
|
|
||||||
iter_index += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// push the return address onto the stack. Current + to write + pushing the return address
|
// push the return address onto the stack. Current + to write + pushing the return address
|
||||||
let return_addr = self.current_line + to_write.lines().count() + 2;
|
let return_addr = self.current_line + to_write.lines().count() + 2;
|
||||||
self.write_output(format!("push {return_addr}"))?;
|
self.write_output(format!("push {return_addr}"))?;
|
||||||
self.output.write(to_write.as_bytes())?;
|
self.output.write_all(to_write.as_bytes())?;
|
||||||
self.current_line = return_addr - 1;
|
self.current_line = return_addr - 1;
|
||||||
|
|
||||||
self.write_output(format!("j {function_line}"))?;
|
self.write_output(format!("j {function_line}"))?;
|
||||||
@@ -336,7 +332,7 @@ impl<'a> Compiler<'a> {
|
|||||||
self.function_locations.insert(func_name, self.current_line);
|
self.function_locations.insert(func_name, self.current_line);
|
||||||
|
|
||||||
for arg in expression.arguments.iter().rev() {
|
for arg in expression.arguments.iter().rev() {
|
||||||
self.push_stack(&arg)?;
|
self.push_stack(arg)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for expr in expression.body.0 {
|
for expr in expression.body.0 {
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ impl Parser {
|
|||||||
// build the expressions and operators vectors
|
// build the expressions and operators vectors
|
||||||
while token_matches!(current_token, TokenType::Symbol(s) if s.is_operator()) {
|
while token_matches!(current_token, TokenType::Symbol(s) if s.is_operator()) {
|
||||||
// We are guaranteed to have an operator symbol here as we checked in the while loop
|
// We are guaranteed to have an operator symbol here as we checked in the while loop
|
||||||
let operator = extract_token_data!(current_token, TokenType::Symbol(ref s), s.clone());
|
let operator = extract_token_data!(current_token, TokenType::Symbol(s), s);
|
||||||
operators.push(operator);
|
operators.push(operator);
|
||||||
self.assign_next()?;
|
self.assign_next()?;
|
||||||
expressions.push(self.get_binary_child_node()?);
|
expressions.push(self.get_binary_child_node()?);
|
||||||
@@ -613,8 +613,8 @@ impl Parser {
|
|||||||
fn literal(&mut self) -> Result<Literal, ParseError> {
|
fn literal(&mut self) -> Result<Literal, ParseError> {
|
||||||
let current_token = token_from_option!(self.current_token);
|
let current_token = token_from_option!(self.current_token);
|
||||||
let literal = match current_token.token_type {
|
let literal = match current_token.token_type {
|
||||||
TokenType::Number(ref num) => Literal::Number(num.clone()),
|
TokenType::Number(num) => Literal::Number(num),
|
||||||
TokenType::String(ref string) => Literal::String(string.clone()),
|
TokenType::String(string) => Literal::String(string),
|
||||||
_ => return Err(ParseError::UnexpectedToken(current_token.clone())),
|
_ => return Err(ParseError::UnexpectedToken(current_token.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -741,15 +741,15 @@ impl Parser {
|
|||||||
|
|
||||||
match invocation.name.as_str() {
|
match invocation.name.as_str() {
|
||||||
// system calls
|
// system calls
|
||||||
"yield" => return Ok(SysCall::System(sys_call::System::Yield)),
|
"yield" => Ok(SysCall::System(sys_call::System::Yield)),
|
||||||
"sleep" => {
|
"sleep" => {
|
||||||
check_length(self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let mut arg = invocation.arguments.iter();
|
let mut arg = invocation.arguments.iter();
|
||||||
let argument = literal_or_variable!(arg.next());
|
let argument = literal_or_variable!(arg.next());
|
||||||
return Ok(SysCall::System(sys_call::System::Sleep(argument)));
|
Ok(SysCall::System(sys_call::System::Sleep(argument)))
|
||||||
}
|
}
|
||||||
"loadFromDevice" => {
|
"loadFromDevice" => {
|
||||||
check_length(&self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.iter();
|
||||||
|
|
||||||
let device = literal_or_variable!(args.next());
|
let device = literal_or_variable!(args.next());
|
||||||
@@ -760,13 +760,13 @@ impl Parser {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
||||||
device,
|
device,
|
||||||
variable.clone(),
|
variable.clone(),
|
||||||
)));
|
)))
|
||||||
}
|
}
|
||||||
"setOnDevice" => {
|
"setOnDevice" => {
|
||||||
check_length(&self, &invocation.arguments, 3)?;
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.iter();
|
||||||
|
|
||||||
let device = literal_or_variable!(args.next());
|
let device = literal_or_variable!(args.next());
|
||||||
@@ -781,95 +781,95 @@ impl Parser {
|
|||||||
|
|
||||||
let variable = literal_or_variable!(args.next());
|
let variable = literal_or_variable!(args.next());
|
||||||
|
|
||||||
return Ok(SysCall::System(sys_call::System::SetOnDevice(
|
Ok(SysCall::System(sys_call::System::SetOnDevice(
|
||||||
device, logic_type, variable,
|
device, logic_type, variable,
|
||||||
)));
|
)))
|
||||||
}
|
}
|
||||||
// math calls
|
// math calls
|
||||||
"acos" => {
|
"acos" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Acos(arg)));
|
Ok(SysCall::Math(sys_call::Math::Acos(arg)))
|
||||||
}
|
}
|
||||||
"asin" => {
|
"asin" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Asin(arg)));
|
Ok(SysCall::Math(sys_call::Math::Asin(arg)))
|
||||||
}
|
}
|
||||||
"atan" => {
|
"atan" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Atan(arg)));
|
Ok(SysCall::Math(sys_call::Math::Atan(arg)))
|
||||||
}
|
}
|
||||||
"atan2" => {
|
"atan2" => {
|
||||||
check_length(&self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.iter();
|
||||||
let arg1 = literal_or_variable!(args.next());
|
let arg1 = literal_or_variable!(args.next());
|
||||||
let arg2 = literal_or_variable!(args.next());
|
let arg2 = literal_or_variable!(args.next());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Atan2(arg1, arg2)));
|
Ok(SysCall::Math(sys_call::Math::Atan2(arg1, arg2)))
|
||||||
}
|
}
|
||||||
"abs" => {
|
"abs" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Abs(arg)));
|
Ok(SysCall::Math(sys_call::Math::Abs(arg)))
|
||||||
}
|
}
|
||||||
"ceil" => {
|
"ceil" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Ceil(arg)));
|
Ok(SysCall::Math(sys_call::Math::Ceil(arg)))
|
||||||
}
|
}
|
||||||
"cos" => {
|
"cos" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Cos(arg)));
|
Ok(SysCall::Math(sys_call::Math::Cos(arg)))
|
||||||
}
|
}
|
||||||
"floor" => {
|
"floor" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Floor(arg)));
|
Ok(SysCall::Math(sys_call::Math::Floor(arg)))
|
||||||
}
|
}
|
||||||
"log" => {
|
"log" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Log(arg)));
|
Ok(SysCall::Math(sys_call::Math::Log(arg)))
|
||||||
}
|
}
|
||||||
"max" => {
|
"max" => {
|
||||||
check_length(&self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.iter();
|
||||||
let arg1 = literal_or_variable!(args.next());
|
let arg1 = literal_or_variable!(args.next());
|
||||||
let arg2 = literal_or_variable!(args.next());
|
let arg2 = literal_or_variable!(args.next());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Max(arg1, arg2)));
|
Ok(SysCall::Math(sys_call::Math::Max(arg1, arg2)))
|
||||||
}
|
}
|
||||||
"min" => {
|
"min" => {
|
||||||
check_length(&self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.iter();
|
||||||
let arg1 = literal_or_variable!(args.next());
|
let arg1 = literal_or_variable!(args.next());
|
||||||
let arg2 = literal_or_variable!(args.next());
|
let arg2 = literal_or_variable!(args.next());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Min(arg1, arg2)));
|
Ok(SysCall::Math(sys_call::Math::Min(arg1, arg2)))
|
||||||
}
|
}
|
||||||
"rand" => {
|
"rand" => {
|
||||||
check_length(&self, &invocation.arguments, 0)?;
|
check_length(self, &invocation.arguments, 0)?;
|
||||||
return Ok(SysCall::Math(sys_call::Math::Rand));
|
Ok(SysCall::Math(sys_call::Math::Rand))
|
||||||
}
|
}
|
||||||
"sin" => {
|
"sin" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Sin(arg)));
|
Ok(SysCall::Math(sys_call::Math::Sin(arg)))
|
||||||
}
|
}
|
||||||
"sqrt" => {
|
"sqrt" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Sqrt(arg)));
|
Ok(SysCall::Math(sys_call::Math::Sqrt(arg)))
|
||||||
}
|
}
|
||||||
"tan" => {
|
"tan" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Tan(arg)));
|
Ok(SysCall::Math(sys_call::Math::Tan(arg)))
|
||||||
}
|
}
|
||||||
"trunc" => {
|
"trunc" => {
|
||||||
check_length(&self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let arg = literal_or_variable!(invocation.arguments.first());
|
let arg = literal_or_variable!(invocation.arguments.first());
|
||||||
return Ok(SysCall::Math(sys_call::Math::Trunc(arg)));
|
Ok(SysCall::Math(sys_call::Math::Trunc(arg)))
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user