Compare commits
3 Commits
f5a28dfd6d
...
0.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
| d8fe9a0d7d | |||
|
089fe46d36
|
|||
|
14c641797a
|
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
[0.5.1]
|
||||||
|
|
||||||
|
- Fixed optimizer bug where `StoreBatch` and `StoreBatchNamed` instructions
|
||||||
|
were not recognized as reading operands, causing incorrect elimination of
|
||||||
|
necessary device property loads
|
||||||
|
- Added comprehensive register read tracking for `StoreSlot`, `JumpRelative`,
|
||||||
|
and `Alias` instructions in the optimizer
|
||||||
|
|
||||||
[0.5.0]
|
[0.5.0]
|
||||||
|
|
||||||
- Added full tuple support: declarations, assignments, and returns
|
- Added full tuple support: declarations, assignments, and returns
|
||||||
|
|||||||
@@ -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.5.0</Version>
|
<Version>0.5.1</Version>
|
||||||
<Description>
|
<Description>
|
||||||
[h1]Slang: High-Level Programming for Stationeers[/h1]
|
[h1]Slang: High-Level Programming for Stationeers[/h1]
|
||||||
|
|
||||||
|
|||||||
@@ -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.5.0";
|
public const string PluginVersion = "0.5.1";
|
||||||
|
|
||||||
private static Harmony? _harmony;
|
private static Harmony? _harmony;
|
||||||
|
|
||||||
|
|||||||
@@ -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.5.0</Version>
|
<Version>0.5.1</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
2
rust_compiler/Cargo.lock
generated
2
rust_compiler/Cargo.lock
generated
@@ -1039,7 +1039,7 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slang"
|
name = "slang"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "slang"
|
name = "slang"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|||||||
@@ -525,28 +525,6 @@ impl<'a> Compiler<'a> {
|
|||||||
temp_name: Some(result_name),
|
temp_name: Some(result_name),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Expression::BitwiseNot(inner_expr) => {
|
|
||||||
// Compile bitwise NOT using the NOT instruction
|
|
||||||
let (inner_str, cleanup) = self.compile_operand(*inner_expr, scope)?;
|
|
||||||
let result_name = self.next_temp_name();
|
|
||||||
let result_loc =
|
|
||||||
scope.add_variable(result_name.clone(), LocationRequest::Temp, None)?;
|
|
||||||
let result_reg = self.resolve_register(&result_loc)?;
|
|
||||||
|
|
||||||
self.write_instruction(
|
|
||||||
Instruction::Not(Operand::Register(result_reg), inner_str),
|
|
||||||
Some(expr.span),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(name) = cleanup {
|
|
||||||
scope.free_temp(name, None)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(CompileLocation {
|
|
||||||
location: result_loc,
|
|
||||||
temp_name: Some(result_name),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
Expression::TupleDeclaration(tuple_decl) => {
|
Expression::TupleDeclaration(tuple_decl) => {
|
||||||
self.expression_tuple_declaration(tuple_decl.node, scope)?;
|
self.expression_tuple_declaration(tuple_decl.node, scope)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -911,32 +889,6 @@ impl<'a> Compiler<'a> {
|
|||||||
}
|
}
|
||||||
(var_loc, None)
|
(var_loc, None)
|
||||||
}
|
}
|
||||||
Expression::BitwiseNot(_) => {
|
|
||||||
// Compile the bitwise NOT expression
|
|
||||||
let result = self.expression(expr, scope)?;
|
|
||||||
let var_loc = scope.add_variable(
|
|
||||||
name_str.clone(),
|
|
||||||
LocationRequest::Persist,
|
|
||||||
Some(name_span),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(res) = result {
|
|
||||||
// Move result from temp to new persistent variable
|
|
||||||
let result_reg = self.resolve_register(&res.location)?;
|
|
||||||
self.emit_variable_assignment(&var_loc, Operand::Register(result_reg))?;
|
|
||||||
|
|
||||||
// Free the temp result
|
|
||||||
if let Some(name) = res.temp_name {
|
|
||||||
scope.free_temp(name, None)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(Error::Unknown(
|
|
||||||
format!("`{name_str}` bitwise NOT expression did not produce a value"),
|
|
||||||
Some(name_span),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
(var_loc, None)
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::Unknown(
|
return Err(Error::Unknown(
|
||||||
format!("`{name_str}` declaration of this type is not supported/implemented."),
|
format!("`{name_str}` declaration of this type is not supported/implemented."),
|
||||||
@@ -2162,36 +2114,13 @@ impl<'a> Compiler<'a> {
|
|||||||
scope: &mut VariableScope<'a, '_>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<CompileLocation<'a>, Error<'a>> {
|
) -> Result<CompileLocation<'a>, Error<'a>> {
|
||||||
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
||||||
fn number_to_i64(n: Number) -> Option<i64> {
|
|
||||||
match n {
|
|
||||||
Number::Integer(i, _) => i64::try_from(i).ok(),
|
|
||||||
Number::Decimal(d, _) => {
|
|
||||||
// Convert decimal to i64 by truncating
|
|
||||||
let int_part = d.trunc();
|
|
||||||
i64::try_from(int_part.mantissa() / 10_i128.pow(int_part.scale())).ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn i64_to_number(i: i64) -> Number {
|
|
||||||
Number::Integer(i as i128, Unit::None)
|
|
||||||
}
|
|
||||||
|
|
||||||
let (lhs, rhs) = match &expr {
|
let (lhs, rhs) = match &expr {
|
||||||
BinaryExpression::Add(l, r)
|
BinaryExpression::Add(l, r)
|
||||||
| BinaryExpression::Subtract(l, r)
|
| BinaryExpression::Subtract(l, r)
|
||||||
| BinaryExpression::Multiply(l, r)
|
| BinaryExpression::Multiply(l, r)
|
||||||
| BinaryExpression::Divide(l, r)
|
| BinaryExpression::Divide(l, r)
|
||||||
| BinaryExpression::Exponent(l, r)
|
| BinaryExpression::Exponent(l, r)
|
||||||
| BinaryExpression::Modulo(l, r)
|
| BinaryExpression::Modulo(l, r) => (fold_expression(l)?, fold_expression(r)?),
|
||||||
| BinaryExpression::BitwiseAnd(l, r)
|
|
||||||
| BinaryExpression::BitwiseOr(l, r)
|
|
||||||
| BinaryExpression::BitwiseXor(l, r)
|
|
||||||
| BinaryExpression::LeftShift(l, r)
|
|
||||||
| BinaryExpression::RightShiftArithmetic(l, r)
|
|
||||||
| BinaryExpression::RightShiftLogical(l, r) => {
|
|
||||||
(fold_expression(l)?, fold_expression(r)?)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
@@ -2200,37 +2129,7 @@ impl<'a> Compiler<'a> {
|
|||||||
BinaryExpression::Multiply(..) => Some(lhs * rhs),
|
BinaryExpression::Multiply(..) => Some(lhs * rhs),
|
||||||
BinaryExpression::Divide(..) => Some(lhs / rhs), // Watch out for div by zero panics!
|
BinaryExpression::Divide(..) => Some(lhs / rhs), // Watch out for div by zero panics!
|
||||||
BinaryExpression::Modulo(..) => Some(lhs % rhs),
|
BinaryExpression::Modulo(..) => Some(lhs % rhs),
|
||||||
BinaryExpression::BitwiseAnd(..) => {
|
_ => None, // Handle Exponent separately or implement pow
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int & rhs_int))
|
|
||||||
}
|
|
||||||
BinaryExpression::BitwiseOr(..) => {
|
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int | rhs_int))
|
|
||||||
}
|
|
||||||
BinaryExpression::BitwiseXor(..) => {
|
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int ^ rhs_int))
|
|
||||||
}
|
|
||||||
BinaryExpression::LeftShift(..) => {
|
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int << rhs_int))
|
|
||||||
}
|
|
||||||
BinaryExpression::RightShiftArithmetic(..) => {
|
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int >> rhs_int))
|
|
||||||
}
|
|
||||||
BinaryExpression::RightShiftLogical(..) => {
|
|
||||||
let lhs_int = number_to_i64(lhs)?;
|
|
||||||
let rhs_int = number_to_i64(rhs)?;
|
|
||||||
Some(i64_to_number(lhs_int >> rhs_int))
|
|
||||||
}
|
|
||||||
_ => None, // Exponent not handled in compile-time folding
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2290,24 +2189,6 @@ impl<'a> Compiler<'a> {
|
|||||||
BinaryExpression::Modulo(l, r) => {
|
BinaryExpression::Modulo(l, r) => {
|
||||||
(|into, lhs, rhs| Instruction::Mod(into, lhs, rhs), l, r)
|
(|into, lhs, rhs| Instruction::Mod(into, lhs, rhs), l, r)
|
||||||
}
|
}
|
||||||
BinaryExpression::BitwiseAnd(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::And(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
BinaryExpression::BitwiseOr(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::Or(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
BinaryExpression::BitwiseXor(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::Xor(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
BinaryExpression::LeftShift(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::Sll(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
BinaryExpression::RightShiftArithmetic(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::Sra(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
BinaryExpression::RightShiftLogical(l, r) => {
|
|
||||||
(|into, lhs, rhs| Instruction::Srl(into, lhs, rhs), l, r)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = Self::merge_spans(left_expr.span, right_expr.span);
|
let span = Self::merge_spans(left_expr.span, right_expr.span);
|
||||||
|
|||||||
@@ -232,22 +232,12 @@ pub enum Instruction<'a> {
|
|||||||
/// `sle dst a b` - Set if Less or Equal
|
/// `sle dst a b` - Set if Less or Equal
|
||||||
SetLe(Operand<'a>, Operand<'a>, Operand<'a>),
|
SetLe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||||
|
|
||||||
/// `and dst a b` - Bitwise AND
|
/// `and dst a b` - Logical AND
|
||||||
And(Operand<'a>, Operand<'a>, Operand<'a>),
|
And(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||||
/// `or dst a b` - Bitwise OR
|
/// `or dst a b` - Logical OR
|
||||||
Or(Operand<'a>, Operand<'a>, Operand<'a>),
|
Or(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||||
/// `xor dst a b` - Bitwise XOR
|
/// `xor dst a b` - Logical XOR
|
||||||
Xor(Operand<'a>, Operand<'a>, Operand<'a>),
|
Xor(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||||
/// `nor dst a b` - Bitwise NOR
|
|
||||||
Nor(Operand<'a>, Operand<'a>, Operand<'a>),
|
|
||||||
/// `not dst a` - Bitwise NOT
|
|
||||||
Not(Operand<'a>, Operand<'a>),
|
|
||||||
/// `sll dst a b` - Logical Left Shift
|
|
||||||
Sll(Operand<'a>, Operand<'a>, Operand<'a>),
|
|
||||||
/// `sra dst a b` - Arithmetic Right Shift
|
|
||||||
Sra(Operand<'a>, Operand<'a>, Operand<'a>),
|
|
||||||
/// `srl dst a b` - Logical Right Shift
|
|
||||||
Srl(Operand<'a>, Operand<'a>, Operand<'a>),
|
|
||||||
|
|
||||||
/// `push val` - Push to Stack
|
/// `push val` - Push to Stack
|
||||||
Push(Operand<'a>),
|
Push(Operand<'a>),
|
||||||
@@ -348,11 +338,6 @@ impl<'a> fmt::Display for Instruction<'a> {
|
|||||||
Instruction::And(dst, a, b) => write!(f, "and {} {} {}", dst, a, b),
|
Instruction::And(dst, a, b) => write!(f, "and {} {} {}", dst, a, b),
|
||||||
Instruction::Or(dst, a, b) => write!(f, "or {} {} {}", dst, a, b),
|
Instruction::Or(dst, a, b) => write!(f, "or {} {} {}", dst, a, b),
|
||||||
Instruction::Xor(dst, a, b) => write!(f, "xor {} {} {}", dst, a, b),
|
Instruction::Xor(dst, a, b) => write!(f, "xor {} {} {}", dst, a, b),
|
||||||
Instruction::Nor(dst, a, b) => write!(f, "nor {} {} {}", dst, a, b),
|
|
||||||
Instruction::Not(dst, a) => write!(f, "not {} {}", dst, a),
|
|
||||||
Instruction::Sll(dst, a, b) => write!(f, "sll {} {} {}", dst, a, b),
|
|
||||||
Instruction::Sra(dst, a, b) => write!(f, "sra {} {} {}", dst, a, b),
|
|
||||||
Instruction::Srl(dst, a, b) => write!(f, "srl {} {} {}", dst, a, b),
|
|
||||||
Instruction::Push(val) => write!(f, "push {}", val),
|
Instruction::Push(val) => write!(f, "push {}", val),
|
||||||
Instruction::Pop(dst) => write!(f, "pop {}", dst),
|
Instruction::Pop(dst) => write!(f, "pop {}", dst),
|
||||||
Instruction::Peek(dst) => write!(f, "peek {}", dst),
|
Instruction::Peek(dst) => write!(f, "peek {}", dst),
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod bitwise_tests {
|
|
||||||
use crate::common::compile_with_and_without_optimization;
|
|
||||||
use indoc::indoc;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_bitwise_operations() {
|
|
||||||
let source = indoc! {"
|
|
||||||
let a = 5;
|
|
||||||
let b = 3;
|
|
||||||
let and_result = a & b;
|
|
||||||
let or_result = a | b;
|
|
||||||
let xor_result = a ^ b;
|
|
||||||
let not_result = ~a;
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_bitwise_shifts() {
|
|
||||||
let source = indoc! {"
|
|
||||||
let x = 8;
|
|
||||||
let left_shift = x << 2;
|
|
||||||
let arithmetic_shift = x >> 1;
|
|
||||||
let logical_shift = x >>> 1;
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_bitwise_constant_folding() {
|
|
||||||
let source = indoc! {"
|
|
||||||
let packed = (1 << 16) & (255 << 8) & 2;
|
|
||||||
let mask = 0xFF & 0x0F;
|
|
||||||
let combined = (15 | 4096);
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_bitwise_with_variables() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn pack_bits(high, low) {
|
|
||||||
let packed = (high << 8) | low;
|
|
||||||
return packed;
|
|
||||||
}
|
|
||||||
fn extract_bits(value) {
|
|
||||||
let high = (value >> 8) & 0xFF;
|
|
||||||
let low = value & 0xFF;
|
|
||||||
return (high, low);
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_complex_bit_manipulation() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn encode_flags(enabled, mode, priority) {
|
|
||||||
let flag_byte = (enabled << 7) | (mode << 4) | priority;
|
|
||||||
return flag_byte;
|
|
||||||
}
|
|
||||||
fn decode_flags(byte) {
|
|
||||||
let enabled = (byte >> 7) & 1;
|
|
||||||
let mode = (byte >> 4) & 0x7;
|
|
||||||
let priority = byte & 0xF;
|
|
||||||
return (enabled, mode, priority);
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
use compiler::Compiler;
|
|
||||||
use parser::Parser;
|
|
||||||
use tokenizer::Tokenizer;
|
|
||||||
|
|
||||||
/// Compile Slang source code and return both unoptimized and optimized output
|
|
||||||
pub fn compile_with_and_without_optimization(source: &str) -> String {
|
|
||||||
// Compile for unoptimized output
|
|
||||||
let tokenizer = Tokenizer::from(source);
|
|
||||||
let parser = Parser::new(tokenizer);
|
|
||||||
let compiler = Compiler::new(parser, None);
|
|
||||||
let result = compiler.compile();
|
|
||||||
|
|
||||||
// Get unoptimized output
|
|
||||||
let mut unoptimized_writer = std::io::BufWriter::new(Vec::new());
|
|
||||||
result
|
|
||||||
.instructions
|
|
||||||
.write(&mut unoptimized_writer)
|
|
||||||
.expect("Failed to write unoptimized output");
|
|
||||||
let unoptimized_bytes = unoptimized_writer
|
|
||||||
.into_inner()
|
|
||||||
.expect("Failed to get bytes");
|
|
||||||
let unoptimized = String::from_utf8(unoptimized_bytes).expect("Invalid UTF-8");
|
|
||||||
|
|
||||||
// Compile again for optimized output
|
|
||||||
let tokenizer2 = Tokenizer::from(source);
|
|
||||||
let parser2 = Parser::new(tokenizer2);
|
|
||||||
let compiler2 = Compiler::new(parser2, None);
|
|
||||||
let result2 = compiler2.compile();
|
|
||||||
|
|
||||||
// Apply optimizations
|
|
||||||
let optimized_instructions = optimizer::optimize(result2.instructions);
|
|
||||||
|
|
||||||
// Get optimized output
|
|
||||||
let mut optimized_writer = std::io::BufWriter::new(Vec::new());
|
|
||||||
optimized_instructions
|
|
||||||
.write(&mut optimized_writer)
|
|
||||||
.expect("Failed to write optimized output");
|
|
||||||
let optimized_bytes = optimized_writer.into_inner().expect("Failed to get bytes");
|
|
||||||
let optimized = String::from_utf8(optimized_bytes).expect("Invalid UTF-8");
|
|
||||||
|
|
||||||
// Combine both outputs with clear separators
|
|
||||||
format!(
|
|
||||||
"## Unoptimized Output\n\n{}\n## Optimized Output\n\n{}",
|
|
||||||
unoptimized, optimized
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod function_tests {
|
|
||||||
use crate::common::compile_with_and_without_optimization;
|
|
||||||
use indoc::indoc;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_simple_leaf_function() {
|
|
||||||
let source = "fn test() { let x = 10; }";
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_function_with_call() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn add(a, b) { return a + b; }
|
|
||||||
fn main() { let x = add(5, 10); }
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_leaf_function_no_stack_frame() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn increment(x) {
|
|
||||||
x = x + 1;
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_nested_function_calls() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn add(a, b) { return a + b; }
|
|
||||||
fn multiply(x, y) { return x * 2; }
|
|
||||||
fn complex(a, b) {
|
|
||||||
let sum = add(a, b);
|
|
||||||
let doubled = multiply(sum, 2);
|
|
||||||
return doubled;
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,20 +4,180 @@
|
|||||||
//! and optimization passes work correctly together using snapshot testing.
|
//! and optimization passes work correctly together using snapshot testing.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod bitwise_tests;
|
mod tests {
|
||||||
#[cfg(test)]
|
use compiler::Compiler;
|
||||||
mod common;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod function_tests;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod number_literal_tests;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod optimization_tests;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod integration_tests {
|
|
||||||
use crate::common::compile_with_and_without_optimization;
|
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
use parser::Parser;
|
||||||
|
use tokenizer::Tokenizer;
|
||||||
|
|
||||||
|
/// Compile Slang source code and return both unoptimized and optimized output
|
||||||
|
fn compile_with_and_without_optimization(source: &str) -> String {
|
||||||
|
// Compile for unoptimized output
|
||||||
|
let tokenizer = Tokenizer::from(source);
|
||||||
|
let parser = Parser::new(tokenizer);
|
||||||
|
let compiler = Compiler::new(parser, None);
|
||||||
|
let result = compiler.compile();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
result.errors.is_empty(),
|
||||||
|
"Compilation errors: {:?}",
|
||||||
|
result.errors
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get unoptimized output
|
||||||
|
let mut unoptimized_writer = std::io::BufWriter::new(Vec::new());
|
||||||
|
result
|
||||||
|
.instructions
|
||||||
|
.write(&mut unoptimized_writer)
|
||||||
|
.expect("Failed to write unoptimized output");
|
||||||
|
let unoptimized_bytes = unoptimized_writer
|
||||||
|
.into_inner()
|
||||||
|
.expect("Failed to get bytes");
|
||||||
|
let unoptimized = String::from_utf8(unoptimized_bytes).expect("Invalid UTF-8");
|
||||||
|
|
||||||
|
// Compile again for optimized output
|
||||||
|
let tokenizer2 = Tokenizer::from(source);
|
||||||
|
let parser2 = Parser::new(tokenizer2);
|
||||||
|
let compiler2 = Compiler::new(parser2, None);
|
||||||
|
let result2 = compiler2.compile();
|
||||||
|
|
||||||
|
// Apply optimizations
|
||||||
|
let optimized_instructions = optimizer::optimize(result2.instructions);
|
||||||
|
|
||||||
|
// Get optimized output
|
||||||
|
let mut optimized_writer = std::io::BufWriter::new(Vec::new());
|
||||||
|
optimized_instructions
|
||||||
|
.write(&mut optimized_writer)
|
||||||
|
.expect("Failed to write optimized output");
|
||||||
|
let optimized_bytes = optimized_writer.into_inner().expect("Failed to get bytes");
|
||||||
|
let optimized = String::from_utf8(optimized_bytes).expect("Invalid UTF-8");
|
||||||
|
|
||||||
|
// Combine both outputs with clear separators
|
||||||
|
format!(
|
||||||
|
"## Unoptimized Output\n\n{}\n## Optimized Output\n\n{}",
|
||||||
|
unoptimized, optimized
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_leaf_function() {
|
||||||
|
let source = "fn test() { let x = 10; }";
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_function_with_call() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn add(a, b) { return a + b; }
|
||||||
|
fn main() { let x = add(5, 10); }
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_constant_folding() {
|
||||||
|
let source = "let x = 5 + 10;";
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_algebraic_simplification() {
|
||||||
|
let source = "let x = 5; let y = x * 1;";
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strength_reduction() {
|
||||||
|
let source = "fn double(x) { return x * 2; }";
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dead_code_elimination() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn compute(x) {
|
||||||
|
let unused = 20;
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_peephole_comparison_fusion() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn compare(x, y) {
|
||||||
|
if (x > y) {
|
||||||
|
let z = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_select_optimization() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn ternary(cond) {
|
||||||
|
let result = 0;
|
||||||
|
if (cond) {
|
||||||
|
result = 10;
|
||||||
|
} else {
|
||||||
|
result = 20;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_leaf_function_no_stack_frame() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn increment(x) {
|
||||||
|
x = x + 1;
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_complex_arithmetic() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn compute(a, b, c) {
|
||||||
|
let x = a * 2;
|
||||||
|
let y = b + 0;
|
||||||
|
let z = c * 1;
|
||||||
|
return x + y + z;
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_function_calls() {
|
||||||
|
let source = indoc! {"
|
||||||
|
fn add(a, b) { return a + b; }
|
||||||
|
fn multiply(x, y) { return x * 2; }
|
||||||
|
fn complex(a, b) {
|
||||||
|
let sum = add(a, b);
|
||||||
|
let doubled = multiply(sum, 2);
|
||||||
|
return doubled;
|
||||||
|
}
|
||||||
|
"};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tuples() {
|
fn test_tuples() {
|
||||||
@@ -65,4 +225,20 @@ mod integration_tests {
|
|||||||
let output = compile_with_and_without_optimization(source);
|
let output = compile_with_and_without_optimization(source);
|
||||||
insta::assert_snapshot!(output);
|
insta::assert_snapshot!(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setbatched_with_member_access() {
|
||||||
|
let source = indoc! {r#"
|
||||||
|
const SENSOR = 20088;
|
||||||
|
const PANELS = hash("StructureSolarPanelDual");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
setBatched(PANELS, "Horizontal", SENSOR.Horizontal);
|
||||||
|
setBatched(PANELS, "Vertical", SENSOR.Vertical + 90);
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
let output = compile_with_and_without_optimization(source);
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod number_literal_tests {
|
|
||||||
use crate::common::compile_with_and_without_optimization;
|
|
||||||
use indoc::indoc;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_binary_literals() {
|
|
||||||
let source = indoc! {"
|
|
||||||
let binary = 0b1010_1100;
|
|
||||||
let octal = 0o755;
|
|
||||||
let hex_upper = 0xDEAD_BEEF;
|
|
||||||
let hex_lower = 0xcafe;
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_number_literal_optimization() {
|
|
||||||
let source = indoc! {"
|
|
||||||
let decimal = 42_000;
|
|
||||||
let negative_hex = -0xFF;
|
|
||||||
let negative_binary = -0b1111_0000;
|
|
||||||
let temp_c = 100c;
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod optimization_tests {
|
|
||||||
use crate::common::compile_with_and_without_optimization;
|
|
||||||
use indoc::indoc;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_constant_folding() {
|
|
||||||
let source = "let x = 5 + 10;";
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_algebraic_simplification() {
|
|
||||||
let source = "let x = 5; let y = x * 1;";
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_strength_reduction() {
|
|
||||||
let source = "fn double(x) { return x * 2; }";
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dead_code_elimination() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn compute(x) {
|
|
||||||
let unused = 20;
|
|
||||||
return x + 1;
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_peephole_comparison_fusion() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn compare(x, y) {
|
|
||||||
if (x > y) {
|
|
||||||
let z = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_select_optimization() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn ternary(cond) {
|
|
||||||
let result = 0;
|
|
||||||
if (cond) {
|
|
||||||
result = 10;
|
|
||||||
} else {
|
|
||||||
result = 20;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_complex_arithmetic() {
|
|
||||||
let source = indoc! {"
|
|
||||||
fn compute(a, b, c) {
|
|
||||||
let x = a * 2;
|
|
||||||
let y = b + 0;
|
|
||||||
let z = c * 1;
|
|
||||||
return x + y + z;
|
|
||||||
}
|
|
||||||
"};
|
|
||||||
let output = compile_with_and_without_optimization(source);
|
|
||||||
insta::assert_snapshot!(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/bitwise_tests.rs
|
|
||||||
assertion_line: 40
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
move r8 0
|
|
||||||
move r9 15
|
|
||||||
move r10 4111
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
move r8 0
|
|
||||||
move r9 15
|
|
||||||
move r10 4111
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/bitwise_tests.rs
|
|
||||||
assertion_line: 17
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
move r8 5
|
|
||||||
move r9 3
|
|
||||||
and r1 r8 r9
|
|
||||||
move r10 r1
|
|
||||||
or r2 r8 r9
|
|
||||||
move r11 r2
|
|
||||||
xor r3 r8 r9
|
|
||||||
move r12 r3
|
|
||||||
not r4 r8
|
|
||||||
move r13 r4
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
move r8 5
|
|
||||||
move r9 3
|
|
||||||
and r10 r8 r9
|
|
||||||
or r11 r8 r9
|
|
||||||
xor r12 r8 r9
|
|
||||||
not r4 r8
|
|
||||||
move r13 r4
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/bitwise_tests.rs
|
|
||||||
assertion_line: 29
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
move r8 8
|
|
||||||
sll r1 r8 2
|
|
||||||
move r9 r1
|
|
||||||
sra r2 r8 1
|
|
||||||
move r10 r2
|
|
||||||
srl r3 r8 1
|
|
||||||
move r11 r3
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
move r8 8
|
|
||||||
sll r1 r8 2
|
|
||||||
move r9 r1
|
|
||||||
sra r2 r8 1
|
|
||||||
move r10 r2
|
|
||||||
srl r3 r8 1
|
|
||||||
move r11 r3
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/bitwise_tests.rs
|
|
||||||
assertion_line: 57
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
pack_bits:
|
|
||||||
pop r8
|
|
||||||
pop r9
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sll r1 r9 8
|
|
||||||
or r2 r1 r8
|
|
||||||
move r10 r2
|
|
||||||
move r15 r10
|
|
||||||
j __internal_L1
|
|
||||||
__internal_L1:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
extract_bits:
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sra r1 r8 8
|
|
||||||
and r2 r1 255
|
|
||||||
move r9 r2
|
|
||||||
and r3 r8 255
|
|
||||||
move r10 r3
|
|
||||||
push r9
|
|
||||||
push r10
|
|
||||||
sub r0 sp 4
|
|
||||||
get r0 db r0
|
|
||||||
move r15 r0
|
|
||||||
j __internal_L2
|
|
||||||
__internal_L2:
|
|
||||||
sub r0 sp 3
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
pop r8
|
|
||||||
pop r9
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sll r1 r9 8
|
|
||||||
or r15 r1 r8
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sra r1 r8 8
|
|
||||||
and r9 r1 255
|
|
||||||
and r10 r8 255
|
|
||||||
push r9
|
|
||||||
push r10
|
|
||||||
sub r0 sp 4
|
|
||||||
get r15 db r0
|
|
||||||
sub r0 sp 3
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/bitwise_tests.rs
|
|
||||||
assertion_line: 75
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
encode_flags:
|
|
||||||
pop r8
|
|
||||||
pop r9
|
|
||||||
pop r10
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sll r1 r10 7
|
|
||||||
sll r2 r9 4
|
|
||||||
or r3 r1 r2
|
|
||||||
or r4 r3 r8
|
|
||||||
move r11 r4
|
|
||||||
move r15 r11
|
|
||||||
j __internal_L1
|
|
||||||
__internal_L1:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
decode_flags:
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sra r1 r8 7
|
|
||||||
and r2 r1 1
|
|
||||||
move r9 r2
|
|
||||||
sra r3 r8 4
|
|
||||||
and r4 r3 7
|
|
||||||
move r10 r4
|
|
||||||
and r5 r8 15
|
|
||||||
move r11 r5
|
|
||||||
push r9
|
|
||||||
push r10
|
|
||||||
push r11
|
|
||||||
sub r0 sp 5
|
|
||||||
get r0 db r0
|
|
||||||
move r15 r0
|
|
||||||
j __internal_L2
|
|
||||||
__internal_L2:
|
|
||||||
sub r0 sp 4
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
pop r8
|
|
||||||
pop r9
|
|
||||||
pop r10
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sll r1 r10 7
|
|
||||||
sll r2 r9 4
|
|
||||||
or r3 r1 r2
|
|
||||||
or r15 r3 r8
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sra r1 r8 7
|
|
||||||
and r9 r1 1
|
|
||||||
sra r3 r8 4
|
|
||||||
and r10 r3 7
|
|
||||||
and r11 r8 15
|
|
||||||
push r9
|
|
||||||
push r10
|
|
||||||
push r11
|
|
||||||
sub r0 sp 5
|
|
||||||
get r15 db r0
|
|
||||||
sub r0 sp 4
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/lib.rs
|
|
||||||
assertion_line: 54
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
waitForIdle:
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
yield
|
|
||||||
__internal_L2:
|
|
||||||
l r1 d0 Idle
|
|
||||||
seq r2 r1 0
|
|
||||||
beqz r2 __internal_L3
|
|
||||||
yield
|
|
||||||
j __internal_L2
|
|
||||||
__internal_L3:
|
|
||||||
__internal_L1:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
deposit:
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
s d0 Setting 1
|
|
||||||
jal waitForIdle
|
|
||||||
move r1 r15
|
|
||||||
s d0 Activate 1
|
|
||||||
jal waitForIdle
|
|
||||||
move r2 r15
|
|
||||||
s d1 Open 0
|
|
||||||
__internal_L4:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
checkAndHarvest:
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sle r1 r8 1
|
|
||||||
ls r15 d0 255 Seeding
|
|
||||||
slt r2 r15 1
|
|
||||||
or r3 r1 r2
|
|
||||||
beqz r3 __internal_L6
|
|
||||||
j __internal_L5
|
|
||||||
__internal_L6:
|
|
||||||
__internal_L7:
|
|
||||||
ls r15 d0 255 Mature
|
|
||||||
beqz r15 __internal_L8
|
|
||||||
yield
|
|
||||||
s d0 Activate 1
|
|
||||||
j __internal_L7
|
|
||||||
__internal_L8:
|
|
||||||
ls r15 d0 255 Occupied
|
|
||||||
move r9 r15
|
|
||||||
s d0 Setting 1
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal waitForIdle
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r4 r15
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal deposit
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r5 r15
|
|
||||||
beqz r9 __internal_L9
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal deposit
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r6 r15
|
|
||||||
__internal_L9:
|
|
||||||
s d0 Setting r8
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal waitForIdle
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r6 r15
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
beqz r15 __internal_L10
|
|
||||||
s d0 Activate 1
|
|
||||||
__internal_L10:
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal waitForIdle
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r7 r15
|
|
||||||
__internal_L5:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
main:
|
|
||||||
move r8 0
|
|
||||||
__internal_L11:
|
|
||||||
yield
|
|
||||||
l r1 d0 Idle
|
|
||||||
seq r2 r1 0
|
|
||||||
beqz r2 __internal_L13
|
|
||||||
j __internal_L11
|
|
||||||
__internal_L13:
|
|
||||||
add r3 r8 1
|
|
||||||
sgt r4 r3 19
|
|
||||||
add r5 r8 1
|
|
||||||
select r6 r4 2 r5
|
|
||||||
move r9 r6
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
push r8
|
|
||||||
jal checkAndHarvest
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r7 r15
|
|
||||||
s d0 Setting r9
|
|
||||||
move r8 r9
|
|
||||||
j __internal_L11
|
|
||||||
__internal_L12:
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
j 77
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
yield
|
|
||||||
l r1 d0 Idle
|
|
||||||
bne r1 0 8
|
|
||||||
yield
|
|
||||||
j 4
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
s d0 Setting 1
|
|
||||||
jal 1
|
|
||||||
move r1 r15
|
|
||||||
s d0 Activate 1
|
|
||||||
jal 1
|
|
||||||
move r2 r15
|
|
||||||
s d1 Open 0
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
sle r1 r8 1
|
|
||||||
ls r15 d0 255 Seeding
|
|
||||||
slt r2 r15 1
|
|
||||||
or r3 r1 r2
|
|
||||||
beqz r3 32
|
|
||||||
j 74
|
|
||||||
ls r15 d0 255 Mature
|
|
||||||
beqz r15 37
|
|
||||||
yield
|
|
||||||
s d0 Activate 1
|
|
||||||
j 32
|
|
||||||
ls r9 d0 255 Occupied
|
|
||||||
s d0 Setting 1
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal 1
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r4 r15
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal 11
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r5 r15
|
|
||||||
beqz r9 58
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal 11
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r6 r15
|
|
||||||
s d0 Setting r8
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal 1
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r6 r15
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
beqz r15 68
|
|
||||||
s d0 Activate 1
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
jal 1
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r7 r15
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
move r8 0
|
|
||||||
yield
|
|
||||||
l r1 d0 Idle
|
|
||||||
bne r1 0 82
|
|
||||||
j 78
|
|
||||||
add r3 r8 1
|
|
||||||
sgt r4 r3 19
|
|
||||||
add r5 r8 1
|
|
||||||
select r6 r4 2 r5
|
|
||||||
move r9 r6
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
push r8
|
|
||||||
jal 23
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move r7 r15
|
|
||||||
s d0 Setting r9
|
|
||||||
move r8 r9
|
|
||||||
j 78
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/lib.rs
|
|
||||||
assertion_line: 61
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
s d2 Mode 1
|
|
||||||
s d2 On 0
|
|
||||||
move r8 0
|
|
||||||
move r9 0
|
|
||||||
__internal_L1:
|
|
||||||
yield
|
|
||||||
l r1 d0 Reagents
|
|
||||||
move r10 r1
|
|
||||||
sge r2 r10 100
|
|
||||||
sge r3 r9 2
|
|
||||||
or r4 r2 r3
|
|
||||||
beqz r4 __internal_L3
|
|
||||||
move r8 1
|
|
||||||
__internal_L3:
|
|
||||||
slt r5 r10 100
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
seq r6 r15 0
|
|
||||||
and r7 r5 r6
|
|
||||||
add r1 r9 1
|
|
||||||
select r2 r7 r1 0
|
|
||||||
move r9 r2
|
|
||||||
l r3 d0 Rpm
|
|
||||||
slt r4 r3 1
|
|
||||||
and r5 r8 r4
|
|
||||||
beqz r5 __internal_L4
|
|
||||||
s d0 Open 1
|
|
||||||
seq r6 r10 0
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
and r7 r6 r15
|
|
||||||
seq r1 r7 0
|
|
||||||
move r8 r1
|
|
||||||
__internal_L4:
|
|
||||||
seq r6 r8 0
|
|
||||||
s d0 On r6
|
|
||||||
ls r15 d1 0 Quantity
|
|
||||||
move r11 r15
|
|
||||||
l r7 d3 Pressure
|
|
||||||
sgt r1 r7 200
|
|
||||||
beqz r1 __internal_L5
|
|
||||||
j __internal_L1
|
|
||||||
__internal_L5:
|
|
||||||
sgt r2 r11 0
|
|
||||||
s d1 On r2
|
|
||||||
sgt r3 r11 0
|
|
||||||
s d1 Activate r3
|
|
||||||
l r4 d3 Pressure
|
|
||||||
sgt r5 r4 0
|
|
||||||
l r6 d1 Activate
|
|
||||||
or r7 r5 r6
|
|
||||||
s d2 On r7
|
|
||||||
l r1 d1 Activate
|
|
||||||
s db Setting r1
|
|
||||||
j __internal_L1
|
|
||||||
__internal_L2:
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
s d2 Mode 1
|
|
||||||
s d2 On 0
|
|
||||||
move r8 0
|
|
||||||
move r9 0
|
|
||||||
yield
|
|
||||||
l r10 d0 Reagents
|
|
||||||
sge r2 r10 100
|
|
||||||
sge r3 r9 2
|
|
||||||
or r4 r2 r3
|
|
||||||
beqz r4 11
|
|
||||||
move r8 1
|
|
||||||
slt r5 r10 100
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
seq r6 r15 0
|
|
||||||
and r7 r5 r6
|
|
||||||
add r1 r9 1
|
|
||||||
select r2 r7 r1 0
|
|
||||||
move r9 r2
|
|
||||||
l r3 d0 Rpm
|
|
||||||
slt r4 r3 1
|
|
||||||
and r5 r8 r4
|
|
||||||
beqz r5 27
|
|
||||||
s d0 Open 1
|
|
||||||
seq r6 r10 0
|
|
||||||
ls r15 d0 0 Occupied
|
|
||||||
and r7 r6 r15
|
|
||||||
seq r8 r7 0
|
|
||||||
seq r6 r8 0
|
|
||||||
s d0 On r6
|
|
||||||
ls r15 d1 0 Quantity
|
|
||||||
move r11 r15
|
|
||||||
l r7 d3 Pressure
|
|
||||||
ble r7 200 34
|
|
||||||
j 4
|
|
||||||
sgt r2 r11 0
|
|
||||||
s d1 On r2
|
|
||||||
sgt r3 r11 0
|
|
||||||
s d1 Activate r3
|
|
||||||
l r4 d3 Pressure
|
|
||||||
sgt r5 r4 0
|
|
||||||
l r6 d1 Activate
|
|
||||||
or r7 r5 r6
|
|
||||||
s d2 On r7
|
|
||||||
l r1 d1 Activate
|
|
||||||
s db Setting r1
|
|
||||||
j 4
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/lib.rs
|
|
||||||
assertion_line: 47
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
getSomethingElse:
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
add r1 r8 1
|
|
||||||
move r15 r1
|
|
||||||
j __internal_L1
|
|
||||||
__internal_L1:
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
getSensorData:
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
l r1 d0 Vertical
|
|
||||||
push r1
|
|
||||||
l r2 d0 Horizontal
|
|
||||||
push r2
|
|
||||||
push 3
|
|
||||||
jal getSomethingElse
|
|
||||||
move r3 r15
|
|
||||||
push r3
|
|
||||||
sub r0 sp 5
|
|
||||||
get r0 db r0
|
|
||||||
move r15 r0
|
|
||||||
j __internal_L2
|
|
||||||
__internal_L2:
|
|
||||||
sub r0 sp 4
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
main:
|
|
||||||
__internal_L3:
|
|
||||||
yield
|
|
||||||
jal getSensorData
|
|
||||||
pop r0
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move sp r15
|
|
||||||
jal getSensorData
|
|
||||||
pop r0
|
|
||||||
pop r0
|
|
||||||
pop r9
|
|
||||||
move sp r15
|
|
||||||
s db Setting r9
|
|
||||||
j __internal_L3
|
|
||||||
__internal_L4:
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
j 23
|
|
||||||
pop r8
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
add r15 r8 1
|
|
||||||
pop ra
|
|
||||||
pop sp
|
|
||||||
j ra
|
|
||||||
push sp
|
|
||||||
push ra
|
|
||||||
l r1 d0 Vertical
|
|
||||||
push r1
|
|
||||||
l r2 d0 Horizontal
|
|
||||||
push r2
|
|
||||||
push 3
|
|
||||||
jal 1
|
|
||||||
move r3 r15
|
|
||||||
push r3
|
|
||||||
sub r0 sp 5
|
|
||||||
get r15 db r0
|
|
||||||
sub r0 sp 4
|
|
||||||
get ra db r0
|
|
||||||
j ra
|
|
||||||
yield
|
|
||||||
jal 8
|
|
||||||
pop r0
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
move sp r15
|
|
||||||
jal 8
|
|
||||||
pop r0
|
|
||||||
pop r0
|
|
||||||
pop r9
|
|
||||||
move sp r15
|
|
||||||
s db Setting r9
|
|
||||||
j 23
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/number_literal_tests.rs
|
|
||||||
assertion_line: 15
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
move r8 172
|
|
||||||
move r9 493
|
|
||||||
move r10 3735928559
|
|
||||||
move r11 51966
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
move r8 172
|
|
||||||
move r9 493
|
|
||||||
move r10 3735928559
|
|
||||||
move r11 51966
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
source: libs/integration_tests/src/number_literal_tests.rs
|
|
||||||
assertion_line: 27
|
|
||||||
expression: output
|
|
||||||
---
|
|
||||||
## Unoptimized Output
|
|
||||||
|
|
||||||
j main
|
|
||||||
main:
|
|
||||||
move r8 42000
|
|
||||||
move r9 -255
|
|
||||||
move r10 -240
|
|
||||||
move r11 373.15
|
|
||||||
|
|
||||||
## Optimized Output
|
|
||||||
|
|
||||||
move r8 42000
|
|
||||||
move r9 -255
|
|
||||||
move r10 -240
|
|
||||||
move r11 373.15
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 17
|
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 80
|
assertion_line: 158
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 10
|
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 36
|
assertion_line: 103
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/function_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 20
|
assertion_line: 70
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/function_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 31
|
assertion_line: 144
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/function_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 46
|
assertion_line: 173
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 49
|
assertion_line: 116
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 66
|
assertion_line: 133
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
source: libs/integration_tests/src/lib.rs
|
||||||
|
assertion_line: 242
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
## Unoptimized Output
|
||||||
|
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
__internal_L1:
|
||||||
|
l r1 20088 Horizontal
|
||||||
|
sb -539224550 Horizontal r1
|
||||||
|
l r2 20088 Vertical
|
||||||
|
add r3 r2 90
|
||||||
|
sb -539224550 Vertical r3
|
||||||
|
yield
|
||||||
|
j __internal_L1
|
||||||
|
__internal_L2:
|
||||||
|
|
||||||
|
## Optimized Output
|
||||||
|
|
||||||
|
l r1 20088 Horizontal
|
||||||
|
sb -539224550 Horizontal r1
|
||||||
|
l r2 20088 Vertical
|
||||||
|
add r3 r2 90
|
||||||
|
sb -539224550 Vertical r3
|
||||||
|
yield
|
||||||
|
j 0
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/function_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 10
|
assertion_line: 60
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: libs/integration_tests/src/optimization_tests.rs
|
source: libs/integration_tests/src/lib.rs
|
||||||
assertion_line: 24
|
assertion_line: 91
|
||||||
expression: output
|
expression: output
|
||||||
---
|
---
|
||||||
## Unoptimized Output
|
## Unoptimized Output
|
||||||
@@ -125,6 +125,9 @@ pub fn reg_is_read(instr: &Instruction, reg: u8) -> bool {
|
|||||||
| Instruction::Pow(_, a, b) => check(a) || check(b),
|
| Instruction::Pow(_, a, b) => check(a) || check(b),
|
||||||
Instruction::Load(_, a, _) => check(a),
|
Instruction::Load(_, a, _) => check(a),
|
||||||
Instruction::Store(a, _, b) => check(a) || check(b),
|
Instruction::Store(a, _, b) => check(a) || check(b),
|
||||||
|
Instruction::StoreBatch(a, _, b) => check(a) || check(b),
|
||||||
|
Instruction::StoreBatchNamed(a, b, _, c) => check(a) || check(b) || check(c),
|
||||||
|
Instruction::StoreSlot(a, b, _, c) => check(a) || check(b) || check(c),
|
||||||
Instruction::BranchEq(a, b, _)
|
Instruction::BranchEq(a, b, _)
|
||||||
| Instruction::BranchNe(a, b, _)
|
| Instruction::BranchNe(a, b, _)
|
||||||
| Instruction::BranchGt(a, b, _)
|
| Instruction::BranchGt(a, b, _)
|
||||||
@@ -167,6 +170,8 @@ pub fn reg_is_read(instr: &Instruction, reg: u8) -> bool {
|
|||||||
Instruction::Atan2(_, a, b) | Instruction::Max(_, a, b) | Instruction::Min(_, a, b) => {
|
Instruction::Atan2(_, a, b) | Instruction::Max(_, a, b) | Instruction::Min(_, a, b) => {
|
||||||
check(a) || check(b)
|
check(a) || check(b)
|
||||||
}
|
}
|
||||||
|
Instruction::JumpRelative(a) => check(a),
|
||||||
|
Instruction::Alias(_, a) => check(a),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,12 +294,12 @@ impl<'a> Parser<'a> {
|
|||||||
// Handle Infix operators (Binary, Logical, Assignment)
|
// Handle Infix operators (Binary, Logical, Assignment)
|
||||||
if self_matches_peek!(
|
if self_matches_peek!(
|
||||||
self,
|
self,
|
||||||
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || s.is_bitwise() || matches!(s, Symbol::Assign | Symbol::Question)
|
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || matches!(s, Symbol::Assign | Symbol::Question)
|
||||||
) {
|
) {
|
||||||
return Ok(Some(self.infix(lhs)?));
|
return Ok(Some(self.infix(lhs)?));
|
||||||
} else if self_matches_current!(
|
} else if self_matches_current!(
|
||||||
self,
|
self,
|
||||||
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || s.is_bitwise() || matches!(s, Symbol::Assign | Symbol::Question)
|
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || matches!(s, Symbol::Assign | Symbol::Question)
|
||||||
) {
|
) {
|
||||||
self.tokenizer.seek(SeekFrom::Current(-1))?;
|
self.tokenizer.seek(SeekFrom::Current(-1))?;
|
||||||
return Ok(Some(self.infix(lhs)?));
|
return Ok(Some(self.infix(lhs)?));
|
||||||
@@ -608,23 +608,6 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenType::Symbol(Symbol::BitwiseNot) => {
|
|
||||||
let start_span = self.current_span();
|
|
||||||
self.assign_next()?;
|
|
||||||
let inner_expr = self.unary()?.ok_or(Error::UnexpectedEOF)?;
|
|
||||||
let inner_with_postfix = self.parse_postfix(inner_expr)?;
|
|
||||||
let combined_span = Span {
|
|
||||||
start_line: start_span.start_line,
|
|
||||||
start_col: start_span.start_col,
|
|
||||||
end_line: inner_with_postfix.span.end_line,
|
|
||||||
end_col: inner_with_postfix.span.end_col,
|
|
||||||
};
|
|
||||||
Some(Spanned {
|
|
||||||
span: combined_span,
|
|
||||||
node: Expression::BitwiseNot(boxed!(inner_with_postfix)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
@@ -716,20 +699,6 @@ impl<'a> Parser<'a> {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenType::Symbol(Symbol::BitwiseNot) => {
|
|
||||||
self.assign_next()?;
|
|
||||||
let inner = self.get_infix_child_node()?;
|
|
||||||
let span = Span {
|
|
||||||
start_line: start_span.start_line,
|
|
||||||
start_col: start_span.start_col,
|
|
||||||
end_line: inner.span.end_line,
|
|
||||||
end_col: inner.span.end_col,
|
|
||||||
};
|
|
||||||
Spanned {
|
|
||||||
span,
|
|
||||||
node: Expression::BitwiseNot(boxed!(inner)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
@@ -808,7 +777,6 @@ impl<'a> Parser<'a> {
|
|||||||
| Expression::Variable(_)
|
| Expression::Variable(_)
|
||||||
| Expression::Ternary(_)
|
| Expression::Ternary(_)
|
||||||
| Expression::Negation(_)
|
| Expression::Negation(_)
|
||||||
| Expression::BitwiseNot(_)
|
|
||||||
| Expression::MemberAccess(_)
|
| Expression::MemberAccess(_)
|
||||||
| Expression::MethodCall(_)
|
| Expression::MethodCall(_)
|
||||||
| Expression::Tuple(_) => {}
|
| Expression::Tuple(_) => {}
|
||||||
@@ -828,7 +796,7 @@ impl<'a> Parser<'a> {
|
|||||||
// Include Assign in the operator loop
|
// Include Assign in the operator loop
|
||||||
while token_matches!(
|
while token_matches!(
|
||||||
temp_token,
|
temp_token,
|
||||||
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || s.is_bitwise() || matches!(s, Symbol::Assign | Symbol::Question | Symbol::Colon)
|
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || matches!(s, Symbol::Assign | Symbol::Question | Symbol::Colon)
|
||||||
) {
|
) {
|
||||||
let operator = match temp_token.token_type {
|
let operator = match temp_token.token_type {
|
||||||
TokenType::Symbol(s) => s,
|
TokenType::Symbol(s) => s,
|
||||||
@@ -901,24 +869,6 @@ impl<'a> Parser<'a> {
|
|||||||
Symbol::Minus => {
|
Symbol::Minus => {
|
||||||
BinaryExpression::Subtract(boxed!(left), boxed!(right))
|
BinaryExpression::Subtract(boxed!(left), boxed!(right))
|
||||||
}
|
}
|
||||||
Symbol::LeftShift => {
|
|
||||||
BinaryExpression::LeftShift(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
Symbol::RightShiftArithmetic => {
|
|
||||||
BinaryExpression::RightShiftArithmetic(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
Symbol::RightShiftLogical => {
|
|
||||||
BinaryExpression::RightShiftLogical(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
Symbol::BitwiseAnd => {
|
|
||||||
BinaryExpression::BitwiseAnd(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
Symbol::BitwiseOr => {
|
|
||||||
BinaryExpression::BitwiseOr(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
Symbol::Caret => {
|
|
||||||
BinaryExpression::BitwiseXor(boxed!(left), boxed!(right))
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -945,22 +895,7 @@ impl<'a> Parser<'a> {
|
|||||||
// --- PRECEDENCE LEVEL 3: Additive (+, -) ---
|
// --- PRECEDENCE LEVEL 3: Additive (+, -) ---
|
||||||
process_binary_ops!(Symbol::Plus | Symbol::Minus, BinaryExpression);
|
process_binary_ops!(Symbol::Plus | Symbol::Minus, BinaryExpression);
|
||||||
|
|
||||||
// --- PRECEDENCE LEVEL 4: Shift Operations (<<, >>, >>>) ---
|
// --- PRECEDENCE LEVEL 4: Comparison (<, >, <=, >=) ---
|
||||||
process_binary_ops!(
|
|
||||||
Symbol::LeftShift | Symbol::RightShiftArithmetic | Symbol::RightShiftLogical,
|
|
||||||
BinaryExpression
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- PRECEDENCE LEVEL 5: Bitwise AND (&) ---
|
|
||||||
process_binary_ops!(Symbol::BitwiseAnd, BinaryExpression);
|
|
||||||
|
|
||||||
// --- PRECEDENCE LEVEL 6: Bitwise XOR (^) ---
|
|
||||||
process_binary_ops!(Symbol::Caret, BinaryExpression);
|
|
||||||
|
|
||||||
// --- PRECEDENCE LEVEL 7: Bitwise OR (|) ---
|
|
||||||
process_binary_ops!(Symbol::BitwiseOr, BinaryExpression);
|
|
||||||
|
|
||||||
// --- PRECEDENCE LEVEL 8: Comparison (<, >, <=, >=) ---
|
|
||||||
let mut current_iteration = 0;
|
let mut current_iteration = 0;
|
||||||
for (i, operator) in operators.iter().enumerate() {
|
for (i, operator) in operators.iter().enumerate() {
|
||||||
if operator.is_comparison() && !matches!(operator, Symbol::Equal | Symbol::NotEqual) {
|
if operator.is_comparison() && !matches!(operator, Symbol::Equal | Symbol::NotEqual) {
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ pub enum BinaryExpression<'a> {
|
|||||||
Subtract(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
Subtract(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
||||||
Exponent(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
Exponent(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
||||||
Modulo(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
Modulo(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
||||||
BitwiseAnd(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
BitwiseOr(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
BitwiseXor(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
LeftShift(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
RightShiftArithmetic(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
RightShiftLogical(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for BinaryExpression<'a> {
|
impl<'a> std::fmt::Display for BinaryExpression<'a> {
|
||||||
@@ -62,12 +56,6 @@ impl<'a> std::fmt::Display for BinaryExpression<'a> {
|
|||||||
BinaryExpression::Subtract(l, r) => write!(f, "({} - {})", l, r),
|
BinaryExpression::Subtract(l, r) => write!(f, "({} - {})", l, r),
|
||||||
BinaryExpression::Exponent(l, r) => write!(f, "({} ** {})", l, r),
|
BinaryExpression::Exponent(l, r) => write!(f, "({} ** {})", l, r),
|
||||||
BinaryExpression::Modulo(l, r) => write!(f, "({} % {})", l, r),
|
BinaryExpression::Modulo(l, r) => write!(f, "({} % {})", l, r),
|
||||||
BinaryExpression::BitwiseAnd(l, r) => write!(f, "({} & {})", l, r),
|
|
||||||
BinaryExpression::BitwiseOr(l, r) => write!(f, "({} | {})", l, r),
|
|
||||||
BinaryExpression::BitwiseXor(l, r) => write!(f, "({} ^ {})", l, r),
|
|
||||||
BinaryExpression::LeftShift(l, r) => write!(f, "({} << {})", l, r),
|
|
||||||
BinaryExpression::RightShiftArithmetic(l, r) => write!(f, "({} >> {})", l, r),
|
|
||||||
BinaryExpression::RightShiftLogical(l, r) => write!(f, "({} >>> {})", l, r),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +367,6 @@ pub enum Expression<'a> {
|
|||||||
Binary(Spanned<BinaryExpression<'a>>),
|
Binary(Spanned<BinaryExpression<'a>>),
|
||||||
Block(Spanned<BlockExpression<'a>>),
|
Block(Spanned<BlockExpression<'a>>),
|
||||||
Break(Span),
|
Break(Span),
|
||||||
BitwiseNot(Box<Spanned<Expression<'a>>>),
|
|
||||||
ConstDeclaration(Spanned<ConstDeclarationExpression<'a>>),
|
ConstDeclaration(Spanned<ConstDeclarationExpression<'a>>),
|
||||||
Continue(Span),
|
Continue(Span),
|
||||||
Declaration(Spanned<Cow<'a, str>>, Box<Spanned<Expression<'a>>>),
|
Declaration(Spanned<Cow<'a, str>>, Box<Spanned<Expression<'a>>>),
|
||||||
@@ -411,7 +398,6 @@ impl<'a> std::fmt::Display for Expression<'a> {
|
|||||||
Expression::Binary(e) => write!(f, "{}", e),
|
Expression::Binary(e) => write!(f, "{}", e),
|
||||||
Expression::Block(e) => write!(f, "{}", e),
|
Expression::Block(e) => write!(f, "{}", e),
|
||||||
Expression::Break(_) => write!(f, "break"),
|
Expression::Break(_) => write!(f, "break"),
|
||||||
Expression::BitwiseNot(e) => write!(f, "(~{})", e),
|
|
||||||
Expression::ConstDeclaration(e) => write!(f, "{}", e),
|
Expression::ConstDeclaration(e) => write!(f, "{}", e),
|
||||||
Expression::Continue(_) => write!(f, "continue"),
|
Expression::Continue(_) => write!(f, "continue"),
|
||||||
Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e),
|
Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e),
|
||||||
@@ -453,3 +439,4 @@ impl<'a> std::fmt::Display for Expression<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,9 +135,6 @@ pub enum TokenType<'a> {
|
|||||||
/// Represents a string token
|
/// Represents a string token
|
||||||
String(Cow<'a, str>),
|
String(Cow<'a, str>),
|
||||||
|
|
||||||
#[regex(r"0[xX][0-9a-fA-F][0-9a-fA-F_]*", parse_number)]
|
|
||||||
#[regex(r"0[oO][0-7][0-7_]*", parse_number)]
|
|
||||||
#[regex(r"0[bB][01][01_]*", parse_number)]
|
|
||||||
#[regex(r"[0-9][0-9_]*(\.[0-9][0-9_]*)?([cfk])?", parse_number)]
|
#[regex(r"[0-9][0-9_]*(\.[0-9][0-9_]*)?([cfk])?", parse_number)]
|
||||||
/// Represents a number token
|
/// Represents a number token
|
||||||
Number(Number),
|
Number(Number),
|
||||||
@@ -175,23 +172,6 @@ pub enum TokenType<'a> {
|
|||||||
#[token(";", symbol!(Semicolon))]
|
#[token(";", symbol!(Semicolon))]
|
||||||
#[token(":", symbol!(Colon))]
|
#[token(":", symbol!(Colon))]
|
||||||
#[token(",", symbol!(Comma))]
|
#[token(",", symbol!(Comma))]
|
||||||
#[token("?", symbol!(Question))]
|
|
||||||
#[token(".", symbol!(Dot))]
|
|
||||||
#[token("%", symbol!(Percent))]
|
|
||||||
#[token("~", symbol!(BitwiseNot))]
|
|
||||||
// Multi-character tokens must be defined before their single-character prefixes
|
|
||||||
// For tokens like >> and >>>, define >>> before >> to ensure correct matching
|
|
||||||
#[token(">>>", symbol!(RightShiftLogical))]
|
|
||||||
#[token(">>", symbol!(RightShiftArithmetic))]
|
|
||||||
#[token("<<", symbol!(LeftShift))]
|
|
||||||
#[token("==", symbol!(Equal))]
|
|
||||||
#[token("!=", symbol!(NotEqual))]
|
|
||||||
#[token("&&", symbol!(LogicalAnd))]
|
|
||||||
#[token("||", symbol!(LogicalOr))]
|
|
||||||
#[token("<=", symbol!(LessThanOrEqual))]
|
|
||||||
#[token(">=", symbol!(GreaterThanOrEqual))]
|
|
||||||
#[token("**", symbol!(Exp))]
|
|
||||||
// Single-character tokens
|
|
||||||
#[token("+", symbol!(Plus))]
|
#[token("+", symbol!(Plus))]
|
||||||
#[token("-", symbol!(Minus))]
|
#[token("-", symbol!(Minus))]
|
||||||
#[token("*", symbol!(Asterisk))]
|
#[token("*", symbol!(Asterisk))]
|
||||||
@@ -200,9 +180,17 @@ pub enum TokenType<'a> {
|
|||||||
#[token(">", symbol!(GreaterThan))]
|
#[token(">", symbol!(GreaterThan))]
|
||||||
#[token("=", symbol!(Assign))]
|
#[token("=", symbol!(Assign))]
|
||||||
#[token("!", symbol!(LogicalNot))]
|
#[token("!", symbol!(LogicalNot))]
|
||||||
|
#[token(".", symbol!(Dot))]
|
||||||
#[token("^", symbol!(Caret))]
|
#[token("^", symbol!(Caret))]
|
||||||
#[token("&", symbol!(BitwiseAnd))]
|
#[token("%", symbol!(Percent))]
|
||||||
#[token("|", symbol!(BitwiseOr))]
|
#[token("?", symbol!(Question))]
|
||||||
|
#[token("==", symbol!(Equal))]
|
||||||
|
#[token("!=", symbol!(NotEqual))]
|
||||||
|
#[token("&&", symbol!(LogicalAnd))]
|
||||||
|
#[token("||", symbol!(LogicalOr))]
|
||||||
|
#[token("<=", symbol!(LessThanOrEqual))]
|
||||||
|
#[token(">=", symbol!(GreaterThanOrEqual))]
|
||||||
|
#[token("**", symbol!(Exp))]
|
||||||
/// Represents a symbol token
|
/// Represents a symbol token
|
||||||
Symbol(Symbol),
|
Symbol(Symbol),
|
||||||
|
|
||||||
@@ -233,39 +221,6 @@ pub enum Comment<'a> {
|
|||||||
|
|
||||||
fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexError> {
|
fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexError> {
|
||||||
let slice = lexer.slice();
|
let slice = lexer.slice();
|
||||||
|
|
||||||
let line = lexer.extras.line_count;
|
|
||||||
let mut span = lexer.span();
|
|
||||||
span.end -= lexer.extras.line_start_index;
|
|
||||||
span.start -= lexer.extras.line_start_index;
|
|
||||||
|
|
||||||
// Determine the base and parse accordingly
|
|
||||||
if slice.starts_with("0x") || slice.starts_with("0X") {
|
|
||||||
// Hexadecimal - no temperature suffix allowed
|
|
||||||
let clean_str = slice[2..].replace('_', "");
|
|
||||||
Ok(Number::Integer(
|
|
||||||
i128::from_str_radix(&clean_str, 16)
|
|
||||||
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
|
||||||
Unit::None,
|
|
||||||
))
|
|
||||||
} else if slice.starts_with("0o") || slice.starts_with("0O") {
|
|
||||||
// Octal - no temperature suffix allowed
|
|
||||||
let clean_str = slice[2..].replace('_', "");
|
|
||||||
Ok(Number::Integer(
|
|
||||||
i128::from_str_radix(&clean_str, 8)
|
|
||||||
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
|
||||||
Unit::None,
|
|
||||||
))
|
|
||||||
} else if slice.starts_with("0b") || slice.starts_with("0B") {
|
|
||||||
// Binary - no temperature suffix allowed
|
|
||||||
let clean_str = slice[2..].replace('_', "");
|
|
||||||
Ok(Number::Integer(
|
|
||||||
i128::from_str_radix(&clean_str, 2)
|
|
||||||
.map_err(|_| LexError::NumberParse(line, span, slice.to_string()))?,
|
|
||||||
Unit::None,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
// Decimal (with optional temperature suffix)
|
|
||||||
let last_char = slice.chars().last().unwrap_or_default();
|
let last_char = slice.chars().last().unwrap_or_default();
|
||||||
let (num_str, suffix) = match last_char {
|
let (num_str, suffix) = match last_char {
|
||||||
'c' | 'k' | 'f' => (&slice[..slice.len() - 1], Some(last_char)),
|
'c' | 'k' | 'f' => (&slice[..slice.len() - 1], Some(last_char)),
|
||||||
@@ -278,6 +233,11 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
num_str.to_string()
|
num_str.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let line = lexer.extras.line_count;
|
||||||
|
let mut span = lexer.span();
|
||||||
|
span.end -= lexer.extras.line_start_index;
|
||||||
|
span.start -= lexer.extras.line_start_index;
|
||||||
|
|
||||||
let unit = match suffix {
|
let unit = match suffix {
|
||||||
Some('c') => Unit::Celsius,
|
Some('c') => Unit::Celsius,
|
||||||
Some('f') => Unit::Fahrenheit,
|
Some('f') => Unit::Fahrenheit,
|
||||||
@@ -286,7 +246,6 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
};
|
};
|
||||||
|
|
||||||
if clean_str.contains('.') {
|
if clean_str.contains('.') {
|
||||||
// Decimal floating point
|
|
||||||
Ok(Number::Decimal(
|
Ok(Number::Decimal(
|
||||||
clean_str
|
clean_str
|
||||||
.parse::<Decimal>()
|
.parse::<Decimal>()
|
||||||
@@ -294,7 +253,6 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
unit,
|
unit,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
// Decimal integer
|
|
||||||
Ok(Number::Integer(
|
Ok(Number::Integer(
|
||||||
clean_str
|
clean_str
|
||||||
.parse::<i128>()
|
.parse::<i128>()
|
||||||
@@ -303,7 +261,6 @@ fn parse_number<'a>(lexer: &mut Lexer<'a, TokenType<'a>>) -> Result<Number, LexE
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for Comment<'a> {
|
impl<'a> std::fmt::Display for Comment<'a> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
@@ -658,12 +615,6 @@ pub enum Symbol {
|
|||||||
Percent,
|
Percent,
|
||||||
/// Represents the `?` symbol
|
/// Represents the `?` symbol
|
||||||
Question,
|
Question,
|
||||||
/// Represents the `&` symbol (bitwise AND)
|
|
||||||
BitwiseAnd,
|
|
||||||
/// Represents the `|` symbol (bitwise OR)
|
|
||||||
BitwiseOr,
|
|
||||||
/// Represents the `~` symbol (bitwise NOT)
|
|
||||||
BitwiseNot,
|
|
||||||
|
|
||||||
// Double Character Symbols
|
// Double Character Symbols
|
||||||
/// Represents the `==` symbol
|
/// Represents the `==` symbol
|
||||||
@@ -678,12 +629,6 @@ pub enum Symbol {
|
|||||||
LessThanOrEqual,
|
LessThanOrEqual,
|
||||||
/// Represents the `>=` symbol
|
/// Represents the `>=` symbol
|
||||||
GreaterThanOrEqual,
|
GreaterThanOrEqual,
|
||||||
/// Represents the `<<` symbol (left shift)
|
|
||||||
LeftShift,
|
|
||||||
/// Represents the `>>` symbol (arithmetic right shift)
|
|
||||||
RightShiftArithmetic,
|
|
||||||
/// Represents the `>>>` symbol (logical right shift)
|
|
||||||
RightShiftLogical,
|
|
||||||
/// Represents the `**` symbol
|
/// Represents the `**` symbol
|
||||||
Exp,
|
Exp,
|
||||||
}
|
}
|
||||||
@@ -698,19 +643,6 @@ impl Symbol {
|
|||||||
| Symbol::Slash
|
| Symbol::Slash
|
||||||
| Symbol::Exp
|
| Symbol::Exp
|
||||||
| Symbol::Percent
|
| Symbol::Percent
|
||||||
| Symbol::Caret
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_bitwise(&self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Symbol::BitwiseAnd
|
|
||||||
| Symbol::BitwiseOr
|
|
||||||
| Symbol::BitwiseNot
|
|
||||||
| Symbol::LeftShift
|
|
||||||
| Symbol::RightShiftArithmetic
|
|
||||||
| Symbol::RightShiftLogical
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,12 +693,6 @@ impl std::fmt::Display for Symbol {
|
|||||||
Self::NotEqual => write!(f, "!="),
|
Self::NotEqual => write!(f, "!="),
|
||||||
Self::Dot => write!(f, "."),
|
Self::Dot => write!(f, "."),
|
||||||
Self::Caret => write!(f, "^"),
|
Self::Caret => write!(f, "^"),
|
||||||
Self::BitwiseAnd => write!(f, "&"),
|
|
||||||
Self::BitwiseOr => write!(f, "|"),
|
|
||||||
Self::BitwiseNot => write!(f, "~"),
|
|
||||||
Self::LeftShift => write!(f, "<<"),
|
|
||||||
Self::RightShiftArithmetic => write!(f, ">>"),
|
|
||||||
Self::RightShiftLogical => write!(f, ">>>"),
|
|
||||||
Self::Exp => write!(f, "**"),
|
Self::Exp => write!(f, "**"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,7 +715,7 @@ documented! {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
Continue,
|
Continue,
|
||||||
/// Represents the `const` keyword. This allows you to define a variable that will never
|
/// Prepresents the `const` keyword. This allows you to define a variable that will never
|
||||||
/// change throughout the lifetime of the program, similar to `define` in IC10. If you are
|
/// change throughout the lifetime of the program, similar to `define` in IC10. If you are
|
||||||
/// not planning on mutating the variable (changing it), it is recommend you store it as a
|
/// not planning on mutating the variable (changing it), it is recommend you store it as a
|
||||||
/// const, as the compiler will not assign it to a register or stack variable.
|
/// const, as the compiler will not assign it to a register or stack variable.
|
||||||
@@ -920,7 +846,6 @@ documented! {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::TokenType;
|
use super::TokenType;
|
||||||
use super::{Number, Unit};
|
|
||||||
use logos::Logos;
|
use logos::Logos;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -931,141 +856,7 @@ mod tests {
|
|||||||
|
|
||||||
let tokens = lexer.collect::<Vec<_>>();
|
let tokens = lexer.collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(
|
assert!(!tokens.iter().any(|res| res.is_err()));
|
||||||
!tokens.iter().any(|res| res.is_err()),
|
|
||||||
"Expected no lexing errors for CRLF endings"
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_binary_literals() -> anyhow::Result<()> {
|
|
||||||
let src = "0b1010 0b0 0b1111_0000";
|
|
||||||
let lexer = TokenType::lexer(src);
|
|
||||||
let tokens: Vec<_> = lexer.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[0],
|
|
||||||
TokenType::Number(Number::Integer(10, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected binary 0b1010 = 10"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[1],
|
|
||||||
TokenType::Number(Number::Integer(0, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected binary 0b0 = 0"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[2],
|
|
||||||
TokenType::Number(Number::Integer(240, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected binary 0b1111_0000 = 240"
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_octal_literals() -> anyhow::Result<()> {
|
|
||||||
let src = "0o77 0o0 0o7_777";
|
|
||||||
let lexer = TokenType::lexer(src);
|
|
||||||
let tokens: Vec<_> = lexer.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[0],
|
|
||||||
TokenType::Number(Number::Integer(63, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected octal 0o77 = 63"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[1],
|
|
||||||
TokenType::Number(Number::Integer(0, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected octal 0o0 = 0"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[2],
|
|
||||||
TokenType::Number(Number::Integer(4095, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected octal 0o7_777 = 4095"
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hex_literals() -> anyhow::Result<()> {
|
|
||||||
let src = "0xFF 0x0 0xFF_FF 0xFF_FF_FF";
|
|
||||||
let lexer = TokenType::lexer(src);
|
|
||||||
let tokens: Vec<_> = lexer.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 4);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[0],
|
|
||||||
TokenType::Number(Number::Integer(255, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xFF = 255"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[1],
|
|
||||||
TokenType::Number(Number::Integer(0, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0x0 = 0"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[2],
|
|
||||||
TokenType::Number(Number::Integer(65535, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xFF_FF = 65535"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[3],
|
|
||||||
TokenType::Number(Number::Integer(16777215, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xFF_FF_FF = 16777215"
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hex_literals_lowercase() -> anyhow::Result<()> {
|
|
||||||
let src = "0xff 0xab 0xcd_ef";
|
|
||||||
let lexer = TokenType::lexer(src);
|
|
||||||
let tokens: Vec<_> = lexer.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[0],
|
|
||||||
TokenType::Number(Number::Integer(255, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xff = 255"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[1],
|
|
||||||
TokenType::Number(Number::Integer(171, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xab = 171"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&tokens[2],
|
|
||||||
TokenType::Number(Number::Integer(52719, Unit::None))
|
|
||||||
),
|
|
||||||
"Expected hex 0xcd_ef = 52719"
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user