Lifetimes are declared, now I gotta fix the lifetime issues

This commit is contained in:
2025-12-09 13:51:54 -07:00
parent d40b759442
commit d9a7a31306
4 changed files with 165 additions and 182 deletions

View File

@@ -3,15 +3,10 @@ macro_rules! documented {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Internal Helper: Filter doc comments // Internal Helper: Filter doc comments
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Case 1: Doc comment. Return Some("string").
// We match the specific structure of a doc attribute.
(@doc_filter #[doc = $doc:expr]) => { (@doc_filter #[doc = $doc:expr]) => {
Some($doc) Some($doc)
}; };
// Case 2: Other attributes (derives, etc.). Return None.
// We catch any other token sequence inside the brackets.
(@doc_filter #[$($attr:tt)*]) => { (@doc_filter #[$($attr:tt)*]) => {
None None
}; };
@@ -30,23 +25,59 @@ macro_rules! documented {
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Main Macro Entry Point // Entry Point 1: Enum with a single Lifetime (e.g. enum Foo<'a>)
// -------------------------------------------------------------------------
(
$(#[$enum_attr:meta])* $vis:vis enum $name:ident < $lt:lifetime > {
$($body:tt)*
}
) => {
documented!(@generate
meta: [$(#[$enum_attr])*],
vis: [$vis],
name: [$name],
generics: [<$lt>],
body: [$($body)*]
);
};
// -------------------------------------------------------------------------
// Entry Point 2: Regular Enum (No Generics)
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
( (
$(#[$enum_attr:meta])* $vis:vis enum $name:ident { $(#[$enum_attr:meta])* $vis:vis enum $name:ident {
$($body:tt)*
}
) => {
documented!(@generate
meta: [$(#[$enum_attr])*],
vis: [$vis],
name: [$name],
generics: [],
body: [$($body)*]
);
};
// -------------------------------------------------------------------------
// Code Generator (Shared Logic)
// -------------------------------------------------------------------------
(@generate
meta: [$(#[$enum_attr:meta])*],
vis: [$vis:vis],
name: [$name:ident],
generics: [$($generics:tt)*],
body: [
$( $(
// Capture attributes as a sequence of token trees inside brackets
// to avoid "local ambiguity" and handle multi-token attributes (like doc="...").
$(#[ $($variant_attr:tt)* ])* $(#[ $($variant_attr:tt)* ])*
$variant:ident $variant:ident
$( ($($tuple:tt)*) )? $( ($($tuple:tt)*) )?
$( {$($structure:tt)*} )? $( {$($structure:tt)*} )?
),* $(,)? ),* $(,)?
} ]
) => { ) => {
// 1. Generate the actual Enum definition // 1. Generate the Enum Definition
$(#[$enum_attr])* $(#[$enum_attr])*
$vis enum $name { $vis enum $name $($generics)* {
$( $(
$(#[ $($variant_attr)* ])* $(#[ $($variant_attr)* ])*
$variant $variant
@@ -55,20 +86,19 @@ macro_rules! documented {
)* )*
} }
// 2. Implement the Documentation Trait // 2. Implement Documentation Trait
impl Documentation for $name { // We apply the captured generics (e.g., <'a>) to both the impl and the type
impl $($generics)* Documentation for $name $($generics)* {
fn docs(&self) -> String { fn docs(&self) -> String {
match self { match self {
$( $(
documented!(@arm $name $variant $( ($($tuple)*) )? $( {$($structure)*} )? ) => { documented!(@arm $name $variant $( ($($tuple)*) )? $( {$($structure)*} )? ) => {
// Create a temporary array of Option<&str> for all attributes
let doc_lines: &[Option<&str>] = &[ let doc_lines: &[Option<&str>] = &[
$( $(
documented!(@doc_filter #[ $($variant_attr)* ]) documented!(@doc_filter #[ $($variant_attr)* ])
),* ),*
]; ];
// Filter out the Nones (non-doc attributes), join, and return
doc_lines.iter() doc_lines.iter()
.filter_map(|&d| d) .filter_map(|&d| d)
.collect::<Vec<_>>() .collect::<Vec<_>>()
@@ -80,7 +110,6 @@ macro_rules! documented {
} }
} }
// 3. Implement Static Documentation Provider
#[allow(dead_code)] #[allow(dead_code)]
fn get_all_documentation() -> Vec<(&'static str, String)> { fn get_all_documentation() -> Vec<(&'static str, String)> {
vec![ vec![
@@ -88,7 +117,6 @@ macro_rules! documented {
( (
stringify!($variant), stringify!($variant),
{ {
// Re-use the same extraction logic
let doc_lines: &[Option<&str>] = &[ let doc_lines: &[Option<&str>] = &[
$( $(
documented!(@doc_filter #[ $($variant_attr)* ]) documented!(@doc_filter #[ $($variant_attr)* ])

View File

@@ -4,7 +4,7 @@ mod test;
pub mod tree_node; pub mod tree_node;
use crate::sys_call::{Math, System}; use crate::sys_call::{Math, System};
use std::io::SeekFrom; use std::{borrow::Cow, io::SeekFrom};
use sys_call::SysCall; use sys_call::SysCall;
use thiserror::Error; use thiserror::Error;
use tokenizer::{ use tokenizer::{
@@ -119,7 +119,7 @@ impl<'a> Parser<'a> {
} }
/// Calculates a Span from a given Token reference. /// Calculates a Span from a given Token reference.
fn token_to_span<'t>(t: &'t Token<'a>) -> Span { fn token_to_span(t: &Token<'a>) -> Span {
Span { Span {
start_line: t.line, start_line: t.line,
start_col: t.span.start, start_col: t.span.start,
@@ -141,7 +141,7 @@ impl<'a> Parser<'a> {
} }
/// Helper to run a parsing closure and wrap the result in a Spanned struct /// Helper to run a parsing closure and wrap the result in a Spanned struct
fn spanned<F, T>(&mut self, parser: F) -> Result<Spanned<T>, Error> fn spanned<F, T>(&mut self, parser: F) -> Result<Spanned<T>, Error<'a>>
where where
F: FnOnce(&mut Self) -> Result<T, Error>, F: FnOnce(&mut Self) -> Result<T, Error>,
{ {
@@ -176,7 +176,7 @@ impl<'a> Parser<'a> {
}) })
} }
fn synchronize(&mut self) -> Result<(), Error> { fn synchronize(&mut self) -> Result<(), Error<'a>> {
self.assign_next()?; self.assign_next()?;
while let Some(token) = &self.current_token { while let Some(token) = &self.current_token {
@@ -202,14 +202,14 @@ impl<'a> Parser<'a> {
Ok(()) Ok(())
} }
pub fn parse_all(&mut self) -> Result<Option<tree_node::Expression>, Error> { pub fn parse_all(&mut self) -> Result<Option<tree_node::Expression<'a>>, Error<'a>> {
let first_token = self.tokenizer.peek().unwrap_or(None); let first_token = self.tokenizer.peek().unwrap_or(None);
let (start_line, start_col) = first_token let (start_line, start_col) = first_token
.as_ref() .as_ref()
.map(|tok| (tok.line, tok.span.start)) .map(|tok| (tok.line, tok.span.start))
.unwrap_or((0, 0)); .unwrap_or((0, 0));
let mut expressions = Vec::<Spanned<Expression>>::new(); let mut expressions = Vec::<Spanned<Expression<'a>>>::new();
loop { loop {
match self.tokenizer.peek() { match self.tokenizer.peek() {
@@ -253,7 +253,7 @@ impl<'a> Parser<'a> {
}))) })))
} }
pub fn parse(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, Error> { pub fn parse(&mut self) -> Result<Option<Spanned<tree_node::Expression<'a>>>, Error<'a>> {
self.assign_next()?; self.assign_next()?;
if self.current_token.is_none() { if self.current_token.is_none() {
@@ -269,17 +269,17 @@ impl<'a> Parser<'a> {
Ok(expr) Ok(expr)
} }
fn assign_next(&'a mut self) -> Result<(), Error> { fn assign_next(&'a mut self) -> Result<(), Error<'a>> {
self.current_token = self.tokenizer.next_token()?; self.current_token = self.tokenizer.next_token()?;
Ok(()) Ok(())
} }
fn get_next(&'a mut self) -> Result<Option<Token>, Error> { fn get_next(&'a mut self) -> Result<Option<Token<'a>>, Error<'a>> {
self.assign_next()?; self.assign_next()?;
Ok(self.current_token.clone()) Ok(self.current_token.clone())
} }
fn expression(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, Error> { fn expression(&mut self) -> Result<Option<Spanned<tree_node::Expression<'a>>>, Error<'a>> {
// Parse the Left Hand Side (unary/primary expression) // Parse the Left Hand Side (unary/primary expression)
let lhs = self.unary()?; let lhs = self.unary()?;
@@ -310,8 +310,8 @@ impl<'a> Parser<'a> {
/// Handles dot notation chains: x.y.z() /// Handles dot notation chains: x.y.z()
fn parse_postfix( fn parse_postfix(
&mut self, &mut self,
mut lhs: Spanned<Expression>, mut lhs: Spanned<Expression<'a>>,
) -> Result<Spanned<Expression>, Error> { ) -> Result<Spanned<Expression<'a>>, Error<'a>> {
loop { loop {
if self_matches_peek!(self, TokenType::Symbol(Symbol::Dot)) { if self_matches_peek!(self, TokenType::Symbol(Symbol::Dot)) {
self.assign_next()?; // consume Dot self.assign_next()?; // consume Dot
@@ -332,7 +332,7 @@ impl<'a> Parser<'a> {
if self_matches_peek!(self, TokenType::Symbol(Symbol::LParen)) { if self_matches_peek!(self, TokenType::Symbol(Symbol::LParen)) {
// Method Call // Method Call
self.assign_next()?; // consume '(' self.assign_next()?; // consume '('
let mut arguments = Vec::<Spanned<Expression>>::new(); let mut arguments = Vec::<Spanned<Expression<'a>>>::new();
while !token_matches!( while !token_matches!(
self.get_next()?.ok_or(Error::UnexpectedEOF)?, self.get_next()?.ok_or(Error::UnexpectedEOF)?,
@@ -417,7 +417,7 @@ impl<'a> Parser<'a> {
Ok(lhs) Ok(lhs)
} }
fn unary(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, Error> { fn unary(&mut self) -> Result<Option<Spanned<tree_node::Expression<'a>>>, Error<'a>> {
macro_rules! matches_keyword { macro_rules! matches_keyword {
($keyword:expr, $($pattern:pat),+) => { ($keyword:expr, $($pattern:pat),+) => {
matches!($keyword, $($pattern)|+) matches!($keyword, $($pattern)|+)
@@ -574,17 +574,6 @@ impl<'a> Parser<'a> {
let start_span = self.current_span(); let start_span = self.current_span();
self.assign_next()?; self.assign_next()?;
let inner_expr = self.unary()?.ok_or(Error::UnexpectedEOF)?; let inner_expr = self.unary()?.ok_or(Error::UnexpectedEOF)?;
// NOTE: Unary negation can also have postfix applied to the inner expression
// But generally -a.b parses as -(a.b), which is what parse_postfix ensures if called here.
// However, we call parse_postfix on the RESULT of unary in expression(), so
// `expression` sees `Negation`. `parse_postfix` doesn't apply to Negation node unless we allow it?
// Actually, `x.y` binds tighter than `-`. `postfix` logic belongs inside `unary` logic or
// `expression` logic.
// If I have `-x.y`, standard precedence says `-(x.y)`.
// `unary` returns `Negation(x)`. Then `expression` calls `postfix` on `Negation(x)`.
// `postfix` loop runs on `Negation`. This implies `(-x).y`. This is usually WRONG.
// `.` binds tighter than `-`.
// So `unary` must call `postfix` on the *operand* of the negation.
let inner_with_postfix = self.parse_postfix(inner_expr)?; let inner_with_postfix = self.parse_postfix(inner_expr)?;
@@ -631,7 +620,7 @@ impl<'a> Parser<'a> {
Ok(expr) Ok(expr)
} }
fn get_infix_child_node(&mut self) -> Result<Spanned<tree_node::Expression>, Error> { fn get_infix_child_node(&mut self) -> Result<Spanned<tree_node::Expression<'a>>, Error<'a>> {
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
let start_span = self.current_span(); let start_span = self.current_span();
@@ -715,7 +704,7 @@ impl<'a> Parser<'a> {
self.parse_postfix(expr) self.parse_postfix(expr)
} }
fn device(&mut self) -> Result<DeviceDeclarationExpression, Error> { fn device(&mut self) -> Result<DeviceDeclarationExpression<'a>, Error<'a>> {
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
if !self_matches_current!(self, TokenType::Keyword(Keyword::Device)) { if !self_matches_current!(self, TokenType::Keyword(Keyword::Device)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
@@ -730,7 +719,7 @@ impl<'a> Parser<'a> {
TokenType::Identifier(ref id) => id.clone(), TokenType::Identifier(ref id) => id.clone(),
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(identifier_token), Self::token_to_span(&identifier_token),
identifier_token.clone(), identifier_token.clone(),
)); ));
} }
@@ -739,7 +728,7 @@ impl<'a> Parser<'a> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token.clone(),
)); ));
} }
@@ -749,7 +738,7 @@ impl<'a> Parser<'a> {
TokenType::String(ref id) => id.clone(), TokenType::String(ref id) => id.clone(),
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(device_token), Self::token_to_span(&device_token),
device_token.clone(), device_token.clone(),
)); ));
} }
@@ -764,7 +753,10 @@ impl<'a> Parser<'a> {
}) })
} }
fn infix(&mut self, previous: Spanned<Expression>) -> Result<Spanned<Expression>, Error> { fn infix(
&mut self,
previous: Spanned<Expression<'a>>,
) -> Result<Spanned<Expression<'a>>, Error<'a>> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?.clone(); let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?.clone();
match previous.node { match previous.node {
@@ -1072,7 +1064,7 @@ impl<'a> Parser<'a> {
expressions.pop().ok_or(Error::UnexpectedEOF) expressions.pop().ok_or(Error::UnexpectedEOF)
} }
fn priority(&mut self) -> Result<Option<Box<Spanned<Expression>>>, Error> { fn priority(&mut self) -> Result<Option<Box<Spanned<Expression<'a>>>>, Error<'a>> {
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
@@ -1087,15 +1079,15 @@ impl<'a> Parser<'a> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::RParen)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::RParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token,
)); ));
} }
Ok(Some(boxed!(expression))) Ok(Some(boxed!(expression)))
} }
fn invocation(&mut self) -> Result<InvocationExpression, Error> { fn invocation(&mut self) -> Result<InvocationExpression<'a>, Error<'a>> {
let identifier_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let identifier_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
let identifier_span = Self::token_to_span(identifier_token); let identifier_span = Self::token_to_span(identifier_token);
let identifier = match identifier_token.token_type { let identifier = match identifier_token.token_type {
@@ -1111,8 +1103,8 @@ impl<'a> Parser<'a> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token,
)); ));
} }
@@ -1138,8 +1130,8 @@ impl<'a> Parser<'a> {
{ {
let next_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(next_token), Self::token_to_span(&next_token),
next_token.clone(), next_token,
)); ));
} }
@@ -1157,7 +1149,7 @@ impl<'a> Parser<'a> {
}) })
} }
fn block(&mut self) -> Result<BlockExpression, Error> { fn block(&mut self) -> Result<BlockExpression<'a>, Error<'a>> {
let mut expressions = Vec::<Spanned<Expression>>::new(); let mut expressions = Vec::<Spanned<Expression>>::new();
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
@@ -1180,7 +1172,7 @@ impl<'a> Parser<'a> {
if token_matches!(current_token, TokenType::Keyword(Keyword::Return)) { if token_matches!(current_token, TokenType::Keyword(Keyword::Return)) {
// Need to capture return span // Need to capture return span
let ret_start_span = Self::token_to_span(current_token); let ret_start_span = Self::token_to_span(&current_token);
self.assign_next()?; self.assign_next()?;
let expression = self.expression()?.ok_or(Error::UnexpectedEOF)?; let expression = self.expression()?.ok_or(Error::UnexpectedEOF)?;
@@ -1199,25 +1191,19 @@ impl<'a> Parser<'a> {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::Semicolon)) { if !token_matches!(next, TokenType::Symbol(Symbol::Semicolon)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::RBrace)) { if !token_matches!(next, TokenType::Symbol(Symbol::RBrace)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
} }
Ok(BlockExpression(expressions)) Ok(BlockExpression(expressions))
} }
fn const_declaration(&mut self) -> Result<ConstDeclarationExpression, Error> { fn const_declaration(&mut self) -> Result<ConstDeclarationExpression<'a>, Error<'a>> {
// const // const
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
if !self_matches_current!(self, TokenType::Keyword(Keyword::Const)) { if !self_matches_current!(self, TokenType::Keyword(Keyword::Const)) {
@@ -1229,7 +1215,7 @@ impl<'a> Parser<'a> {
// variable_name // variable_name
let ident_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let ident_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
let ident_span = Self::token_to_span(ident_token); let ident_span = Self::token_to_span(&ident_token);
let ident = match ident_token.token_type { let ident = match ident_token.token_type {
TokenType::Identifier(ref id) => id.clone(), TokenType::Identifier(ref id) => id.clone(),
_ => return Err(Error::UnexpectedToken(ident_span, ident_token.clone())), _ => return Err(Error::UnexpectedToken(ident_span, ident_token.clone())),
@@ -1287,7 +1273,7 @@ impl<'a> Parser<'a> {
} }
} }
fn declaration(&mut self) -> Result<Expression, Error> { fn declaration(&mut self) -> Result<Expression<'a>, Error<'a>> {
let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?;
if !self_matches_current!(self, TokenType::Keyword(Keyword::Let)) { if !self_matches_current!(self, TokenType::Keyword(Keyword::Let)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
@@ -1296,13 +1282,13 @@ impl<'a> Parser<'a> {
)); ));
} }
let identifier_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let identifier_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
let identifier_span = Self::token_to_span(identifier_token); let identifier_span = Self::token_to_span(&identifier_token);
let identifier = match identifier_token.token_type { let identifier = match identifier_token.token_type {
TokenType::Identifier(ref id) => id.clone(), TokenType::Identifier(ref id) => id.clone(),
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(identifier_token), Self::token_to_span(&identifier_token),
identifier_token.clone(), identifier_token,
)); ));
} }
}; };
@@ -1322,8 +1308,8 @@ impl<'a> Parser<'a> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::Semicolon)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::Semicolon)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token,
)); ));
} }
@@ -1336,7 +1322,7 @@ impl<'a> Parser<'a> {
)) ))
} }
fn literal(&mut self) -> Result<Literal, Error> { fn literal(&mut self) -> Result<Literal<'a>, Error<'a>> {
let current_token = self.current_token.clone().ok_or(Error::UnexpectedEOF)?; let current_token = self.current_token.clone().ok_or(Error::UnexpectedEOF)?;
let literal = match current_token.token_type { let literal = match current_token.token_type {
TokenType::Number(num) => Literal::Number(num), TokenType::Number(num) => Literal::Number(num),
@@ -1346,11 +1332,11 @@ impl<'a> Parser<'a> {
Some(Token { Some(Token {
token_type: TokenType::Number(num), token_type: TokenType::Number(num),
.. ..
}) => Literal::Number(-*num), }) => Literal::Number(-num),
Some(wrong_token) => { Some(wrong_token) => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(wrong_token), Self::token_to_span(&wrong_token),
wrong_token.clone(), wrong_token,
)); ));
} }
None => return Err(Error::UnexpectedEOF), None => return Err(Error::UnexpectedEOF),
@@ -1366,14 +1352,11 @@ impl<'a> Parser<'a> {
Ok(literal) Ok(literal)
} }
fn if_expression(&mut self) -> Result<IfExpression, Error> { fn if_expression(&mut self) -> Result<IfExpression<'a>, Error<'a>> {
// 'if' is current // 'if' is current
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::LParen)) { if !token_matches!(next, TokenType::Symbol(Symbol::LParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
self.assign_next()?; self.assign_next()?;
@@ -1381,18 +1364,12 @@ impl<'a> Parser<'a> {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::RParen)) { if !token_matches!(next, TokenType::Symbol(Symbol::RParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) { if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let body = self.spanned(|p| p.block())?; let body = self.spanned(|p| p.block())?;
@@ -1417,10 +1394,7 @@ impl<'a> Parser<'a> {
})) }))
} else { } else {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
} else { } else {
None None
@@ -1433,13 +1407,10 @@ impl<'a> Parser<'a> {
}) })
} }
fn loop_expression(&mut self) -> Result<LoopExpression, Error> { fn loop_expression(&mut self) -> Result<LoopExpression<'a>, Error<'a>> {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) { if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let body = self.spanned(|p| p.block())?; let body = self.spanned(|p| p.block())?;
@@ -1447,13 +1418,10 @@ impl<'a> Parser<'a> {
Ok(LoopExpression { body }) Ok(LoopExpression { body })
} }
fn while_expression(&mut self) -> Result<WhileExpression, Error> { fn while_expression(&mut self) -> Result<WhileExpression<'a>, Error<'a>> {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::LParen)) { if !token_matches!(next, TokenType::Symbol(Symbol::LParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
self.assign_next()?; self.assign_next()?;
@@ -1461,18 +1429,12 @@ impl<'a> Parser<'a> {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::RParen)) { if !token_matches!(next, TokenType::Symbol(Symbol::RParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) { if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
let body = self.block()?; let body = self.block()?;
@@ -1483,29 +1445,26 @@ impl<'a> Parser<'a> {
}) })
} }
fn function(&mut self) -> Result<FunctionExpression, Error> { fn function(&mut self) -> Result<FunctionExpression<'a>, Error<'a>> {
// 'fn' is current // 'fn' is current
let fn_ident_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let fn_ident_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
let fn_ident_span = Self::token_to_span(fn_ident_token); let fn_ident_span = Self::token_to_span(&fn_ident_token);
let fn_ident = match fn_ident_token.token_type { let fn_ident = match fn_ident_token.token_type {
TokenType::Identifier(ref id) => id.clone(), TokenType::Identifier(ref id) => id.clone(),
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(fn_ident_span, fn_ident_token));
Self::token_to_span(fn_ident_token),
fn_ident_token.clone(),
));
} }
}; };
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::LParen)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token,
)); ));
} }
let mut arguments = Vec::<Spanned<String>>::new(); let mut arguments = Vec::<Spanned<Cow<'a, str>>>::new();
while !token_matches!( while !token_matches!(
self.get_next()?.ok_or(Error::UnexpectedEOF)?, self.get_next()?.ok_or(Error::UnexpectedEOF)?,
@@ -1516,10 +1475,7 @@ impl<'a> Parser<'a> {
let argument = match current_token.token_type { let argument = match current_token.token_type {
TokenType::Identifier(ref id) => id.clone(), TokenType::Identifier(ref id) => id.clone(),
_ => { _ => {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(arg_span, current_token.clone()));
Self::token_to_span(current_token),
current_token.clone(),
));
} }
}; };
@@ -1541,10 +1497,7 @@ impl<'a> Parser<'a> {
&& !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen)) && !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen))
{ {
let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let next = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(Self::token_to_span(&next), next));
Self::token_to_span(next),
next.clone(),
));
} }
if !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen)) { if !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen)) {
@@ -1555,8 +1508,8 @@ impl<'a> Parser<'a> {
let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; let current_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?;
if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) { if !token_matches!(current_token, TokenType::Symbol(Symbol::LBrace)) {
return Err(Error::UnexpectedToken( return Err(Error::UnexpectedToken(
Self::token_to_span(current_token), Self::token_to_span(&current_token),
current_token.clone(), current_token,
)); ));
}; };
@@ -1570,12 +1523,12 @@ impl<'a> Parser<'a> {
}) })
} }
fn syscall(&mut self) -> Result<SysCall, Error> { fn syscall(&mut self) -> Result<SysCall<'a>, Error<'a>> {
fn check_length( fn check_length<'a>(
parser: &Parser, parser: &'a Parser,
arguments: &[Spanned<Expression>], arguments: &[Spanned<Expression<'a>>],
length: usize, length: usize,
) -> Result<(), Error> { ) -> Result<(), Error<'a>> {
if arguments.len() != length { if arguments.len() != length {
return Err(Error::InvalidSyntax( return Err(Error::InvalidSyntax(
parser.current_span(), parser.current_span(),
@@ -1636,7 +1589,7 @@ impl<'a> Parser<'a> {
let invocation = self.invocation()?; let invocation = self.invocation()?;
match invocation.name.node.as_str() { match invocation.name.node.as_ref() {
// System SysCalls // System SysCalls
"yield" => { "yield" => {
check_length(self, &invocation.arguments, 0)?; check_length(self, &invocation.arguments, 0)?;
@@ -1764,7 +1717,9 @@ impl<'a> Parser<'a> {
Ok(SysCall::System(sys_call::System::SetOnDevice( Ok(SysCall::System(sys_call::System::SetOnDevice(
device, device,
Spanned { Spanned {
node: Literal::String(logic_type.node.to_string().replace("\"", "")), node: Literal::String(Cow::from(
logic_type.node.to_string().replace("\"", ""),
)),
span: logic_type.span, span: logic_type.span,
}, },
boxed!(variable), boxed!(variable),
@@ -1783,7 +1738,7 @@ impl<'a> Parser<'a> {
Ok(SysCall::System(sys_call::System::SetOnDeviceBatched( Ok(SysCall::System(sys_call::System::SetOnDeviceBatched(
device_hash, device_hash,
Spanned { Spanned {
node: Literal::String(logic_type.to_string().replace("\"", "")), node: Literal::String(Cow::from(logic_type.to_string().replace("\"", ""))),
span: logic_type.span, span: logic_type.span,
}, },
boxed!(variable), boxed!(variable),

View File

@@ -4,73 +4,73 @@ use helpers::prelude::*;
documented! { documented! {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Math { pub enum Math<'a> {
/// Returns the angle in radians whose cosine is the specified number. /// Returns the angle in radians whose cosine is the specified number.
/// ## IC10 /// ## IC10
/// `acos r? a(r?|num)` /// `acos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = acos(number|var|expression);` /// `let item = acos(number|var|expression);`
Acos(Box<Spanned<Expression>>), Acos(Box<Spanned<Expression<'a>>>),
/// Returns the angle in radians whose sine is the specified number. /// Returns the angle in radians whose sine is the specified number.
/// ## IC10 /// ## IC10
/// `asin r? a(r?|num)` /// `asin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = asin(number|var|expression);` /// `let item = asin(number|var|expression);`
Asin(Box<Spanned<Expression>>), Asin(Box<Spanned<Expression<'a>>>),
/// Returns the angle in radians whose tangent is the specified number. /// Returns the angle in radians whose tangent is the specified number.
/// ## IC10 /// ## IC10
/// `atan r? a(r?|num)` /// `atan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = atan(number|var|expression);` /// `let item = atan(number|var|expression);`
Atan(Box<Spanned<Expression>>), Atan(Box<Spanned<Expression<'a>>>),
/// Returns the angle in radians whose tangent is the quotient of the specified numbers. /// Returns the angle in radians whose tangent is the quotient of the specified numbers.
/// ## IC10 /// ## IC10
/// `atan2 r? a(r?|num) b(r?|num)` /// `atan2 r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `let item = atan2((number|var|expression), (number|var|expression));` /// `let item = atan2((number|var|expression), (number|var|expression));`
Atan2(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Atan2(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
/// Gets the absolute value of a number. /// Gets the absolute value of a number.
/// ## IC10 /// ## IC10
/// `abs r? a(r?|num)` /// `abs r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = abs((number|var|expression));` /// `let item = abs((number|var|expression));`
Abs(Box<Spanned<Expression>>), Abs(Box<Spanned<Expression<'a>>>),
/// Rounds a number up to the nearest whole number. /// Rounds a number up to the nearest whole number.
/// ## IC10 /// ## IC10
/// `ceil r? a(r?|num)` /// `ceil r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = ceil((number|var|expression));` /// `let item = ceil((number|var|expression));`
Ceil(Box<Spanned<Expression>>), Ceil(Box<Spanned<Expression<'a>>>),
/// Returns the cosine of the specified angle in radians. /// Returns the cosine of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `cos r? a(r?|num)` /// `cos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = cos((number|var|expression));` /// `let item = cos((number|var|expression));`
Cos(Box<Spanned<Expression>>), Cos(Box<Spanned<Expression<'a>>>),
/// Rounds a number down to the nearest whole number. /// Rounds a number down to the nearest whole number.
/// ## IC10 /// ## IC10
/// `floor r? a(r?|num)` /// `floor r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = floor((number|var|expression));` /// `let item = floor((number|var|expression));`
Floor(Box<Spanned<Expression>>), Floor(Box<Spanned<Expression<'a>>>),
/// Computes the natural logarithm of a number. /// Computes the natural logarithm of a number.
/// ## IC10 /// ## IC10
/// `log r? a(r?|num)` /// `log r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = log((number|var|expression));` /// `let item = log((number|var|expression));`
Log(Box<Spanned<Expression>>), Log(Box<Spanned<Expression<'a>>>),
/// Computes the maximum of two numbers. /// Computes the maximum of two numbers.
/// ## IC10 /// ## IC10
/// `max r? a(r?|num) b(r?|num)` /// `max r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `let item = max((number|var|expression), (number|var|expression));` /// `let item = max((number|var|expression), (number|var|expression));`
Max(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Max(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
/// Computes the minimum of two numbers. /// Computes the minimum of two numbers.
/// ## IC10 /// ## IC10
/// `min r? a(r?|num) b(r?|num)` /// `min r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `let item = min((number|var|expression), (number|var|expression));` /// `let item = min((number|var|expression), (number|var|expression));`
Min(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Min(Box<Spanned<Expression<'a>>>, Box<Spanned<Expression<'a>>>),
/// Gets a random number between 0 and 1. /// Gets a random number between 0 and 1.
/// ## IC10 /// ## IC10
/// `rand r?` /// `rand r?`
@@ -82,29 +82,29 @@ documented! {
/// `sin r? a(r?|num)` /// `sin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = sin((number|var|expression));` /// `let item = sin((number|var|expression));`
Sin(Box<Spanned<Expression>>), Sin(Box<Spanned<Expression<'a>>>),
/// Computes the square root of a number. /// Computes the square root of a number.
/// ## IC10 /// ## IC10
/// `sqrt r? a(r?|num)` /// `sqrt r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = sqrt((number|var|expression));` /// `let item = sqrt((number|var|expression));`
Sqrt(Box<Spanned<Expression>>), Sqrt(Box<Spanned<Expression<'a>>>),
/// Returns the tangent of the specified angle in radians. /// Returns the tangent of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `tan r? a(r?|num)` /// `tan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = tan((number|var|expression));` /// `let item = tan((number|var|expression));`
Tan(Box<Spanned<Expression>>), Tan(Box<Spanned<Expression<'a>>>),
/// Truncates a number by removing the decimal portion. /// Truncates a number by removing the decimal portion.
/// ## IC10 /// ## IC10
/// `trunc r? a(r?|num)` /// `trunc r? a(r?|num)`
/// ## Slang /// ## Slang
/// `let item = trunc((number|var|expression));` /// `let item = trunc((number|var|expression));`
Trunc(Box<Spanned<Expression>>), Trunc(Box<Spanned<Expression<'a>>>),
} }
} }
impl std::fmt::Display for Math { impl<'a> std::fmt::Display for Math<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Math::Acos(a) => write!(f, "acos({})", a), Math::Acos(a) => write!(f, "acos({})", a),
@@ -129,7 +129,7 @@ impl std::fmt::Display for Math {
documented! { documented! {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum System { pub enum System<'a> {
/// Pauses execution for exactly 1 tick and then resumes. /// Pauses execution for exactly 1 tick and then resumes.
/// ## IC10 /// ## IC10
/// `yield` /// `yield`
@@ -141,7 +141,7 @@ documented! {
/// `sleep a(r?|num)` /// `sleep a(r?|num)`
/// ## Slang /// ## Slang
/// `sleep(number|var);` /// `sleep(number|var);`
Sleep(Box<Spanned<Expression>>), Sleep(Box<Spanned<Expression<'a>>>),
/// Gets the in-game hash for a specific prefab name. NOTE! This call is COMPLETELY /// 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 /// 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. /// however, the hash is correctly computed at compile time and substitued automatically.
@@ -155,7 +155,7 @@ documented! {
/// const compDoor = hash("StructureCompositeDoor"); /// const compDoor = hash("StructureCompositeDoor");
/// setOnDeviceBatched(compDoor, "Lock", true); /// setOnDeviceBatched(compDoor, "Lock", true);
/// ``` /// ```
Hash(Spanned<Literal>), Hash(Spanned<Literal<'a>>),
/// 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`
@@ -163,7 +163,7 @@ documented! {
/// `let item = load(deviceHash, "LogicType");` /// `let item = load(deviceHash, "LogicType");`
/// `let item = l(deviceHash, "LogicType");` /// `let item = l(deviceHash, "LogicType");`
/// `let item = deviceAlias.LogicType;` /// `let item = deviceAlias.LogicType;`
LoadFromDevice(Spanned<LiteralOrVariable>, Spanned<Literal>), LoadFromDevice(Spanned<LiteralOrVariable<'a>>, Spanned<Literal<'a>>),
/// 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
@@ -172,10 +172,10 @@ documented! {
/// `loadBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");` /// `loadBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");`
/// `lbn(deviceHash, deviceName, "LogicType", "BatchMode");` /// `lbn(deviceHash, deviceName, "LogicType", "BatchMode");`
LoadBatchNamed( LoadBatchNamed(
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable<'a>>,
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable<'a>>,
Spanned<Literal>, Spanned<Literal<'a>>,
Spanned<Literal>, Spanned<Literal<'a>>,
), ),
/// 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
@@ -184,7 +184,7 @@ documented! {
/// ## Slang /// ## Slang
/// `loadBatched(deviceHash, "Variable", "LogicType");` /// `loadBatched(deviceHash, "Variable", "LogicType");`
/// `lb(deviceHash, "Variable", "LogicType");` /// `lb(deviceHash, "Variable", "LogicType");`
LoadBatch(Spanned<LiteralOrVariable>, Spanned<Literal>, Spanned<Literal>), LoadBatch(Spanned<LiteralOrVariable<'a>>, Spanned<Literal<'a>>, Spanned<Literal<'a>>),
/// 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?`
@@ -192,7 +192,7 @@ documented! {
/// `set(deviceHash, "LogicType", (number|var));` /// `set(deviceHash, "LogicType", (number|var));`
/// `s(deviceHash, "LogicType", (number|var));` /// `s(deviceHash, "LogicType", (number|var));`
/// `deviceAlias.LogicType = (number|var);` /// `deviceAlias.LogicType = (number|var);`
SetOnDevice(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>), SetOnDevice(Spanned<LiteralOrVariable<'a>>, Spanned<Literal<'a>>, Box<Spanned<Expression<'a>>>),
/// 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
@@ -200,7 +200,7 @@ documented! {
/// ## Slang /// ## Slang
/// `setBatched(deviceHash, "LogicType", (number|var));` /// `setBatched(deviceHash, "LogicType", (number|var));`
/// `sb(deviceHash, "LogicType", (number|var));` /// `sb(deviceHash, "LogicType", (number|var));`
SetOnDeviceBatched(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>), SetOnDeviceBatched(Spanned<LiteralOrVariable<'a>>, Spanned<Literal<'a>>, Box<Spanned<Expression<'a>>>),
/// 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
@@ -209,15 +209,15 @@ documented! {
/// `setBatchedNamed(deviceHash, nameHash, "LogicType", (number|var));` /// `setBatchedNamed(deviceHash, nameHash, "LogicType", (number|var));`
/// `sbn(deviceHash, nameHash, "LogicType", (number|var));` /// `sbn(deviceHash, nameHash, "LogicType", (number|var));`
SetOnDeviceBatchedNamed( SetOnDeviceBatchedNamed(
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable<'a>>,
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable<'a>>,
Spanned<Literal>, Spanned<Literal<'a>>,
Box<Spanned<Expression>>, Box<Spanned<Expression<'a>>>,
), ),
} }
} }
impl std::fmt::Display for System { impl<'a> std::fmt::Display for System<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
System::Yield => write!(f, "yield()"), System::Yield => write!(f, "yield()"),
@@ -242,13 +242,13 @@ impl std::fmt::Display for System {
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
/// This represents built in functions that cannot be overwritten, but can be invoked by the user as functions. /// This represents built in functions that cannot be overwritten, but can be invoked by the user as functions.
pub enum SysCall { pub enum SysCall<'a> {
System(System), System(System<'a>),
/// Represents any mathmatical function that can be called. /// Represents any mathmatical function that can be called.
Math(Math), Math(Math<'a>),
} }
impl Documentation for SysCall { impl<'a> Documentation for SysCall<'a> {
fn docs(&self) -> String { fn docs(&self) -> String {
match self { match self {
Self::System(s) => s.docs(), Self::System(s) => s.docs(),
@@ -264,7 +264,7 @@ impl Documentation for SysCall {
} }
} }
impl std::fmt::Display for SysCall { impl<'a> std::fmt::Display for SysCall<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
SysCall::System(s) => write!(f, "{}", s), SysCall::System(s) => write!(f, "{}", s),
@@ -273,7 +273,7 @@ impl std::fmt::Display for SysCall {
} }
} }
impl SysCall { impl<'a> SysCall<'a> {
pub fn is_syscall(identifier: &str) -> bool { pub fn is_syscall(identifier: &str) -> bool {
tokenizer::token::is_syscall(identifier) tokenizer::token::is_syscall(identifier)
} }

View File

@@ -213,7 +213,7 @@ impl<'a> std::fmt::Display for LiteralOrVariable<'a> {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct ConstDeclarationExpression<'a> { pub struct ConstDeclarationExpression<'a> {
pub name: Spanned<Cow<'a, str>>, pub name: Spanned<Cow<'a, str>>,
pub value: LiteralOr<'a, SysCall>, pub value: LiteralOr<'a, SysCall<'a>>,
} }
impl<'a> ConstDeclarationExpression<'a> { impl<'a> ConstDeclarationExpression<'a> {
@@ -365,8 +365,8 @@ pub enum Expression<'a> {
Negation(Box<Spanned<Expression<'a>>>), Negation(Box<Spanned<Expression<'a>>>),
Priority(Box<Spanned<Expression<'a>>>), Priority(Box<Spanned<Expression<'a>>>),
Return(Box<Spanned<Expression<'a>>>), Return(Box<Spanned<Expression<'a>>>),
Syscall(Spanned<SysCall>), Syscall(Spanned<SysCall<'a>>),
Variable(Spanned<String>), Variable(Spanned<Cow<'a, str>>),
While(Spanned<WhileExpression<'a>>), While(Spanned<WhileExpression<'a>>),
} }