Found bug, unable to do an assignment expression with a syscall
This commit is contained in:
@@ -243,6 +243,22 @@ fn test_max() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
fn test_max_from_game() -> Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
result
|
||||||
|
r#"
|
||||||
|
let item = 0;
|
||||||
|
item = max(1, 2);
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{compiled:?}");
|
||||||
|
assert!(compiled.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_min() -> Result<()> {
|
fn test_min() -> Result<()> {
|
||||||
let compiled = compile! {
|
let compiled = compile! {
|
||||||
|
|||||||
@@ -157,3 +157,54 @@ fn test_load_from_device() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_load_from_slot() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
device airCon = "d0";
|
||||||
|
|
||||||
|
let setting = ls(airCon, 0, "Occupied");
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
ls r15 d0 0 Occupied
|
||||||
|
move r8 r15 #setting
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_slot() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
device airCon = "d0";
|
||||||
|
|
||||||
|
ss(airCon, 0, "Occupied", true);
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
ss d0 0 Occupied 1
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -865,6 +865,7 @@ impl<'a, 'w, W: std::io::Write> Compiler<'a, 'w, W> {
|
|||||||
scope.free_temp(c, None)?;
|
scope.free_temp(c, None)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::Unknown(
|
return Err(Error::Unknown(
|
||||||
"Invalid assignment target. Only variables and member access are supported."
|
"Invalid assignment target. Only variables and member access are supported."
|
||||||
@@ -1952,6 +1953,55 @@ impl<'a, 'w, W: std::io::Write> Compiler<'a, 'w, W> {
|
|||||||
temp_name: None,
|
temp_name: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
System::LoadSlot(dev_name, slot_index, logic_type) => {
|
||||||
|
let (dev_hash, hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(dev_name.node, scope)?;
|
||||||
|
let (slot_index, slot_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(slot_index.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
let (logic_type, logic_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(logic_type.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.write_output(format!(
|
||||||
|
"ls r{} {} {} {}",
|
||||||
|
VariableScope::RETURN_REGISTER,
|
||||||
|
dev_hash,
|
||||||
|
slot_index,
|
||||||
|
logic_type
|
||||||
|
))?;
|
||||||
|
|
||||||
|
cleanup!(hash_cleanup, slot_cleanup, logic_cleanup);
|
||||||
|
|
||||||
|
Ok(Some(CompilationResult {
|
||||||
|
location: VariableLocation::Persistant(VariableScope::RETURN_REGISTER),
|
||||||
|
temp_name: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
System::SetSlot(dev_name, slot_index, logic_type, var) => {
|
||||||
|
let (dev_name, name_cleanup) =
|
||||||
|
self.compile_literal_or_variable(dev_name.node, scope)?;
|
||||||
|
let (slot_index, index_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(slot_index.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
let (logic_type, type_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(logic_type.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
let (var, var_cleanup) = self.compile_operand(*var, scope)?;
|
||||||
|
|
||||||
|
self.write_output(format!(
|
||||||
|
"ss {} {} {} {}",
|
||||||
|
dev_name, slot_index, logic_type, var
|
||||||
|
))?;
|
||||||
|
|
||||||
|
cleanup!(name_cleanup, index_cleanup, type_cleanup, var_cleanup);
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub enum LocationRequest {
|
|||||||
Stack,
|
Stack,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum VariableLocation<'a> {
|
pub enum VariableLocation<'a> {
|
||||||
/// Represents a temporary register (r1 - r7)
|
/// Represents a temporary register (r1 - r7)
|
||||||
Temporary(u8),
|
Temporary(u8),
|
||||||
@@ -66,7 +66,6 @@ pub enum VariableLocation<'a> {
|
|||||||
Device(Cow<'a, str>),
|
Device(Cow<'a, str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX: Added 'b lifetime for the parent reference
|
|
||||||
pub struct VariableScope<'a, 'b> {
|
pub struct VariableScope<'a, 'b> {
|
||||||
temporary_vars: VecDeque<u8>,
|
temporary_vars: VecDeque<u8>,
|
||||||
persistant_vars: VecDeque<u8>,
|
persistant_vars: VecDeque<u8>,
|
||||||
@@ -75,7 +74,6 @@ pub struct VariableScope<'a, 'b> {
|
|||||||
parent: Option<&'b VariableScope<'a, 'b>>,
|
parent: Option<&'b VariableScope<'a, 'b>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX: Updated Default impl to include 'b
|
|
||||||
impl<'a, 'b> Default for VariableScope<'a, 'b> {
|
impl<'a, 'b> Default for VariableScope<'a, 'b> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -88,7 +86,6 @@ impl<'a, 'b> Default for VariableScope<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX: Updated impl block to include 'b
|
|
||||||
impl<'a, 'b> VariableScope<'a, 'b> {
|
impl<'a, 'b> VariableScope<'a, 'b> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const TEMP_REGISTER_COUNT: u8 = 7;
|
pub const TEMP_REGISTER_COUNT: u8 = 7;
|
||||||
@@ -112,7 +109,6 @@ impl<'a, 'b> VariableScope<'a, 'b> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX: parent is now &'b VariableScope<'a, 'b>
|
|
||||||
pub fn scoped(parent: &'b VariableScope<'a, 'b>) -> Self {
|
pub fn scoped(parent: &'b VariableScope<'a, 'b>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: Option::Some(parent),
|
parent: Option::Some(parent),
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ macro_rules! with_syscalls {
|
|||||||
"load",
|
"load",
|
||||||
"loadBatched",
|
"loadBatched",
|
||||||
"loadBatchedNamed",
|
"loadBatchedNamed",
|
||||||
|
"loadSlot",
|
||||||
"set",
|
"set",
|
||||||
"setBatched",
|
"setBatched",
|
||||||
"setBatchedNamed",
|
"setBatchedNamed",
|
||||||
|
"setSlot",
|
||||||
"acos",
|
"acos",
|
||||||
"asin",
|
"asin",
|
||||||
"atan",
|
"atan",
|
||||||
@@ -32,9 +34,11 @@ macro_rules! with_syscalls {
|
|||||||
"l",
|
"l",
|
||||||
"lb",
|
"lb",
|
||||||
"lbn",
|
"lbn",
|
||||||
|
"ls",
|
||||||
"s",
|
"s",
|
||||||
"sb",
|
"sb",
|
||||||
"sbn"
|
"sbn",
|
||||||
|
"ss"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ impl<'a> Parser<'a> {
|
|||||||
self,
|
self,
|
||||||
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || matches!(s, Symbol::Assign)
|
TokenType::Symbol(s) if s.is_operator() || s.is_comparison() || s.is_logical() || matches!(s, Symbol::Assign)
|
||||||
) {
|
) {
|
||||||
|
println!("{lhs}");
|
||||||
return Ok(Some(self.infix(lhs)?));
|
return Ok(Some(self.infix(lhs)?));
|
||||||
} else if self_matches_current!(
|
} else if self_matches_current!(
|
||||||
self,
|
self,
|
||||||
@@ -1518,18 +1519,23 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn syscall(&mut self) -> Result<SysCall<'a>, Error<'a>> {
|
fn syscall(&mut self) -> Result<SysCall<'a>, Error<'a>> {
|
||||||
fn check_length<'a>(
|
let invocation = self.invocation()?;
|
||||||
span: Span,
|
|
||||||
arguments: &[Spanned<Expression<'a>>],
|
let check_length = |len: usize| -> Result<(), Error> {
|
||||||
length: usize,
|
if invocation.arguments.len() != len {
|
||||||
) -> Result<(), Error<'a>> {
|
|
||||||
if arguments.len() != length {
|
|
||||||
return Err(Error::InvalidSyntax(
|
return Err(Error::InvalidSyntax(
|
||||||
span,
|
self.current_span(),
|
||||||
format!("Expected {} arguments", length),
|
format!("Expected {} arguments", len),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! args {
|
||||||
|
($count:expr) => {{
|
||||||
|
check_length($count)?;
|
||||||
|
invocation.arguments.into_iter()
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! literal_or_variable {
|
macro_rules! literal_or_variable {
|
||||||
@@ -1581,23 +1587,19 @@ impl<'a> Parser<'a> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let invocation = self.invocation()?;
|
|
||||||
|
|
||||||
match invocation.name.node.as_ref() {
|
match invocation.name.node.as_ref() {
|
||||||
// System SysCalls
|
// System SysCalls
|
||||||
"yield" => {
|
"yield" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 0)?;
|
check_length(0)?;
|
||||||
Ok(SysCall::System(sys_call::System::Yield))
|
Ok(SysCall::System(sys_call::System::Yield))
|
||||||
}
|
}
|
||||||
"sleep" => {
|
"sleep" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
let mut args = args!(1);
|
||||||
let mut arg = invocation.arguments.into_iter();
|
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
let expr = arg.next().ok_or(Error::UnexpectedEOF)?;
|
|
||||||
Ok(SysCall::System(System::Sleep(boxed!(expr))))
|
Ok(SysCall::System(System::Sleep(boxed!(expr))))
|
||||||
}
|
}
|
||||||
"hash" => {
|
"hash" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
let mut args = args!(1);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let lit_str = literal_or_variable!(args.next());
|
let lit_str = literal_or_variable!(args.next());
|
||||||
|
|
||||||
let Spanned {
|
let Spanned {
|
||||||
@@ -1617,8 +1619,7 @@ impl<'a> Parser<'a> {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
"load" | "l" => {
|
"load" | "l" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 2)?;
|
let mut args = args!(2);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let device = literal_or_variable!(tmp);
|
let device = literal_or_variable!(tmp);
|
||||||
@@ -1662,8 +1663,7 @@ impl<'a> Parser<'a> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"loadBatched" | "lb" => {
|
"loadBatched" | "lb" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 3)?;
|
let mut args = args!(3);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let device_hash = literal_or_variable!(tmp);
|
let device_hash = literal_or_variable!(tmp);
|
||||||
|
|
||||||
@@ -1680,8 +1680,7 @@ impl<'a> Parser<'a> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"loadBatchedNamed" | "lbn" => {
|
"loadBatchedNamed" | "lbn" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 4)?;
|
let mut args = args!(4);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let dev_hash = literal_or_variable!(tmp);
|
let dev_hash = literal_or_variable!(tmp);
|
||||||
|
|
||||||
@@ -1699,8 +1698,7 @@ impl<'a> Parser<'a> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"set" | "s" => {
|
"set" | "s" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 3)?;
|
let mut args = args!(3);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let device = literal_or_variable!(tmp);
|
let device = literal_or_variable!(tmp);
|
||||||
|
|
||||||
@@ -1720,8 +1718,7 @@ impl<'a> Parser<'a> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"setBatched" | "sb" => {
|
"setBatched" | "sb" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 3)?;
|
let mut args = args!(3);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let device_hash = literal_or_variable!(tmp);
|
let device_hash = literal_or_variable!(tmp);
|
||||||
|
|
||||||
@@ -1739,8 +1736,7 @@ impl<'a> Parser<'a> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"setBatchedNamed" | "sbn" => {
|
"setBatchedNamed" | "sbn" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 4)?;
|
let mut args = args!(4);
|
||||||
let mut args = invocation.arguments.into_iter();
|
|
||||||
let tmp = args.next();
|
let tmp = args.next();
|
||||||
let device_hash = literal_or_variable!(tmp);
|
let device_hash = literal_or_variable!(tmp);
|
||||||
|
|
||||||
@@ -1760,30 +1756,110 @@ impl<'a> Parser<'a> {
|
|||||||
expr,
|
expr,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
"loadSlot" | "ls" => {
|
||||||
|
let mut args = args!(3);
|
||||||
|
let next = args.next();
|
||||||
|
let dev_name = literal_or_variable!(next);
|
||||||
|
let next = args.next();
|
||||||
|
let slot_index = get_arg!(Literal, literal_or_variable!(next));
|
||||||
|
if !matches!(
|
||||||
|
slot_index,
|
||||||
|
Spanned {
|
||||||
|
node: Literal::Number(_),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
return Err(Error::InvalidSyntax(
|
||||||
|
slot_index.span,
|
||||||
|
"Expected a number".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let next = args.next();
|
||||||
|
let slot_logic = get_arg!(Literal, literal_or_variable!(next));
|
||||||
|
if !matches!(
|
||||||
|
slot_logic,
|
||||||
|
Spanned {
|
||||||
|
node: Literal::String(_),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return Err(Error::InvalidSyntax(
|
||||||
|
slot_logic.span,
|
||||||
|
"Expected a String".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::LoadSlot(
|
||||||
|
dev_name, slot_index, slot_logic,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
"setSlot" | "ss" => {
|
||||||
|
let mut args = args!(4);
|
||||||
|
let next = args.next();
|
||||||
|
let dev_name = literal_or_variable!(next);
|
||||||
|
let next = args.next();
|
||||||
|
let slot_index = get_arg!(Literal, literal_or_variable!(next));
|
||||||
|
if !matches!(
|
||||||
|
slot_index,
|
||||||
|
Spanned {
|
||||||
|
node: Literal::Number(_),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return Err(Error::InvalidSyntax(
|
||||||
|
slot_index.span,
|
||||||
|
"Expected a number".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let next = args.next();
|
||||||
|
let slot_logic = get_arg!(Literal, literal_or_variable!(next));
|
||||||
|
if !matches!(
|
||||||
|
slot_logic,
|
||||||
|
Spanned {
|
||||||
|
node: Literal::String(_),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return Err(Error::InvalidSyntax(
|
||||||
|
slot_logic.span,
|
||||||
|
"Expected a string".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let next = args.next();
|
||||||
|
let expr = next.ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::SetSlot(
|
||||||
|
dev_name,
|
||||||
|
slot_index,
|
||||||
|
slot_logic,
|
||||||
|
Box::new(expr),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
// Math SysCalls
|
// Math SysCalls
|
||||||
"acos" => {
|
"acos" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
|
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Acos(boxed!(tmp))))
|
Ok(SysCall::Math(Math::Acos(boxed!(tmp))))
|
||||||
}
|
}
|
||||||
"asin" => {
|
"asin" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
|
let tmp = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Asin(boxed!(tmp))))
|
Ok(SysCall::Math(Math::Asin(boxed!(tmp))))
|
||||||
}
|
}
|
||||||
"atan" => {
|
"atan" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
|
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Atan(boxed!(expr))))
|
Ok(SysCall::Math(Math::Atan(boxed!(expr))))
|
||||||
}
|
}
|
||||||
"atan2" => {
|
"atan2" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 2)?;
|
check_length(2)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
@@ -1791,42 +1867,42 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(SysCall::Math(Math::Atan2(boxed!(arg1), boxed!(arg2))))
|
Ok(SysCall::Math(Math::Atan2(boxed!(arg1), boxed!(arg2))))
|
||||||
}
|
}
|
||||||
"abs" => {
|
"abs" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
|
let expr = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Abs(boxed!(expr))))
|
Ok(SysCall::Math(Math::Abs(boxed!(expr))))
|
||||||
}
|
}
|
||||||
"ceil" => {
|
"ceil" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Ceil(boxed!(arg))))
|
Ok(SysCall::Math(Math::Ceil(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"cos" => {
|
"cos" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Cos(boxed!(arg))))
|
Ok(SysCall::Math(Math::Cos(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"floor" => {
|
"floor" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Floor(boxed!(arg))))
|
Ok(SysCall::Math(Math::Floor(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"log" => {
|
"log" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Log(boxed!(arg))))
|
Ok(SysCall::Math(Math::Log(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"max" => {
|
"max" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 2)?;
|
check_length(2)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
@@ -1834,7 +1910,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(SysCall::Math(Math::Max(boxed!(arg1), boxed!(arg2))))
|
Ok(SysCall::Math(Math::Max(boxed!(arg1), boxed!(arg2))))
|
||||||
}
|
}
|
||||||
"min" => {
|
"min" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 2)?;
|
check_length(2)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg1 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg2 = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
@@ -1842,32 +1918,32 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(SysCall::Math(Math::Min(boxed!(arg1), boxed!(arg2))))
|
Ok(SysCall::Math(Math::Min(boxed!(arg1), boxed!(arg2))))
|
||||||
}
|
}
|
||||||
"rand" => {
|
"rand" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 0)?;
|
check_length(0)?;
|
||||||
Ok(SysCall::Math(Math::Rand))
|
Ok(SysCall::Math(Math::Rand))
|
||||||
}
|
}
|
||||||
"sin" => {
|
"sin" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Sin(boxed!(arg))))
|
Ok(SysCall::Math(Math::Sin(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"sqrt" => {
|
"sqrt" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Sqrt(boxed!(arg))))
|
Ok(SysCall::Math(Math::Sqrt(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"tan" => {
|
"tan" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::Math(Math::Tan(boxed!(arg))))
|
Ok(SysCall::Math(Math::Tan(boxed!(arg))))
|
||||||
}
|
}
|
||||||
"trunc" => {
|
"trunc" => {
|
||||||
check_length(self.current_span(), &invocation.arguments, 1)?;
|
check_length(1)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
let arg = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
|
|||||||
@@ -214,6 +214,30 @@ documented! {
|
|||||||
Spanned<Literal<'a>>,
|
Spanned<Literal<'a>>,
|
||||||
Box<Spanned<Expression<'a>>>,
|
Box<Spanned<Expression<'a>>>,
|
||||||
),
|
),
|
||||||
|
/// Loads slot LogicSlotType from device into a variable
|
||||||
|
///
|
||||||
|
/// ## IC10
|
||||||
|
/// `ls r0 d0 2 Occupied`
|
||||||
|
/// ## Slang
|
||||||
|
/// `let isOccupied = loadSlot(deviceHash, 2, "Occupied");`
|
||||||
|
/// `let isOccupied = ls(deviceHash, 2, "Occupied");`
|
||||||
|
LoadSlot(
|
||||||
|
Spanned<LiteralOrVariable<'a>>,
|
||||||
|
Spanned<Literal<'a>>,
|
||||||
|
Spanned<Literal<'a>>
|
||||||
|
),
|
||||||
|
/// Stores a value of LogicType on a device by the index value
|
||||||
|
/// ## IC10
|
||||||
|
/// `ss d0 0 "Open" 1`
|
||||||
|
/// ## Slang
|
||||||
|
/// `setSlot(deviceHash, 0, "Open", true);`
|
||||||
|
/// `ss(deviceHash, 0, "Open", true);`
|
||||||
|
SetSlot(
|
||||||
|
Spanned<LiteralOrVariable<'a>>,
|
||||||
|
Spanned<Literal<'a>>,
|
||||||
|
Spanned<Literal<'a>>,
|
||||||
|
Box<Spanned<Expression<'a>>>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +259,8 @@ impl<'a> std::fmt::Display for System<'a> {
|
|||||||
System::SetOnDeviceBatchedNamed(a, b, c, d) => {
|
System::SetOnDeviceBatchedNamed(a, b, c, d) => {
|
||||||
write!(f, "setOnDeviceBatchedNamed({}, {}, {}, {})", a, b, c, d)
|
write!(f, "setOnDeviceBatchedNamed({}, {}, {}, {})", a, b, c, d)
|
||||||
}
|
}
|
||||||
|
System::LoadSlot(a, b, c) => write!(f, "loadSlot({}, {}, {})", a, b, c),
|
||||||
|
System::SetSlot(a, b, c, d) => write!(f, "setSlot({}, {}, {}, {})", a, b, c, d),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl From<LexError> for Diagnostic {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => Diagnostic::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user