diff --git a/rust_compiler/Cargo.lock b/rust_compiler/Cargo.lock index 511d7ef..0803d0c 100644 --- a/rust_compiler/Cargo.lock +++ b/rust_compiler/Cargo.lock @@ -930,7 +930,7 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slang" -version = "0.3.2" +version = "0.3.3" dependencies = [ "anyhow", "clap", diff --git a/rust_compiler/libs/compiler/src/test/syscall.rs b/rust_compiler/libs/compiler/src/test/syscall.rs index 8456448..f7df25e 100644 --- a/rust_compiler/libs/compiler/src/test/syscall.rs +++ b/rust_compiler/libs/compiler/src/test/syscall.rs @@ -208,3 +208,29 @@ fn test_set_slot() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn test_load_reagent() -> anyhow::Result<()> { + let compiled = compile! { + debug + r#" + device thingy = "d0"; + + let something = lr(thingy, "Contents", hash("Iron")); + "# + }; + + assert_eq!( + compiled, + indoc! { + " + j main + main: + lr r15 d0 Contents -666742878 + move r8 r15 + " + } + ); + + Ok(()) +} diff --git a/rust_compiler/libs/compiler/src/v1.rs b/rust_compiler/libs/compiler/src/v1.rs index db2282b..c536f64 100644 --- a/rust_compiler/libs/compiler/src/v1.rs +++ b/rust_compiler/libs/compiler/src/v1.rs @@ -2296,6 +2296,48 @@ impl<'a> Compiler<'a> { Ok(None) } + System::LoadReagent(device, reagent_mode, reagent_hash) => { + let Spanned { + node: LiteralOrVariable::Variable(device_spanned), + .. + } = device + else { + return Err(Error::AgrumentMismatch( + "Arg1 expected to be a variable".into(), + span, + )); + }; + + let (device, device_cleanup) = self.compile_literal_or_variable( + LiteralOrVariable::Variable(device_spanned), + scope, + )?; + + let (reagent_mode, reagent_cleanup) = self.compile_literal_or_variable( + LiteralOrVariable::Literal(reagent_mode.node), + scope, + )?; + + let (reagent_hash, reagent_hash_cleanup) = + self.compile_operand(*reagent_hash, scope)?; + + self.write_instruction( + Instruction::LoadReagent( + Operand::Register(VariableScope::RETURN_REGISTER), + device, + reagent_mode, + reagent_hash, + ), + Some(span), + )?; + + cleanup!(reagent_cleanup, reagent_hash_cleanup, device_cleanup); + + Ok(Some(CompileLocation { + location: VariableLocation::Persistant(VariableScope::RETURN_REGISTER), + temp_name: None, + })) + } } } diff --git a/rust_compiler/libs/helpers/src/syscall.rs b/rust_compiler/libs/helpers/src/syscall.rs index 5ec38c5..e329129 100644 --- a/rust_compiler/libs/helpers/src/syscall.rs +++ b/rust_compiler/libs/helpers/src/syscall.rs @@ -10,6 +10,7 @@ macro_rules! with_syscalls { "loadBatched", "loadBatchedNamed", "loadSlot", + "loadReagent", "set", "setBatched", "setBatchedNamed", @@ -35,6 +36,7 @@ macro_rules! with_syscalls { "lb", "lbn", "ls", + "lr", "s", "sb", "sbn", diff --git a/rust_compiler/libs/il/src/lib.rs b/rust_compiler/libs/il/src/lib.rs index 62affd8..1a3fdc3 100644 --- a/rust_compiler/libs/il/src/lib.rs +++ b/rust_compiler/libs/il/src/lib.rs @@ -191,6 +191,9 @@ pub enum Instruction<'a> { /// `sbn deviceHash nameHash type value` - Set Batch Named StoreBatchNamed(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>), + /// `lr register device reagentMode int` + LoadReagent(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>), + /// `j label` - Unconditional Jump Jump(Operand<'a>), /// `jal label` - Jump and Link (Function Call) @@ -311,6 +314,9 @@ impl<'a> fmt::Display for Instruction<'a> { Instruction::StoreBatchNamed(d_hash, n_hash, typ, val) => { write!(f, "sbn {} {} {} {}", d_hash, n_hash, typ, val) } + Instruction::LoadReagent(reg, device, reagent_mode, reagent_hash) => { + write!(f, "lr {} {} {} {}", reg, device, reagent_mode, reagent_hash) + } Instruction::Jump(lbl) => write!(f, "j {}", lbl), Instruction::JumpAndLink(lbl) => write!(f, "jal {}", lbl), Instruction::JumpRelative(off) => write!(f, "jr {}", off), diff --git a/rust_compiler/libs/optimizer/src/lib.rs b/rust_compiler/libs/optimizer/src/lib.rs index ea75c06..10f5d95 100644 --- a/rust_compiler/libs/optimizer/src/lib.rs +++ b/rust_compiler/libs/optimizer/src/lib.rs @@ -565,6 +565,7 @@ fn get_destination_reg(instr: &Instruction) -> Option { | Instruction::Sqrt(Operand::Register(r), _) | Instruction::Tan(Operand::Register(r), _) | Instruction::Trunc(Operand::Register(r), _) + | Instruction::LoadReagent(Operand::Register(r), _, _, _) | Instruction::Pop(Operand::Register(r)) => Some(*r), _ => None, } @@ -595,6 +596,9 @@ fn set_destination_reg<'a>(instr: &Instruction<'a>, new_reg: u8) -> Option { + Some(Instruction::LoadReagent(r, b.clone(), c.clone(), d.clone())) + } Instruction::SetEq(_, a, b) => Some(Instruction::SetEq(r, a.clone(), b.clone())), Instruction::SetNe(_, a, b) => Some(Instruction::SetNe(r, a.clone(), b.clone())), Instruction::SetGt(_, a, b) => Some(Instruction::SetGt(r, a.clone(), b.clone())), diff --git a/rust_compiler/libs/parser/src/lib.rs b/rust_compiler/libs/parser/src/lib.rs index 66d0d99..4cb4618 100644 --- a/rust_compiler/libs/parser/src/lib.rs +++ b/rust_compiler/libs/parser/src/lib.rs @@ -1909,6 +1909,20 @@ impl<'a> Parser<'a> { Box::new(expr), ))) } + "loadReagent" | "lr" => { + let mut args = args!(3); + let next = args.next(); + let device = literal_or_variable!(next); + let next = args.next(); + let reagent_mode = get_arg!(Literal, literal_or_variable!(next)); + let reagent_hash = args.next().ok_or(Error::UnexpectedEOF)?; + + Ok(SysCall::System(System::LoadReagent( + device, + reagent_mode, + Box::new(reagent_hash), + ))) + } // Math SysCalls "acos" => { diff --git a/rust_compiler/libs/parser/src/sys_call.rs b/rust_compiler/libs/parser/src/sys_call.rs index 00a48ef..0251e91 100644 --- a/rust_compiler/libs/parser/src/sys_call.rs +++ b/rust_compiler/libs/parser/src/sys_call.rs @@ -237,6 +237,18 @@ documented! { Spanned>, Spanned>, Box>> + ), + /// Loads reagent of device's ReagentMode where a hash of the reagent type to check for + /// + /// ## IC10 + /// `lr r? device(d?|r?|id) reagentMode int` + /// ## Slang + /// `let result = loadReagent(deviceHash, "ReagentMode", reagentHash);` + /// `let result = lr(deviceHash, "ReagentMode", reagentHash);` + LoadReagent( + Spanned>, + Spanned>, + Box>> ) } } @@ -261,6 +273,7 @@ impl<'a> std::fmt::Display for System<'a> { } System::LoadSlot(a, b, c) => write!(f, "loadSlot({}, {}, {})", a, b, c), System::SetSlot(a, b, c, d) => write!(f, "setSlot({}, {}, {}, {})", a, b, c, d), + System::LoadReagent(a, b, c) => write!(f, "loadReagent({}, {}, {})", a, b, c), } } }