Lifetimes are declared, now I gotta fix the lifetime issues
This commit is contained in:
@@ -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)* ])
|
||||||
|
|||||||
@@ -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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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),
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user