syscall aliases and more syscalls
This commit is contained in:
@@ -106,6 +106,36 @@ fn test_set_on_device_batched() -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_on_device_batched_named() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
result
|
||||||
|
r#"
|
||||||
|
device dev = "d0";
|
||||||
|
const devName = hash("test");
|
||||||
|
|
||||||
|
let myVar = lbn(dev, devName, "On", 12);
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{compiled:?}");
|
||||||
|
|
||||||
|
assert!(compiled.is_empty());
|
||||||
|
|
||||||
|
// assert_eq!(
|
||||||
|
// compiled,
|
||||||
|
// indoc! {
|
||||||
|
// "
|
||||||
|
// j main
|
||||||
|
// main:
|
||||||
|
// lbn r8 d0
|
||||||
|
// "
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_from_device() -> anyhow::Result<()> {
|
fn test_load_from_device() -> anyhow::Result<()> {
|
||||||
let compiled = compile! {
|
let compiled = compile! {
|
||||||
|
|||||||
@@ -693,7 +693,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
// check for a hash expression or a literal
|
// check for a hash expression or a literal
|
||||||
let value = match const_value {
|
let value = match const_value {
|
||||||
LiteralOr::Or(Spanned {
|
LiteralOr::Or(Spanned {
|
||||||
node: SysCall::System(System::Hash(Literal::String(str_to_hash))),
|
node:
|
||||||
|
SysCall::System(System::Hash(Spanned {
|
||||||
|
node: Literal::String(str_to_hash),
|
||||||
|
..
|
||||||
|
})),
|
||||||
..
|
..
|
||||||
}) => Literal::Number(Number::Integer(crc_hash_signed(&str_to_hash))),
|
}) => Literal::Number(Number::Integer(crc_hash_signed(&str_to_hash))),
|
||||||
LiteralOr::Or(Spanned { span, .. }) => {
|
LiteralOr::Or(Spanned { span, .. }) => {
|
||||||
@@ -1148,6 +1152,9 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
if let Literal::Boolean(b) = spanned_lit.node {
|
if let Literal::Boolean(b) = spanned_lit.node {
|
||||||
return Ok((if b { "1".to_string() } else { "0".to_string() }, None));
|
return Ok((if b { "1".to_string() } else { "0".to_string() }, None));
|
||||||
}
|
}
|
||||||
|
if let Literal::String(ref s) = spanned_lit.node {
|
||||||
|
return Ok((s.to_string(), None));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimization for negated literals used as operands.
|
// Optimization for negated literals used as operands.
|
||||||
@@ -1585,22 +1592,34 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
scope: &mut VariableScope<'v>,
|
scope: &mut VariableScope<'v>,
|
||||||
) -> Result<Option<CompilationResult>, Error> {
|
) -> Result<Option<CompilationResult>, Error> {
|
||||||
|
macro_rules! cleanup {
|
||||||
|
($($to_clean:expr),*) => {
|
||||||
|
$(
|
||||||
|
if let Some(to_clean) = $to_clean {
|
||||||
|
scope.free_temp(to_clean)?;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
match expr {
|
match expr {
|
||||||
System::Yield => {
|
System::Yield => {
|
||||||
self.write_output("yield")?;
|
self.write_output("yield")?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
System::Sleep(amt) => {
|
System::Sleep(amt) => {
|
||||||
let (var, cleanup) = self.compile_operand(*amt, scope)?;
|
let (var, var_cleanup) = self.compile_operand(*amt, scope)?;
|
||||||
self.write_output(format!("sleep {var}"))?;
|
self.write_output(format!("sleep {var}"))?;
|
||||||
if let Some(temp) = cleanup {
|
|
||||||
scope.free_temp(temp)?;
|
cleanup!(var_cleanup);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
System::Hash(hash_arg) => {
|
System::Hash(hash_arg) => {
|
||||||
let Literal::String(str_lit) = hash_arg else {
|
let Spanned {
|
||||||
|
node: Literal::String(str_lit),
|
||||||
|
..
|
||||||
|
} = hash_arg
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg1 expected to be a string literal.".into(),
|
"Arg1 expected to be a string literal.".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1619,7 +1638,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
System::SetOnDevice(device, logic_type, variable) => {
|
System::SetOnDevice(device, logic_type, variable) => {
|
||||||
let (variable, var_cleanup) = self.compile_operand(*variable, scope)?;
|
let (variable, var_cleanup) = self.compile_operand(*variable, scope)?;
|
||||||
|
|
||||||
let LiteralOrVariable::Variable(device_spanned) = device else {
|
let Spanned {
|
||||||
|
node: LiteralOrVariable::Variable(device_spanned),
|
||||||
|
..
|
||||||
|
} = device
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg1 expected to be a variable".into(),
|
"Arg1 expected to be a variable".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1641,7 +1664,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or("d0".to_string());
|
.unwrap_or("d0".to_string());
|
||||||
|
|
||||||
let Literal::String(logic_type) = logic_type else {
|
let Spanned {
|
||||||
|
node: Literal::String(logic_type),
|
||||||
|
..
|
||||||
|
} = logic_type
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg2 expected to be a string".into(),
|
"Arg2 expected to be a string".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1650,17 +1677,19 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
|
|
||||||
self.write_output(format!("s {} {} {}", device_val, logic_type, variable))?;
|
self.write_output(format!("s {} {} {}", device_val, logic_type, variable))?;
|
||||||
|
|
||||||
if let Some(temp_var) = var_cleanup {
|
cleanup!(var_cleanup);
|
||||||
scope.free_temp(temp_var)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
System::SetOnDeviceBatched(device_hash, logic_type, variable) => {
|
System::SetOnDeviceBatched(device_hash, logic_type, variable) => {
|
||||||
let (var, var_cleanup) = self.compile_operand(*variable, scope)?;
|
let (var, var_cleanup) = self.compile_operand(*variable, scope)?;
|
||||||
let (device_hash_val, device_hash_cleanup) =
|
let (device_hash_val, device_hash_cleanup) =
|
||||||
self.compile_literal_or_variable(device_hash, scope)?;
|
self.compile_literal_or_variable(device_hash.node, scope)?;
|
||||||
let Literal::String(logic_type) = logic_type else {
|
let Spanned {
|
||||||
|
node: Literal::String(logic_type),
|
||||||
|
..
|
||||||
|
} = logic_type
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg2 expected to be a string".into(),
|
"Arg2 expected to be a string".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1669,18 +1698,41 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
|
|
||||||
self.write_output(format!("sb {} {} {}", device_hash_val, logic_type, var))?;
|
self.write_output(format!("sb {} {} {}", device_hash_val, logic_type, var))?;
|
||||||
|
|
||||||
if let Some(var_cleanup) = var_cleanup {
|
cleanup!(var_cleanup, device_hash_cleanup);
|
||||||
scope.free_temp(var_cleanup)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(device_cleanup) = device_hash_cleanup {
|
|
||||||
scope.free_temp(device_cleanup)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
System::SetOnDeviceBatchedNamed(device_hash, name_hash, logic_type, val_expr) => {
|
||||||
|
let (value, value_cleanup) = self.compile_operand(*val_expr, scope)?;
|
||||||
|
let (device_hash, device_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(device_hash.node, scope)?;
|
||||||
|
let (name_hash, name_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(name_hash.node, scope)?;
|
||||||
|
let (logic_type, logic_type_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(logic_type.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.write_output(format!(
|
||||||
|
"snb {} {} {} {}",
|
||||||
|
device_hash, name_hash, logic_type, value
|
||||||
|
))?;
|
||||||
|
|
||||||
|
cleanup!(
|
||||||
|
value_cleanup,
|
||||||
|
device_hash_cleanup,
|
||||||
|
name_hash_cleanup,
|
||||||
|
logic_type_cleanup
|
||||||
|
);
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
System::LoadFromDevice(device, logic_type) => {
|
System::LoadFromDevice(device, logic_type) => {
|
||||||
let LiteralOrVariable::Variable(device_spanned) = device else {
|
let Spanned {
|
||||||
|
node: LiteralOrVariable::Variable(device_spanned),
|
||||||
|
..
|
||||||
|
} = device
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg1 expected to be a variable".into(),
|
"Arg1 expected to be a variable".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1702,7 +1754,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or("d0".to_string());
|
.unwrap_or("d0".to_string());
|
||||||
|
|
||||||
let Literal::String(logic_type) = logic_type else {
|
let Spanned {
|
||||||
|
node: Literal::String(logic_type),
|
||||||
|
..
|
||||||
|
} = logic_type
|
||||||
|
else {
|
||||||
return Err(Error::AgrumentMismatch(
|
return Err(Error::AgrumentMismatch(
|
||||||
"Arg2 expected to be a string".into(),
|
"Arg2 expected to be a string".into(),
|
||||||
span,
|
span,
|
||||||
@@ -1721,11 +1777,68 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
temp_name: None,
|
temp_name: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
System::LoadBatch(device_hash, logic_type, batch_mode) => {
|
||||||
|
let (device_hash, device_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(device_hash.node, scope)?;
|
||||||
|
let (logic_type, logic_type_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(logic_type.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
let (batch_mode, batch_mode_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(batch_mode.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
|
||||||
t => Err(Error::Unknown(
|
self.write_output(format!(
|
||||||
format!("{t:?}\n\nNot yet implemented"),
|
"lb r{} {} {} {}",
|
||||||
Some(span),
|
VariableScope::RETURN_REGISTER,
|
||||||
)),
|
device_hash,
|
||||||
|
logic_type,
|
||||||
|
batch_mode
|
||||||
|
))?;
|
||||||
|
|
||||||
|
cleanup!(device_hash_cleanup, logic_type_cleanup, batch_mode_cleanup);
|
||||||
|
|
||||||
|
Ok(Some(CompilationResult {
|
||||||
|
location: VariableLocation::Persistant(VariableScope::RETURN_REGISTER),
|
||||||
|
temp_name: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
System::LoadBatchNamed(device_hash, name_hash, logic_type, batch_mode) => {
|
||||||
|
let (device_hash, device_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(device_hash.node, scope)?;
|
||||||
|
let (name_hash, name_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(name_hash.node, scope)?;
|
||||||
|
let (logic_type, logic_type_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(logic_type.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
let (batch_mode, batch_mode_cleanup) = self.compile_literal_or_variable(
|
||||||
|
LiteralOrVariable::Literal(batch_mode.node),
|
||||||
|
scope,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.write_output(format!(
|
||||||
|
"lbn r{} {} {} {} {}",
|
||||||
|
VariableScope::RETURN_REGISTER,
|
||||||
|
device_hash,
|
||||||
|
name_hash,
|
||||||
|
logic_type,
|
||||||
|
batch_mode
|
||||||
|
))?;
|
||||||
|
|
||||||
|
cleanup!(
|
||||||
|
device_hash_cleanup,
|
||||||
|
name_hash_cleanup,
|
||||||
|
logic_type_cleanup,
|
||||||
|
batch_mode_cleanup
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Some(CompilationResult {
|
||||||
|
location: VariableLocation::Persistant(VariableScope::RETURN_REGISTER),
|
||||||
|
temp_name: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,16 @@
|
|||||||
macro_rules! with_syscalls {
|
macro_rules! with_syscalls {
|
||||||
($matcher:ident) => {
|
($matcher:ident) => {
|
||||||
$matcher!(
|
$matcher!(
|
||||||
|
// Big names
|
||||||
"yield",
|
"yield",
|
||||||
"sleep",
|
"sleep",
|
||||||
"hash",
|
"hash",
|
||||||
"loadFromDevice",
|
"load",
|
||||||
"loadBatchNamed",
|
"loadBatched",
|
||||||
"loadBatch",
|
"loadBatchedNamed",
|
||||||
"setOnDevice",
|
"set",
|
||||||
"setOnDeviceBatched",
|
"setBatched",
|
||||||
"setOnDeviceBatchedNamed",
|
"setBatchedNamed",
|
||||||
"acos",
|
"acos",
|
||||||
"asin",
|
"asin",
|
||||||
"atan",
|
"atan",
|
||||||
@@ -26,7 +27,14 @@ macro_rules! with_syscalls {
|
|||||||
"sin",
|
"sin",
|
||||||
"sqrt",
|
"sqrt",
|
||||||
"tan",
|
"tan",
|
||||||
"trunc"
|
"trunc",
|
||||||
|
// Lil' names
|
||||||
|
"l",
|
||||||
|
"lb",
|
||||||
|
"lbn",
|
||||||
|
"s",
|
||||||
|
"sb",
|
||||||
|
"sbn"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1587,18 +1587,25 @@ impl<'a> Parser<'a> {
|
|||||||
macro_rules! literal_or_variable {
|
macro_rules! literal_or_variable {
|
||||||
($iter:expr) => {
|
($iter:expr) => {
|
||||||
match $iter {
|
match $iter {
|
||||||
Some(expr) => match &expr.node {
|
Some(expr) => {
|
||||||
Expression::Literal(literal) => {
|
let span = expr.span;
|
||||||
LiteralOrVariable::Literal(literal.node.clone())
|
match &expr.node {
|
||||||
}
|
Expression::Literal(literal) => Spanned {
|
||||||
Expression::Variable(ident) => LiteralOrVariable::Variable(ident.clone()),
|
span,
|
||||||
|
node: LiteralOrVariable::Literal(literal.node.clone()),
|
||||||
|
},
|
||||||
|
Expression::Variable(ident) => Spanned {
|
||||||
|
span,
|
||||||
|
node: LiteralOrVariable::Variable(ident.clone()),
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
||||||
))
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
@@ -1611,8 +1618,11 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
macro_rules! get_arg {
|
macro_rules! get_arg {
|
||||||
($matcher: ident, $arg: expr) => {
|
($matcher: ident, $arg: expr) => {
|
||||||
match $arg {
|
match $arg.node {
|
||||||
LiteralOrVariable::$matcher(i) => i,
|
LiteralOrVariable::$matcher(i) => Spanned {
|
||||||
|
node: i,
|
||||||
|
span: $arg.span,
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::InvalidSyntax(
|
return Err(Error::InvalidSyntax(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
@@ -1641,16 +1651,23 @@ impl<'a> Parser<'a> {
|
|||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let lit_str = literal_or_variable!(args.next());
|
let lit_str = literal_or_variable!(args.next());
|
||||||
|
|
||||||
let LiteralOrVariable::Literal(lit_str) = lit_str else {
|
let Spanned {
|
||||||
|
node: LiteralOrVariable::Literal(lit_str),
|
||||||
|
span,
|
||||||
|
} = lit_str
|
||||||
|
else {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(SysCall::System(System::Hash(lit_str)))
|
Ok(SysCall::System(System::Hash(Spanned {
|
||||||
|
node: lit_str,
|
||||||
|
span,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
"loadFromDevice" => {
|
"load" | "l" => {
|
||||||
check_length(self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
|
||||||
@@ -1660,7 +1677,10 @@ impl<'a> Parser<'a> {
|
|||||||
let variable = match next_arg {
|
let variable = match next_arg {
|
||||||
Some(expr) => match expr.node {
|
Some(expr) => match expr.node {
|
||||||
Expression::Literal(spanned_lit) => match spanned_lit.node {
|
Expression::Literal(spanned_lit) => match spanned_lit.node {
|
||||||
Literal::String(s) => s,
|
Literal::String(s) => Spanned {
|
||||||
|
node: s,
|
||||||
|
span: spanned_lit.span,
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedToken(
|
return Err(Error::UnexpectedToken(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
@@ -1685,10 +1705,38 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
||||||
device,
|
device,
|
||||||
Literal::String(variable),
|
Spanned {
|
||||||
|
node: Literal::String(variable.node),
|
||||||
|
span: variable.span,
|
||||||
|
},
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"setOnDevice" => {
|
"loadBatched" | "lb" => {
|
||||||
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
let device_hash = literal_or_variable!(args.next());
|
||||||
|
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
let batch_mode = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::LoadBatch(
|
||||||
|
device_hash,
|
||||||
|
logic_type,
|
||||||
|
batch_mode,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
"loadBatchedNamed" | "lbn" => {
|
||||||
|
check_length(self, &invocation.arguments, 4)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
let dev_hash = literal_or_variable!(args.next());
|
||||||
|
let name_hash = literal_or_variable!(args.next());
|
||||||
|
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
let batch_mode = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::LoadBatchNamed(
|
||||||
|
dev_hash, name_hash, logic_type, batch_mode,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
"set" | "s" => {
|
||||||
check_length(self, &invocation.arguments, 3)?;
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let device = literal_or_variable!(args.next());
|
let device = literal_or_variable!(args.next());
|
||||||
@@ -1696,22 +1744,44 @@ impl<'a> Parser<'a> {
|
|||||||
let variable = args.next().ok_or(Error::UnexpectedEOF)?;
|
let variable = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
Ok(SysCall::System(sys_call::System::SetOnDevice(
|
Ok(SysCall::System(sys_call::System::SetOnDevice(
|
||||||
device,
|
device,
|
||||||
Literal::String(logic_type.to_string().replace("\"", "")),
|
Spanned {
|
||||||
|
node: Literal::String(logic_type.node.to_string().replace("\"", "")),
|
||||||
|
span: logic_type.span,
|
||||||
|
},
|
||||||
boxed!(variable),
|
boxed!(variable),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"setOnDeviceBatched" => {
|
"setBatched" | "sb" => {
|
||||||
check_length(self, &invocation.arguments, 3)?;
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
let mut args = invocation.arguments.into_iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
let device_hash = literal_or_variable!(args.next());
|
let device_hash = literal_or_variable!(args.next());
|
||||||
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
let variable = args.next().ok_or(Error::UnexpectedEOF)?;
|
let variable = args.next().ok_or(Error::UnexpectedEOF)?;
|
||||||
|
|
||||||
Ok(SysCall::System(sys_call::System::SetOnDeviceBatched(
|
Ok(SysCall::System(sys_call::System::SetOnDeviceBatched(
|
||||||
device_hash,
|
device_hash,
|
||||||
Literal::String(logic_type.to_string().replace("\"", "")),
|
Spanned {
|
||||||
|
node: Literal::String(logic_type.to_string().replace("\"", "")),
|
||||||
|
span: logic_type.span,
|
||||||
|
},
|
||||||
boxed!(variable),
|
boxed!(variable),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
"setBatchedNamed" | "sbn" => {
|
||||||
|
check_length(self, &invocation.arguments, 4)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
let device_hash = literal_or_variable!(args.next());
|
||||||
|
let name_hash = literal_or_variable!(args.next());
|
||||||
|
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
let expr = Box::new(args.next().ok_or(Error::UnexpectedEOF)?);
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::SetOnDeviceBatchedNamed(
|
||||||
|
device_hash,
|
||||||
|
name_hash,
|
||||||
|
logic_type,
|
||||||
|
expr,
|
||||||
|
)))
|
||||||
|
}
|
||||||
_ => Err(Error::UnsupportedKeyword(
|
_ => Err(Error::UnsupportedKeyword(
|
||||||
self.current_span(),
|
self.current_span(),
|
||||||
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
self.current_token.clone().ok_or(Error::UnexpectedEOF)?,
|
||||||
|
|||||||
@@ -142,58 +142,68 @@ documented! {
|
|||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `sleep(number|var);`
|
/// `sleep(number|var);`
|
||||||
Sleep(Box<Spanned<Expression>>),
|
Sleep(Box<Spanned<Expression>>),
|
||||||
/// Gets the in-game hash for a specific prefab name.
|
/// Gets the in-game hash for a specific prefab name. NOTE! This call is COMPLETELY
|
||||||
|
/// optimized away unless you bind it to a `let` variable. If you use a `const` variable
|
||||||
|
/// however, the hash is correctly computed at compile time and substitued automatically.
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `HASH("prefabName")`
|
/// `HASH("prefabName")`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `HASH("prefabName");`
|
/// `hash("prefabName");`
|
||||||
Hash(Literal),
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```
|
||||||
|
/// const compDoor = hash("StructureCompositeDoor");
|
||||||
|
/// setOnDeviceBatched(compDoor, "Lock", true);
|
||||||
|
/// ```
|
||||||
|
Hash(Spanned<Literal>),
|
||||||
/// Represents a function which loads a device variable into a register.
|
/// Represents a function which loads a device variable into a register.
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `l r? d? var`
|
/// `l r? d? var`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `loadFromDevice(deviceType, "LogicType");`
|
/// `load(deviceType, "LogicType");`
|
||||||
LoadFromDevice(LiteralOrVariable, Literal),
|
LoadFromDevice(Spanned<LiteralOrVariable>, Spanned<Literal>),
|
||||||
/// Function which gets a LogicType from all connected network devices that match
|
/// Function which gets a LogicType from all connected network devices that match
|
||||||
/// the provided device hash and name, aggregating them via a batchMode
|
/// the provided device hash and name, aggregating them via a batchMode
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `lbn r? deviceHash nameHash logicType batchMode`
|
/// `lbn r? deviceHash nameHash logicType batchMode`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `loadFromDeviceBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");`
|
/// `loadBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");`
|
||||||
LoadBatchNamed(
|
LoadBatchNamed(
|
||||||
LiteralOrVariable,
|
Spanned<LiteralOrVariable>,
|
||||||
Box<Spanned<Expression>>,
|
Spanned<LiteralOrVariable>,
|
||||||
Literal,
|
Spanned<Literal>,
|
||||||
Literal,
|
Spanned<Literal>,
|
||||||
),
|
),
|
||||||
/// Loads a LogicType from all connected network devices, aggregating them via a
|
/// Loads a LogicType from all connected network devices, aggregating them via a
|
||||||
/// batchMode
|
/// BatchMode
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `lb r? deviceHash logicType batchMode`
|
/// `lb r? deviceHash logicType batchMode`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `loadFromDeviceBatched(deviceHash, "Variable", "LogicType");`
|
/// `loadBatched(deviceHash, "Variable", "LogicType");`
|
||||||
LoadBatch(LiteralOrVariable, Literal, Literal),
|
LoadBatch(Spanned<LiteralOrVariable>, Spanned<Literal>, Spanned<Literal>),
|
||||||
/// Represents a function which stores a setting into a specific device.
|
/// Represents a function which stores a setting into a specific device.
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `s d? logicType r?`
|
/// `s d? logicType r?`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `setOnDevice(deviceType, "Variable", (number|var));`
|
/// `set(deviceType, "Variable", (number|var));`
|
||||||
SetOnDevice(LiteralOrVariable, Literal, Box<Spanned<Expression>>),
|
SetOnDevice(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>),
|
||||||
/// Represents a function which stores a setting to all devices that match
|
/// Represents a function which stores a setting to all devices that match
|
||||||
/// the given deviceHash
|
/// the given deviceHash
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `sb deviceHash logicType r?`
|
/// `sb deviceHash logicType r?`
|
||||||
SetOnDeviceBatched(LiteralOrVariable, Literal, Box<Spanned<Expression>>),
|
/// ## Slang
|
||||||
|
/// `setBatched(deviceHash, "LogicType", (number|var))`
|
||||||
|
SetOnDeviceBatched(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>),
|
||||||
/// Represents a function which stores a setting to all devices that match
|
/// Represents a function which stores a setting to all devices that match
|
||||||
/// both the given deviceHash AND the given nameHash
|
/// both the given deviceHash AND the given nameHash
|
||||||
/// ## IC10
|
/// ## IC10
|
||||||
/// `sbn deviceHash nameHash logicType r?`
|
/// `sbn deviceHash nameHash logicType r?`
|
||||||
/// ## Slang
|
/// ## Slang
|
||||||
/// `setOnDeviceBatchedNamed(deviceType, nameHash, "LogicType", (number|var))`
|
/// `setBatchedNamed(deviceHash, nameHash, "LogicType", (number|var))`
|
||||||
SetOnDeviceBatchedNamed(
|
SetOnDeviceBatchedNamed(
|
||||||
LiteralOrVariable,
|
Spanned<LiteralOrVariable>,
|
||||||
LiteralOrVariable,
|
Spanned<LiteralOrVariable>,
|
||||||
Literal,
|
Spanned<Literal>,
|
||||||
Box<Spanned<Expression>>,
|
Box<Spanned<Expression>>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user