Compare commits

..

No commits in common. "bd8270bd5dc814222bb9b5f74820dd9d13714533" and "3271ca514c9243877df5a62cbe8650860da27d7e" have entirely different histories.

26 changed files with 424 additions and 495 deletions

View File

@ -19,7 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Boolean map (tag) - Boolean map (tag)
- Member access (e.g. `.objective` to get objective name where int is stored) - Member access (e.g. `.objective` to get objective name where int is stored)
- Return statement - Return statement
- internal `print` function
- Example: barebones compiler - Example: barebones compiler
### Changed ### Changed

View File

@ -99,7 +99,7 @@ FunctionParameterList:
```ebnf ```ebnf
ArrayVariableDeclaration: ArrayVariableDeclaration:
('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment? ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
``` ```
## ComptimeValueDeclaration ## ComptimeValueDeclaration

View File

@ -7,11 +7,11 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
LexicalError(#[from] crate::lexical::Error), LexicalError(#[from] crate::lexical::Error),
#[error(transparent)] #[error(transparent)]
ParseError(#[from] Box<crate::syntax::error::Error>), ParseError(#[from] crate::syntax::error::Error),
#[error(transparent)] #[error(transparent)]
SemanticError(#[from] crate::semantic::error::Error), SemanticError(#[from] crate::semantic::error::Error),
#[error(transparent)] #[error(transparent)]
TranspileError(#[from] Box<crate::transpile::TranspileError>), TranspileError(#[from] crate::transpile::TranspileError),
#[error("An error occurred: {0}")] #[error("An error occurred: {0}")]
Other(String), Other(String),
} }

View File

@ -12,7 +12,7 @@ pub trait FileProvider {
/// # Errors /// # Errors
/// - If an error occurs while reading the file. /// - If an error occurs while reading the file.
/// - If the file does not exist. /// - If the file does not exist.
fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error>; fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error>;
/// Reads the contents of the file at the given path. /// Reads the contents of the file at the given path.
/// ///
@ -20,7 +20,7 @@ pub trait FileProvider {
/// - If an error occurs while reading the file. /// - If an error occurs while reading the file.
/// - If the file does not exist. /// - If the file does not exist.
/// - If the file is not valid UTF-8. /// - If the file is not valid UTF-8.
fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> { fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
let bytes = self.read_bytes(path)?; let bytes = self.read_bytes(path)?;
let string = std::str::from_utf8(&bytes) let string = std::str::from_utf8(&bytes)
.map_err(|err| { .map_err(|err| {
@ -57,14 +57,14 @@ where
} }
impl FileProvider for FsProvider { impl FileProvider for FsProvider {
fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error> { fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error> {
let full_path = self.root.join(path); let full_path = self.root.join(path);
std::fs::read(full_path) std::fs::read(full_path)
.map(Cow::Owned) .map(Cow::Owned)
.map_err(Error::from) .map_err(Error::from)
} }
fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> { fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
let full_path = self.root.join(path); let full_path = self.root.join(path);
std::fs::read_to_string(full_path) std::fs::read_to_string(full_path)
.map(Cow::Owned) .map(Cow::Owned)
@ -178,7 +178,7 @@ mod vfs {
use shulkerbox::virtual_fs::{VFile, VFolder}; use shulkerbox::virtual_fs::{VFile, VFolder};
impl FileProvider for VFolder { impl FileProvider for VFolder {
fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error> { fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error> {
normalize_path_str(path).map_or_else( normalize_path_str(path).map_or_else(
|| Err(Error::from(std::io::ErrorKind::InvalidData)), || Err(Error::from(std::io::ErrorKind::InvalidData)),
|path| { |path| {
@ -189,7 +189,7 @@ mod vfs {
) )
} }
fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> { fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
normalize_path_str(path).map_or_else( normalize_path_str(path).map_or_else(
|| Err(Error::from(std::io::ErrorKind::InvalidData)), || Err(Error::from(std::io::ErrorKind::InvalidData)),
|path| { |path| {

View File

@ -69,7 +69,7 @@ impl SourceFile {
/// Get the [`SourceIterator`] for the source file. /// Get the [`SourceIterator`] for the source file.
#[must_use] #[must_use]
pub fn iter(self: &Arc<Self>) -> SourceIterator<'_> { pub fn iter<'a>(self: &'a Arc<Self>) -> SourceIterator<'a> {
SourceIterator { SourceIterator {
source_file: self, source_file: self,
iterator: self.content().char_indices().peekable(), iterator: self.content().char_indices().peekable(),

View File

@ -161,7 +161,7 @@ pub enum Token {
DocComment(DocComment), DocComment(DocComment),
CommandLiteral(CommandLiteral), CommandLiteral(CommandLiteral),
StringLiteral(StringLiteral), StringLiteral(StringLiteral),
MacroStringLiteral(Box<MacroStringLiteral>), MacroStringLiteral(MacroStringLiteral),
} }
impl SourceElement for Token { impl SourceElement for Token {
@ -325,7 +325,7 @@ pub struct StringLiteral {
impl StringLiteral { impl StringLiteral {
/// Returns the string content without escapement characters, leading and trailing double quotes. /// Returns the string content without escapement characters, leading and trailing double quotes.
#[must_use] #[must_use]
pub fn str_content(&self) -> Cow<'_, str> { pub fn str_content(&self) -> Cow<str> {
let string = self.span.str(); let string = self.span.str();
let string = &string[1..string.len() - 1]; let string = &string[1..string.len() - 1];
if string.contains('\\') { if string.contains('\\') {
@ -740,7 +740,7 @@ impl Token {
handler.receive(error::Error::from(UnterminatedDelimitedComment { handler.receive(error::Error::from(UnterminatedDelimitedComment {
span: Span::new(iter.source_file().clone(), start, start + 2).unwrap(), span: Span::new(iter.source_file().clone(), start, start + 2).unwrap(),
})); }));
Err(TokenizeError::FatalLexicalError) return Err(TokenizeError::FatalLexicalError);
} }
} }
// When there is no second slash and at the start of a line // When there is no second slash and at the start of a line
@ -883,14 +883,14 @@ impl Token {
} }
.into()) .into())
} else { } else {
Ok(Box::new(MacroStringLiteral { Ok(MacroStringLiteral {
starting_backtick, starting_backtick,
parts, parts,
ending_backtick: Punctuation { ending_backtick: Punctuation {
span: Self::create_span(start, iter), span: Self::create_span(start, iter),
punctuation: '`', punctuation: '`',
}, },
}) }
.into()) .into())
} }
} }

View File

@ -100,7 +100,7 @@ pub fn parse(
tracing::info!("Parsing the source code at path: {}", path.display()); tracing::info!("Parsing the source code at path: {}", path.display());
let mut parser = Parser::new(&tokens); let mut parser = Parser::new(&tokens);
let program = parser.parse_program(handler).map_err(Box::new)?; let program = parser.parse_program(handler)?;
if handler.has_received() { if handler.has_received() {
return Err(Error::other( return Err(Error::other(
@ -165,9 +165,8 @@ where
tracing::info!("Transpiling the source code."); tracing::info!("Transpiling the source code.");
let datapack = Transpiler::new(main_namespace_name, pack_format) let datapack =
.transpile(&programs, handler) Transpiler::new(main_namespace_name, pack_format).transpile(&programs, handler)?;
.map_err(Box::new)?;
if handler.has_received() { if handler.has_received() {
return Err(Error::other( return Err(Error::other(

View File

@ -48,7 +48,7 @@ pub enum Error {
/// An error that occurs when a function declaration is missing. /// An error that occurs when a function declaration is missing.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UnexpectedExpression(pub Box<Expression>); pub struct UnexpectedExpression(pub Expression);
impl Display for UnexpectedExpression { impl Display for UnexpectedExpression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View File

@ -70,7 +70,7 @@ fn get_global_scope(declarations: &[Declaration]) -> SemanticScope<'static> {
impl Namespace { impl Namespace {
/// Analyzes the semantics of the namespace. /// Analyzes the semantics of the namespace.
fn analyze_semantics(&self, handler: &impl Handler<base::Error>) -> Result<(), error::Error> { fn analyze_semantics(&self, handler: &impl Handler<base::Error>) -> Result<(), error::Error> {
let name = self.name(); let name = self.namespace_name();
Self::validate_str(name.str_content().as_ref()).map_err(|invalid_chars| { Self::validate_str(name.str_content().as_ref()).map_err(|invalid_chars| {
let err = error::Error::from(InvalidNamespaceName { let err = error::Error::from(InvalidNamespaceName {
name: name.clone(), name: name.clone(),
@ -393,22 +393,12 @@ impl Assignment {
if let Some(variable_type) = variable_type { if let Some(variable_type) = variable_type {
let expected = match variable_type { let expected = match variable_type {
VariableType::BooleanStorage => ValueType::Boolean, VariableType::BooleanStorage | VariableType::Tag => ValueType::Boolean,
VariableType::ScoreboardValue => ValueType::Integer, VariableType::ScoreboardValue => ValueType::Integer,
VariableType::ComptimeValue => { VariableType::ComptimeValue => {
// TODO: check if the expression is a constant expression // TODO: check if the expression is a constant expression
return Ok(()); return Ok(());
} }
VariableType::BooleanStorageArray | VariableType::Tag
if matches!(self.destination(), AssignmentDestination::Indexed(..)) =>
{
ValueType::Boolean
}
VariableType::Scoreboard | VariableType::ScoreboardArray
if matches!(self.destination(), AssignmentDestination::Indexed(..)) =>
{
ValueType::Integer
}
_ => { _ => {
let err = error::Error::AssignmentError(AssignmentError { let err = error::Error::AssignmentError(AssignmentError {
identifier: self.destination().span(), identifier: self.destination().span(),
@ -571,7 +561,7 @@ impl Primary {
VariableType::Function | VariableType::InternalFunction => Ok(()), VariableType::Function | VariableType::InternalFunction => Ok(()),
_ => { _ => {
let err = error::Error::UnexpectedExpression(UnexpectedExpression( let err = error::Error::UnexpectedExpression(UnexpectedExpression(
Box::new(Expression::Primary(self.clone())), Expression::Primary(self.clone()),
)); ));
handler.receive(err.clone()); handler.receive(err.clone());
Err(err) Err(err)
@ -716,14 +706,13 @@ impl Primary {
_ => false, _ => false,
}, },
Self::MemberAccess(_) => { Self::MemberAccess(_) => {
// TODO: correct return value after check // TODO:
true true
} }
Self::Identifier(ident) => match scope.get_variable(ident.span.str()) { Self::Identifier(ident) => match scope.get_variable(ident.span.str()) {
Some(VariableType::BooleanStorage) => expected == ValueType::Boolean, Some(VariableType::BooleanStorage) => expected == ValueType::Boolean,
Some(VariableType::ScoreboardValue) => expected == ValueType::Integer, Some(VariableType::ScoreboardValue) => expected == ValueType::Integer,
Some(VariableType::Tag) => expected == ValueType::String, Some(VariableType::Tag) => expected == ValueType::String,
Some(VariableType::ComptimeValue) => true,
_ => false, _ => false,
}, },
Self::Prefix(prefixed) => match prefixed.operator() { Self::Prefix(prefixed) => match prefixed.operator() {
@ -941,10 +930,9 @@ impl MacroStringLiteral {
MacroStringLiteralPart::MacroUsage { identifier, .. } => { MacroStringLiteralPart::MacroUsage { identifier, .. } => {
if let Some(variable_type) = scope.get_variable(identifier.span.str()) { if let Some(variable_type) = scope.get_variable(identifier.span.str()) {
if variable_type != VariableType::MacroParameter { if variable_type != VariableType::MacroParameter {
let err = let err = error::Error::UnexpectedExpression(UnexpectedExpression(
error::Error::UnexpectedExpression(UnexpectedExpression(Box::new(
Expression::Primary(Primary::Identifier(identifier.clone())), Expression::Primary(Primary::Identifier(identifier.clone())),
))); ));
handler.receive(err.clone()); handler.receive(err.clone());
errs.push(err); errs.push(err);
} }

View File

@ -80,7 +80,7 @@ impl<'a> Parser<'a> {
} }
}), }),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
@ -90,7 +90,7 @@ impl<'a> Parser<'a> {
expected: SyntaxKind::Punctuation(expected), expected: SyntaxKind::Punctuation(expected),
found: self.get_reading(None).into_token(), found: self.get_reading(None).into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
}; };
@ -129,7 +129,7 @@ impl<'a> Parser<'a> {
expected: SyntaxKind::Punctuation(expected), expected: SyntaxKind::Punctuation(expected),
found: self.peek().into_token(), found: self.peek().into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
@ -393,7 +393,7 @@ impl Frame<'_> {
expected: SyntaxKind::Identifier, expected: SyntaxKind::Identifier,
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -432,7 +432,7 @@ impl Frame<'_> {
expected: SyntaxKind::StringLiteral, expected: SyntaxKind::StringLiteral,
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -447,13 +447,13 @@ impl Frame<'_> {
handler: &impl Handler<base::Error>, handler: &impl Handler<base::Error>,
) -> ParseResult<MacroStringLiteral> { ) -> ParseResult<MacroStringLiteral> {
match self.next_significant_token() { match self.next_significant_token() {
Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(*literal), Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(literal),
found => { found => {
let err = Error::UnexpectedSyntax(UnexpectedSyntax { let err = Error::UnexpectedSyntax(UnexpectedSyntax {
expected: SyntaxKind::MacroStringLiteral, expected: SyntaxKind::MacroStringLiteral,
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -469,13 +469,13 @@ impl Frame<'_> {
) -> ParseResult<AnyStringLiteral> { ) -> ParseResult<AnyStringLiteral> {
match self.next_significant_token() { match self.next_significant_token() {
Reading::Atomic(Token::StringLiteral(literal)) => Ok(literal.into()), Reading::Atomic(Token::StringLiteral(literal)) => Ok(literal.into()),
Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok((*literal).into()), Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(literal.into()),
found => { found => {
let err = Error::UnexpectedSyntax(UnexpectedSyntax { let err = Error::UnexpectedSyntax(UnexpectedSyntax {
expected: SyntaxKind::AnyStringLiteral, expected: SyntaxKind::AnyStringLiteral,
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -499,7 +499,7 @@ impl Frame<'_> {
expected: SyntaxKind::Keyword(expected), expected: SyntaxKind::Keyword(expected),
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -530,7 +530,7 @@ impl Frame<'_> {
expected: SyntaxKind::Punctuation(expected), expected: SyntaxKind::Punctuation(expected),
found: found.into_token(), found: found.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -1,7 +1,6 @@
//! Syntax tree nodes for declarations. //! Syntax tree nodes for declarations.
#![expect(missing_docs)] #![allow(missing_docs)]
#![expect(clippy::struct_field_names)]
use std::collections::VecDeque; use std::collections::VecDeque;
@ -392,7 +391,7 @@ impl Parser<'_> {
declaration declaration
.with_annotation(annotation) .with_annotation(annotation)
.inspect_err(|err| handler.receive(Box::new(err.clone()))) .inspect_err(|err| handler.receive(err.clone()))
} }
Reading::Atomic(Token::Keyword(from_keyword)) Reading::Atomic(Token::Keyword(from_keyword))
@ -442,7 +441,7 @@ impl Parser<'_> {
expected: SyntaxKind::Punctuation('*'), expected: SyntaxKind::Punctuation('*'),
found: self.stop_at_significant().into_token(), found: self.stop_at_significant().into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
@ -512,7 +511,7 @@ impl Parser<'_> {
expected: SyntaxKind::Declaration, expected: SyntaxKind::Declaration,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
@ -563,7 +562,7 @@ impl Parser<'_> {
expected: SyntaxKind::Keyword(KeywordKind::Function), expected: SyntaxKind::Keyword(KeywordKind::Function),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -616,7 +615,7 @@ impl Parser<'_> {
]), ]),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -666,7 +666,7 @@ impl Parser<'_> {
// eat the macro string literal // eat the macro string literal
self.forward(); self.forward();
Ok(Primary::MacroStringLiteral(*macro_string_literal)) Ok(Primary::MacroStringLiteral(macro_string_literal))
} }
// lua code expression // lua code expression
@ -687,7 +687,7 @@ impl Parser<'_> {
expected: syntax::error::SyntaxKind::Identifier, expected: syntax::error::SyntaxKind::Identifier,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -741,7 +741,7 @@ impl Parser<'_> {
expected: syntax::error::SyntaxKind::Expression, expected: syntax::error::SyntaxKind::Expression,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
@ -829,7 +829,7 @@ impl Parser<'_> {
expected: syntax::error::SyntaxKind::Operator, expected: syntax::error::SyntaxKind::Operator,
found: Some(Token::Punctuation(punc)), found: Some(Token::Punctuation(punc)),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -838,7 +838,7 @@ impl Parser<'_> {
expected: syntax::error::SyntaxKind::Operator, expected: syntax::error::SyntaxKind::Operator,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -388,7 +388,7 @@ impl Parser<'_> {
expected: SyntaxKind::Punctuation('#'), expected: SyntaxKind::Punctuation('#'),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -52,10 +52,10 @@ pub struct ProgramFile {
pub struct Namespace { pub struct Namespace {
/// The `namespace` keyword. /// The `namespace` keyword.
#[get = "pub"] #[get = "pub"]
keyword: Keyword, namespace_keyword: Keyword,
/// The name of the namespace. /// The name of the namespace.
#[get = "pub"] #[get = "pub"]
name: StringLiteral, namespace_name: StringLiteral,
/// The semicolon. /// The semicolon.
#[get = "pub"] #[get = "pub"]
semicolon: Punctuation, semicolon: Punctuation,
@ -63,7 +63,7 @@ pub struct Namespace {
impl SourceElement for Namespace { impl SourceElement for Namespace {
fn span(&self) -> Span { fn span(&self) -> Span {
self.keyword self.namespace_keyword
.span() .span()
.join(&self.semicolon.span()) .join(&self.semicolon.span())
.expect("Invalid span") .expect("Invalid span")
@ -74,7 +74,7 @@ impl Namespace {
/// Dissolves the namespace into its components. /// Dissolves the namespace into its components.
#[must_use] #[must_use]
pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) { pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) {
(self.keyword, self.name, self.semicolon) (self.namespace_keyword, self.namespace_name, self.semicolon)
} }
/// Validates a namespace string. /// Validates a namespace string.
@ -112,19 +112,19 @@ impl Parser<'_> {
tracing::debug!("Parsing program"); tracing::debug!("Parsing program");
let namespace = match self.stop_at_significant() { let namespace = match self.stop_at_significant() {
Reading::Atomic(Token::Keyword(keyword)) Reading::Atomic(Token::Keyword(namespace_keyword))
if keyword.keyword == KeywordKind::Namespace => if namespace_keyword.keyword == KeywordKind::Namespace =>
{ {
// eat the keyword // eat the keyword
self.forward(); self.forward();
let name = self.parse_string_literal(handler)?; let namespace_name = self.parse_string_literal(handler)?;
let semicolon = self.parse_punctuation(';', true, handler)?; let semicolon = self.parse_punctuation(';', true, handler)?;
Ok(Namespace { Ok(Namespace {
keyword, namespace_keyword,
name, namespace_name,
semicolon, semicolon,
}) })
} }
@ -133,14 +133,14 @@ impl Parser<'_> {
expected: SyntaxKind::Keyword(KeywordKind::Namespace), expected: SyntaxKind::Keyword(KeywordKind::Namespace),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
tracing::debug!( tracing::debug!(
"Found namespace '{}', parsing declarations", "Found namespace '{}', parsing declarations",
namespace.name.str_content() namespace.namespace_name.str_content()
); );
let mut declarations = Vec::new(); let mut declarations = Vec::new();

View File

@ -493,7 +493,7 @@ impl SingleVariableDeclaration {
/// ///
/// ```ebnf /// ```ebnf
/// ArrayVariableDeclaration: /// ArrayVariableDeclaration:
/// ('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment? /// ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -501,6 +501,9 @@ pub struct ArrayVariableDeclaration {
/// The type of the variable. /// The type of the variable.
#[get = "pub"] #[get = "pub"]
variable_type: Keyword, variable_type: Keyword,
/// The identifier of the variable.
#[get = "pub"]
identifier: Identifier,
/// The opening bracket of the array. /// The opening bracket of the array.
#[get = "pub"] #[get = "pub"]
open_bracket: Punctuation, open_bracket: Punctuation,
@ -510,9 +513,6 @@ pub struct ArrayVariableDeclaration {
/// The closing bracket of the array. /// The closing bracket of the array.
#[get = "pub"] #[get = "pub"]
close_bracket: Punctuation, close_bracket: Punctuation,
/// The identifier of the variable.
#[get = "pub"]
identifier: Identifier,
/// The optional assignment of the variable. /// The optional assignment of the variable.
#[get = "pub"] #[get = "pub"]
assignment: Option<VariableDeclarationAssignment>, assignment: Option<VariableDeclarationAssignment>,
@ -798,7 +798,7 @@ pub enum AssignmentDestination {
/// Assignment to an identifier. /// Assignment to an identifier.
Identifier(Identifier), Identifier(Identifier),
/// Assignment to an indexed identifier. /// Assignment to an indexed identifier.
Indexed(Identifier, Punctuation, Box<Expression>, Punctuation), Indexed(Identifier, Punctuation, Expression, Punctuation),
} }
impl SourceElement for AssignmentDestination { impl SourceElement for AssignmentDestination {
@ -872,7 +872,7 @@ impl Parser<'_> {
statement statement
.with_annotation(annotation) .with_annotation(annotation)
.inspect_err(|err| handler.receive(Box::new(err.clone()))) .inspect_err(|err| handler.receive(err.clone()))
} }
// variable declaration // variable declaration
Reading::Atomic(Token::CommandLiteral(command)) => { Reading::Atomic(Token::CommandLiteral(command)) => {
@ -971,12 +971,7 @@ impl Parser<'_> {
let close = tree.close; let close = tree.close;
let expression = tree.tree?; let expression = tree.tree?;
AssignmentDestination::Indexed( AssignmentDestination::Indexed(identifier, open, expression, close)
identifier,
open,
Box::new(expression),
close,
)
} }
_ => AssignmentDestination::Identifier(identifier), _ => AssignmentDestination::Identifier(identifier),
} }
@ -1041,7 +1036,7 @@ impl Parser<'_> {
]), ]),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
}; };
@ -1058,7 +1053,11 @@ impl Parser<'_> {
None None
}; };
let index = match self.stop_at_significant() { // read identifier
self.stop_at_significant();
let identifier = self.parse_identifier(handler)?;
match self.stop_at_significant() {
Reading::IntoDelimited(punc) Reading::IntoDelimited(punc)
if punc.punctuation == '[' if punc.punctuation == '['
&& matches!(variable_type.keyword, KeywordKind::Int | KeywordKind::Bool) => && matches!(variable_type.keyword, KeywordKind::Int | KeywordKind::Bool) =>
@ -1081,7 +1080,7 @@ impl Parser<'_> {
expected: SyntaxKind::Integer, expected: SyntaxKind::Integer,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
}; };
@ -1095,18 +1094,10 @@ impl Parser<'_> {
let close_bracket = tree.close; let close_bracket = tree.close;
let inner = tree.tree?; let inner = tree.tree?;
Some((open_bracket, inner, close_bracket)) match inner {
} IndexingType::IntegerSize(size) => {
_ => None, let assignment = self
}; .try_parse(|p| {
// read identifier
self.stop_at_significant();
let identifier = self.parse_identifier(handler)?;
// TODO: allow assignment when map and array literals have been implemented
let assignment = if index.is_none() {
self.try_parse(|p| {
// read equals sign // read equals sign
let equals = p.parse_punctuation('=', true, &VoidHandler)?; let equals = p.parse_punctuation('=', true, &VoidHandler)?;
@ -1115,13 +1106,8 @@ impl Parser<'_> {
Ok(VariableDeclarationAssignment { equals, expression }) Ok(VariableDeclarationAssignment { equals, expression })
}) })
.ok() .ok();
} else {
None
};
match index {
Some((open_bracket, IndexingType::IntegerSize(size), close_bracket)) => {
Ok(VariableDeclaration::Array(ArrayVariableDeclaration { Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
variable_type, variable_type,
identifier, identifier,
@ -1132,9 +1118,9 @@ impl Parser<'_> {
annotations: VecDeque::new(), annotations: VecDeque::new(),
})) }))
} }
Some((open_bracket, IndexingType::None, close_bracket)) => { IndexingType::None => match variable_type.keyword {
match variable_type.keyword { KeywordKind::Int => {
KeywordKind::Int => Ok(VariableDeclaration::Score(ScoreVariableDeclaration { Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
int_keyword: variable_type, int_keyword: variable_type,
criteria: criteria_selection, criteria: criteria_selection,
identifier, identifier,
@ -1142,7 +1128,8 @@ impl Parser<'_> {
close_bracket, close_bracket,
assignment: None, assignment: None,
annotations: VecDeque::new(), annotations: VecDeque::new(),
})), }))
}
KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration { KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
bool_keyword: variable_type, bool_keyword: variable_type,
identifier, identifier,
@ -1152,15 +1139,22 @@ impl Parser<'_> {
annotations: VecDeque::new(), annotations: VecDeque::new(),
})), })),
_ => unreachable!(), _ => unreachable!(),
},
} }
} }
None => { // SingleVariableDeclaration with Assignment
if matches!(variable_type.keyword, KeywordKind::Val) { Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '=' => {
self.forward();
let equals = punc;
let expression = self.parse_expression(handler)?;
let assignment = VariableDeclarationAssignment { equals, expression };
if variable_type.keyword == KeywordKind::Val {
Ok(VariableDeclaration::ComptimeValue( Ok(VariableDeclaration::ComptimeValue(
ComptimeValueDeclaration { ComptimeValueDeclaration {
val_keyword: variable_type, val_keyword: variable_type,
identifier, identifier,
assignment, assignment: Some(assignment),
annotations: VecDeque::new(), annotations: VecDeque::new(),
}, },
)) ))
@ -1168,11 +1162,18 @@ impl Parser<'_> {
Ok(VariableDeclaration::Single(SingleVariableDeclaration { Ok(VariableDeclaration::Single(SingleVariableDeclaration {
variable_type, variable_type,
identifier, identifier,
assignment, assignment: Some(assignment),
annotations: VecDeque::new(), annotations: VecDeque::new(),
})) }))
} }
} }
// SingleVariableDeclaration without Assignment
_ => Ok(VariableDeclaration::Single(SingleVariableDeclaration {
variable_type,
identifier,
assignment: None,
annotations: VecDeque::new(),
})),
} }
} }
} }

View File

@ -1,7 +1,5 @@
//! Execute block statement syntax tree. //! Execute block statement syntax tree.
#![expect(clippy::struct_field_names)]
use derive_more::From; use derive_more::From;
use enum_as_inner::EnumAsInner; use enum_as_inner::EnumAsInner;
use getset::Getters; use getset::Getters;
@ -826,7 +824,7 @@ impl Parser<'_> {
expected: SyntaxKind::Punctuation('('), expected: SyntaxKind::Punctuation('('),
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
@ -844,7 +842,7 @@ impl Parser<'_> {
expected: SyntaxKind::ExecuteBlock, expected: SyntaxKind::ExecuteBlock,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -880,7 +878,7 @@ impl Parser<'_> {
expected: SyntaxKind::ExecuteBlockTail, expected: SyntaxKind::ExecuteBlockTail,
found: unexpected.into_token(), found: unexpected.into_token(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -104,8 +104,6 @@ impl MissingFunctionDeclaration {
impl Display for MissingFunctionDeclaration { impl Display for MissingFunctionDeclaration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use std::fmt::Write as _;
let message = format!( let message = format!(
"no matching function declaration found for invocation of function `{}`", "no matching function declaration found for invocation of function `{}`",
self.span.str() self.span.str()
@ -120,7 +118,7 @@ impl Display for MissingFunctionDeclaration {
if i > 0 { if i > 0 {
message.push_str(", "); message.push_str(", ");
} }
let _ = write!(message, "`{}`", alternative.identifier_span.str()); message.push_str(&format!("`{}`", alternative.identifier_span.str()));
} }
Some(message + "?") Some(message + "?")
}; };
@ -400,11 +398,6 @@ pub enum IllegalIndexingReason {
/// The length indexed object. /// The length indexed object.
length: usize, length: usize,
}, },
/// The index provided is invalid
InvalidIndex {
/// The invalid index
index: Span,
},
} }
impl Display for IllegalIndexingReason { impl Display for IllegalIndexingReason {
@ -428,9 +421,6 @@ impl Display for IllegalIndexingReason {
"The index {index} is out of bounds for the expression with length {length}." "The index {index} is out of bounds for the expression with length {length}."
) )
} }
Self::InvalidIndex { index } => {
write!(f, "The index {index} is invalid.", index = index.str())
}
} }
} }
} }

View File

@ -405,7 +405,7 @@ impl Primary {
Self::Lua(lua) => lua Self::Lua(lua) => lua
.eval_comptime(scope, &VoidHandler) .eval_comptime(scope, &VoidHandler)
.inspect_err(|err| { .inspect_err(|err| {
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
}) })
.map_err(|_| NotComptime { .map_err(|_| NotComptime {
expression: lua.span(), expression: lua.span(),
@ -1191,7 +1191,7 @@ impl Transpiler {
.into(), .into(),
}, },
); );
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} else { } else {
let prepare_cmd = Command::Raw(format!("tag {entity} remove {tag_name}")); let prepare_cmd = Command::Raw(format!("tag {entity} remove {tag_name}"));
@ -1225,18 +1225,7 @@ impl Transpiler {
.parent() .parent()
.comptime_member_access(member_access, scope, handler) .comptime_member_access(member_access, scope, handler)
.map_or_else( .map_or_else(
|_| { |_| todo!("implement non-comptime member access"),
// TODO: implement non-comptime access
let err = TranspileError::IllegalIndexing(IllegalIndexing {
expression: member_access.member().span(),
reason: IllegalIndexingReason::InvalidIndex {
index: member_access.member().span(),
},
});
handler.receive(Box::new(err.clone()));
Err(err)
},
|value| self.store_comptime_value(&value, target, member_access, handler), |value| self.store_comptime_value(&value, target, member_access, handler),
), ),
Primary::Lua(lua) => Primary::Lua(lua) =>
@ -1248,7 +1237,7 @@ impl Transpiler {
let err = TranspileError::MissingValue(MissingValue { let err = TranspileError::MissingValue(MissingValue {
expression: lua.span(), expression: lua.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1273,7 +1262,7 @@ impl Transpiler {
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1337,7 +1326,7 @@ impl Transpiler {
expression: prefix.span(), expression: prefix.span(),
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -1433,7 +1422,7 @@ impl Transpiler {
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
@ -1443,7 +1432,7 @@ impl Transpiler {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1455,7 +1444,7 @@ impl Transpiler {
reason: IllegalIndexingReason::NotIdentifier, reason: IllegalIndexingReason::NotIdentifier,
expression: indexed.object().span(), expression: indexed.object().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
}?; }?;
let variable = scope.get_variable(ident.span.str()); let variable = scope.get_variable(ident.span.str());
@ -1477,7 +1466,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1502,7 +1491,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} else { } else {
@ -1512,7 +1501,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1541,7 +1530,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} else { } else {
@ -1551,7 +1540,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1560,7 +1549,7 @@ impl Transpiler {
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
@ -1570,7 +1559,7 @@ impl Transpiler {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1647,7 +1636,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
Primary::StringLiteral(s) => Ok(( Primary::StringLiteral(s) => Ok((
@ -1670,7 +1659,7 @@ impl Transpiler {
message: "Function calls as conditions do not support arguments." message: "Function calls as conditions do not support arguments."
.into(), .into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} else { } else {
let (func_location, _) = self.get_or_transpile_function( let (func_location, _) = self.get_or_transpile_function(
@ -1713,7 +1702,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1721,7 +1710,7 @@ impl Transpiler {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1736,7 +1725,7 @@ impl Transpiler {
reason: IllegalIndexingReason::NotIdentifier, reason: IllegalIndexingReason::NotIdentifier,
expression: indexed.object().span(), expression: indexed.object().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
}?; }?;
#[expect(clippy::option_if_let_else)] #[expect(clippy::option_if_let_else)]
@ -1770,7 +1759,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} else { } else {
@ -1780,7 +1769,7 @@ impl Transpiler {
}, },
expression: indexed.index().span(), expression: indexed.index().span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1789,7 +1778,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1797,7 +1786,7 @@ impl Transpiler {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1805,18 +1794,7 @@ impl Transpiler {
.parent() .parent()
.comptime_member_access(member_access, scope, handler) .comptime_member_access(member_access, scope, handler)
.map_or_else( .map_or_else(
|_| { |_| todo!("implement non-comptime member access"),
// TODO: implement non-comptime access
let err = TranspileError::IllegalIndexing(IllegalIndexing {
expression: member_access.member().span(),
reason: IllegalIndexingReason::InvalidIndex {
index: member_access.member().span(),
},
});
handler.receive(Box::new(err.clone()));
Err(err)
},
|value| match value { |value| match value {
ComptimeValue::Boolean(b) => { ComptimeValue::Boolean(b) => {
Ok((Vec::new(), ExtendedCondition::Comptime(b))) Ok((Vec::new(), ExtendedCondition::Comptime(b)))
@ -1826,7 +1804,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
ComptimeValue::String(s) => Ok(( ComptimeValue::String(s) => Ok((
@ -1882,7 +1860,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -1903,7 +1881,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: primary.span(), expression: primary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -1933,7 +1911,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: binary.span(), expression: binary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -2022,7 +2000,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: binary.span(), expression: binary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
DataLocation::Storage { DataLocation::Storage {
@ -2049,7 +2027,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: binary.span(), expression: binary.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
}, },
@ -2195,7 +2173,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: source.span(), expression: source.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
DataLocation::Storage { DataLocation::Storage {
@ -2219,7 +2197,7 @@ impl Transpiler {
expression: source.span(), expression: source.span(),
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -2245,7 +2223,7 @@ impl Transpiler {
expression: source.span(), expression: source.span(),
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -2280,7 +2258,7 @@ impl Transpiler {
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
expression: source.span(), expression: source.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -2316,7 +2294,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: source.span(), expression: source.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
} }

View File

@ -32,7 +32,7 @@ use super::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum TranspiledFunctionArguments { pub enum TranspiledFunctionArguments {
None, None,
Static(BTreeMap<String, MacroString>, Vec<Command>), Static(BTreeMap<String, MacroString>),
Dynamic(Vec<Command>), Dynamic(Vec<Command>),
} }
@ -59,11 +59,11 @@ impl Transpiler {
.expect("called variable should be of type function"); .expect("called variable should be of type function");
let function_data = function.ok_or_else(|| { let function_data = function.ok_or_else(|| {
let err = TranspileError::MissingFunctionDeclaration( let error = TranspileError::MissingFunctionDeclaration(
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope), MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
); );
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
err error
})?; })?;
let VariableData::Function { let VariableData::Function {
@ -99,7 +99,7 @@ impl Transpiler {
.to_string(), .to_string(),
}, },
); );
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
err err
}), }),
TranspileAnnotationValue::Map(_, span) => { TranspileAnnotationValue::Map(_, span) => {
@ -108,7 +108,7 @@ impl Transpiler {
annotation: span.clone(), annotation: span.clone(),
message: "Deobfuscate annotation cannot be a map.".to_string(), message: "Deobfuscate annotation cannot be a map.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -175,7 +175,7 @@ impl Transpiler {
name: modified_name, name: modified_name,
definition: identifier_span.clone(), definition: identifier_span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
@ -193,11 +193,11 @@ impl Transpiler {
let function_location = function_path let function_location = function_path
.get() .get()
.ok_or_else(|| { .ok_or_else(|| {
let err = TranspileError::MissingFunctionDeclaration( let error = TranspileError::MissingFunctionDeclaration(
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope), MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
); );
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
err error
}) })
.map(String::to_owned)?; .map(String::to_owned)?;
@ -258,7 +258,7 @@ impl Transpiler {
actual: arg_count, actual: arg_count,
span: identifier_span.clone(), span: identifier_span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
Some(arg_count) if arg_count > 0 => { Some(arg_count) if arg_count > 0 => {
@ -283,7 +283,7 @@ impl Transpiler {
Ok(val) => Ok(Parameter::Static(val.to_macro_string())), Ok(val) => Ok(Parameter::Static(val.to_macro_string())),
Err(err) => { Err(err) => {
let err = TranspileError::NotComptime(err); let err = TranspileError::NotComptime(err);
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}) })
@ -305,7 +305,7 @@ impl Transpiler {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span(), identifier: ident.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
err err
})?; })?;
match var.as_ref() { match var.as_ref() {
@ -353,7 +353,7 @@ impl Transpiler {
ExpectedType::String, ExpectedType::String,
]), ]),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -430,9 +430,9 @@ impl Transpiler {
} }
if compiled_args.iter().any(|arg| !arg.is_static()) { if compiled_args.iter().any(|arg| !arg.is_static()) {
let (require_dyn_params, mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold( let (mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
(false, Vec::new(), Vec::new(), BTreeMap::new()), (Vec::new(), Vec::new(), BTreeMap::new()),
|(mut require_dyn_params, mut acc_setup, mut acc_move, mut statics), (param, data)| { |(mut acc_setup, mut acc_move, mut statics), (param, data)| {
match param.variable_type() { match param.variable_type() {
FunctionVariableType::Macro(_) => { FunctionVariableType::Macro(_) => {
let arg_name = crate::util::identifier_to_macro(param.identifier().span.str()); let arg_name = crate::util::identifier_to_macro(param.identifier().span.str());
@ -455,7 +455,6 @@ impl Transpiler {
}; };
} }
Parameter::Storage { prepare_cmds, storage_name, path } => { Parameter::Storage { prepare_cmds, storage_name, path } => {
require_dyn_params = true;
acc_setup.extend(prepare_cmds); acc_setup.extend(prepare_cmds);
acc_move.push(Command::Raw( acc_move.push(Command::Raw(
format!(r"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}") format!(r"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}")
@ -496,7 +495,6 @@ impl Transpiler {
} }
}, },
FunctionVariableType::Boolean(_) => { FunctionVariableType::Boolean(_) => {
require_dyn_params = true;
let target_storage_name = format!("shulkerscript:arguments_{}", function_location.replace(['/', ':'], "_")); let target_storage_name = format!("shulkerscript:arguments_{}", function_location.replace(['/', ':'], "_"));
let param_str = param.identifier().span.str(); let param_str = param.identifier().span.str();
let target_path = crate::util::identifier_to_scoreboard_target(param_str); let target_path = crate::util::identifier_to_scoreboard_target(param_str);
@ -526,15 +524,12 @@ impl Transpiler {
} }
}, },
} }
(require_dyn_params, acc_setup, acc_move, statics)}, (acc_setup, acc_move, statics)},
); );
if require_dyn_params {
let statics_len = static_params.len(); let statics_len = static_params.len();
let joined_statics = super::util::join_macro_strings( let joined_statics =
static_params super::util::join_macro_strings(static_params.into_iter().enumerate().map(
.into_iter() |(i, (k, v))| match v {
.enumerate()
.map(|(i, (k, v))| match v {
MacroString::String(s) => { MacroString::String(s) => {
let mut s = format!(r#"{k}:"{s}""#); let mut s = format!(r#"{k}:"{s}""#);
if i < statics_len - 1 { if i < statics_len - 1 {
@ -543,10 +538,7 @@ impl Transpiler {
MacroString::String(s) MacroString::String(s)
} }
MacroString::MacroString(mut parts) => { MacroString::MacroString(mut parts) => {
parts.insert( parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#)));
0,
MacroStringPart::String(format!(r#"{k}:""#)),
);
let mut ending = '"'.to_string(); let mut ending = '"'.to_string();
if i < statics_len - 1 { if i < statics_len - 1 {
ending.push(','); ending.push(',');
@ -554,39 +546,28 @@ impl Transpiler {
parts.push(MacroStringPart::String(ending)); parts.push(MacroStringPart::String(ending));
MacroString::MacroString(parts) MacroString::MacroString(parts)
} }
}), },
); ));
let storage_suffix = function_location.replace(['/', ':'], "_");
let statics_cmd = match joined_statics { let statics_cmd = match joined_statics {
MacroString::String(s) => Command::Raw(format!( MacroString::String(s) => Command::Raw(format!(
r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}" r"data merge storage shulkerscript:function_arguments {{{s}}}"
)), )),
MacroString::MacroString(_) => { MacroString::MacroString(_) => Command::UsesMacro(
let prefix = MacroString::String(
format!("data merge storage shulkerscript:function_arguments_{storage_suffix} {{"),
);
Command::UsesMacro(
super::util::join_macro_strings([ super::util::join_macro_strings([
prefix, MacroString::String(
"data merge storage shulkerscript:function_arguments {"
.to_string(),
),
joined_statics, joined_statics,
MacroString::String("}".to_string()), MacroString::String("}".to_string()),
]) ])
.into(), .into(),
) ),
}
}; };
setup_cmds.push(statics_cmd); setup_cmds.push(statics_cmd);
setup_cmds.extend(move_cmds); setup_cmds.extend(move_cmds);
Ok(TranspiledFunctionArguments::Dynamic(setup_cmds)) Ok(TranspiledFunctionArguments::Dynamic(setup_cmds))
} else {
setup_cmds.extend(move_cmds);
Ok(TranspiledFunctionArguments::Static(
static_params,
setup_cmds,
))
}
} else { } else {
let function_args = parameters let function_args = parameters
.clone() .clone()
@ -598,10 +579,7 @@ impl Transpiler {
) )
.map(|(k, v)| (k.identifier().span.str().to_string(), v)) .map(|(k, v)| (k.identifier().span.str().to_string(), v))
.collect(); .collect();
Ok(TranspiledFunctionArguments::Static( Ok(TranspiledFunctionArguments::Static(function_args))
function_args,
Vec::new(),
))
} }
} }
_ => Ok(TranspiledFunctionArguments::None), _ => Ok(TranspiledFunctionArguments::None),

View File

@ -132,7 +132,7 @@ fn print_function(
Ok((false, cmd, value)) Ok((false, cmd, value))
} }
_ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression( _ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression(
Box::new(Expression::Primary(Primary::Identifier(ident.to_owned()))), Expression::Primary(Primary::Identifier(ident.to_owned())),
))), ))),
} }
} else { } else {

View File

@ -58,7 +58,7 @@ mod enabled {
}; };
self.add_globals(&lua, scope) self.add_globals(&lua, scope)
.inspect_err(|err| handler.receive(Box::new(err.clone())))?; .inspect_err(|err| handler.receive(err.clone()))?;
let res = lua let res = lua
.load(self.code()) .load(self.code())
@ -67,7 +67,7 @@ mod enabled {
.map_err(|err| { .map_err(|err| {
let err = let err =
TranspileError::from(LuaRuntimeError::from_lua_err(&err, self.span())); TranspileError::from(LuaRuntimeError::from_lua_err(&err, self.span()));
handler.receive(crate::Error::from(Box::new(err.clone()))); handler.receive(crate::Error::from(err.clone()));
err err
}); });
@ -329,7 +329,7 @@ mod enabled {
code_block: self.span(), code_block: self.span(),
error_message: "return table must contain non-nil 'value'".to_string(), error_message: "return table must contain non-nil 'value'".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
Ok(value) => { Ok(value) => {
@ -348,7 +348,7 @@ mod enabled {
expression: self.span(), expression: self.span(),
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -358,7 +358,7 @@ mod enabled {
expression: self.span(), expression: self.span(),
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
@ -380,7 +380,7 @@ mod enabled {
&err, &err,
self.span(), self.span(),
)); ));
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -393,7 +393,7 @@ mod enabled {
code_block: self.span(), code_block: self.span(),
error_message: format!("invalid return type {}", value.type_name()), error_message: format!("invalid return type {}", value.type_name()),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -196,12 +196,13 @@ impl Transpiler {
} }
TranspileAnnotationValue::Expression(_, span) TranspileAnnotationValue::Expression(_, span)
| TranspileAnnotationValue::Map(_, span) => { | TranspileAnnotationValue::Map(_, span) => {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: span.clone(), annotation: span.clone(),
message: "uninstall annotation must not have a value".to_string(), message: "uninstall annotation must not have a value".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
}) })
.collect::<TranspileResult<Vec<_>>>()?; .collect::<TranspileResult<Vec<_>>>()?;
@ -272,7 +273,7 @@ impl Transpiler {
}) })
.collect(); .collect();
let function_data = FunctionData { let function_data = FunctionData {
namespace: namespace.name().str_content().to_string(), namespace: namespace.namespace_name().str_content().to_string(),
identifier_span: identifier_span.clone(), identifier_span: identifier_span.clone(),
parameters: function parameters: function
.parameters() .parameters()
@ -317,7 +318,9 @@ impl Transpiler {
} }
} }
Declaration::Tag(tag) => { Declaration::Tag(tag) => {
let namespace = self.datapack.namespace_mut(namespace.name().str_content()); let namespace = self
.datapack
.namespace_mut(namespace.namespace_name().str_content());
let sb_tag = namespace.tag_mut(tag.name().str_content(), tag.tag_type()); let sb_tag = namespace.tag_mut(tag.name().str_content(), tag.tag_type());
if let Some(list) = &tag.entries().list { if let Some(list) = &tag.entries().list {
@ -341,7 +344,7 @@ impl Transpiler {
self.setup_cmds.extend(setup_variable_cmds); self.setup_cmds.extend(setup_variable_cmds);
} }
} };
Ok(()) Ok(())
} }
@ -412,11 +415,11 @@ impl Transpiler {
self.transpile_run_expression(prefix.operand(), scope, handler) self.transpile_run_expression(prefix.operand(), scope, handler)
} }
unexpected => { unexpected => {
let err = TranspileError::UnexpectedExpression(UnexpectedExpression( let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
Box::new(unexpected.clone()), unexpected.clone(),
)); ));
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
}, },
SemicolonStatement::VariableDeclaration(decl) => self SemicolonStatement::VariableDeclaration(decl) => self
@ -492,11 +495,11 @@ impl Transpiler {
read_only: _, read_only: _,
} => value.read().unwrap().as_ref().map_or_else( } => value.read().unwrap().as_ref().map_or_else(
|| { || {
let err = TranspileError::MissingValue(MissingValue { let error = TranspileError::MissingValue(MissingValue {
expression: ident.span.clone(), expression: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
}, },
|val| { |val| {
let cmd = val.to_string_no_macro().map_or_else( let cmd = val.to_string_no_macro().map_or_else(
@ -529,21 +532,20 @@ impl Transpiler {
)))), )))),
), ),
_ => { _ => {
let err = TranspileError::UnexpectedExpression( let error =
UnexpectedExpression(Box::new(Expression::Primary( TranspileError::UnexpectedExpression(UnexpectedExpression(
Primary::Identifier(ident.clone()), Expression::Primary(Primary::Identifier(ident.clone())),
))), ));
); handler.receive(error.clone());
handler.receive(Box::new(err.clone())); return Err(error);
return Err(err);
} }
} }
} else { } else {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
} }
_ => { _ => {
@ -588,11 +590,11 @@ impl Transpiler {
read_only: _, read_only: _,
}) => value.read().unwrap().as_ref().map_or_else( }) => value.read().unwrap().as_ref().map_or_else(
|| { || {
let err = TranspileError::MissingValue(MissingValue { let error = TranspileError::MissingValue(MissingValue {
expression: ident.span.clone(), expression: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
}, },
|val| { |val| {
let cmd = val.to_string_no_macro().map_or_else( let cmd = val.to_string_no_macro().map_or_else(
@ -603,18 +605,18 @@ impl Transpiler {
}, },
), ),
Some(_) => { Some(_) => {
let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new( let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
Expression::Primary(expression.clone()), Expression::Primary(expression.clone()),
))); ));
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
None => { None => {
let err = TranspileError::UnknownIdentifier(UnknownIdentifier { let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
identifier: ident.span.clone(), identifier: ident.span.clone(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
}, },
@ -623,11 +625,11 @@ impl Transpiler {
| Primary::Prefix(_) | Primary::Prefix(_)
| Primary::Indexed(_) | Primary::Indexed(_)
| Primary::MemberAccess(_) => { | Primary::MemberAccess(_) => {
let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new( let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
Expression::Primary(expression.clone()), Expression::Primary(expression.clone()),
))); ));
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
Primary::StringLiteral(string) => { Primary::StringLiteral(string) => {
Ok(vec![Command::Raw(string.str_content().to_string())]) Ok(vec![Command::Raw(string.str_content().to_string())])
@ -641,14 +643,14 @@ impl Transpiler {
expected_type: ExpectedType::String, expected_type: ExpectedType::String,
expression: code.span(), expression: code.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
Err(_) => { Err(_) => {
let err = TranspileError::MissingValue(MissingValue { let err = TranspileError::MissingValue(MissingValue {
expression: code.span(), expression: code.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -665,12 +667,12 @@ impl Transpiler {
expression: bin.span(), expression: bin.span(),
expected_type: ExpectedType::String, expected_type: ExpectedType::String,
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
Err(not_comptime) => { Err(not_comptime) => {
let err = TranspileError::NotComptime(not_comptime); let err = TranspileError::NotComptime(not_comptime);
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -692,7 +694,7 @@ impl Transpiler {
scope.get_variable(func.identifier().span.str()).as_deref() scope.get_variable(func.identifier().span.str()).as_deref()
{ {
implementation(self, scope, func).inspect_err(|err| { implementation(self, scope, func).inspect_err(|err| {
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
}) })
} else { } else {
let (location, arguments) = self.get_or_transpile_function( let (location, arguments) = self.get_or_transpile_function(
@ -703,12 +705,8 @@ impl Transpiler {
)?; )?;
let mut function_call = format!("function {location}"); let mut function_call = format!("function {location}");
match arguments { match arguments {
TranspiledFunctionArguments::Static(arguments, mut setup_cmds) => { TranspiledFunctionArguments::Static(arguments) => {
use std::fmt::Write; use std::fmt::Write;
let cmd = if arguments.is_empty() {
Command::Raw(function_call)
} else {
let arguments_iter = arguments.iter().map(|(ident, v)| match v { let arguments_iter = arguments.iter().map(|(ident, v)| match v {
MacroString::String(s) => MacroString::String(format!( MacroString::String(s) => MacroString::String(format!(
r#"{macro_name}:"{escaped}""#, r#"{macro_name}:"{escaped}""#,
@ -721,9 +719,9 @@ impl Transpiler {
macro_name = crate::util::identifier_to_macro(ident) macro_name = crate::util::identifier_to_macro(ident)
))) )))
.chain(parts.clone().into_iter().map(|part| match part { .chain(parts.clone().into_iter().map(|part| match part {
MacroStringPart::String(s) => MacroStringPart::String( MacroStringPart::String(s) => {
crate::util::escape_str(&s).to_string(), MacroStringPart::String(crate::util::escape_str(&s).to_string())
), }
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage, macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
})) }))
.chain(std::iter::once(MacroStringPart::String('"'.to_string()))) .chain(std::iter::once(MacroStringPart::String('"'.to_string())))
@ -732,7 +730,7 @@ impl Transpiler {
}); });
let arguments = super::util::join_macro_strings(arguments_iter); let arguments = super::util::join_macro_strings(arguments_iter);
match arguments { let cmd = match arguments {
MacroString::String(arguments) => { MacroString::String(arguments) => {
write!(function_call, " {{{arguments}}}").unwrap(); write!(function_call, " {{{arguments}}}").unwrap();
Command::Raw(function_call) Command::Raw(function_call)
@ -743,21 +741,12 @@ impl Transpiler {
parts.push(MacroStringPart::String('}'.to_string())); parts.push(MacroStringPart::String('}'.to_string()));
Command::UsesMacro(MacroString::MacroString(parts).into()) Command::UsesMacro(MacroString::MacroString(parts).into())
} }
}
}; };
setup_cmds.push(cmd); Ok(vec![cmd])
Ok(setup_cmds)
} }
TranspiledFunctionArguments::Dynamic(mut cmds) => { TranspiledFunctionArguments::Dynamic(mut cmds) => {
use std::fmt::Write as _; function_call.push_str(" with storage shulkerscript:function_arguments");
let _ = write!(
function_call,
" with storage shulkerscript:function_arguments_{suffix}",
suffix = location.replace(['/', ':'], "_")
);
cmds.push(Command::Raw(function_call)); cmds.push(Command::Raw(function_call));
Ok(cmds) Ok(cmds)
} }

View File

@ -60,7 +60,7 @@ impl MacroString {
/// ///
/// # Errors /// # Errors
/// - If the macro string contains macros /// - If the macro string contains macros
pub fn as_str(&self) -> Result<std::borrow::Cow<'_, str>, &[MacroStringPart]> { pub fn as_str(&self) -> Result<std::borrow::Cow<str>, &[MacroStringPart]> {
match self { match self {
Self::String(s) => Ok(std::borrow::Cow::Borrowed(s)), Self::String(s) => Ok(std::borrow::Cow::Borrowed(s)),
Self::MacroString(parts) if self.contains_macros() => Err(parts), Self::MacroString(parts) if self.contains_macros() => Err(parts),

View File

@ -308,7 +308,7 @@ impl Transpiler {
.comptime_eval(scope, handler) .comptime_eval(scope, handler)
.map_err(|err| { .map_err(|err| {
let err = TranspileError::NotComptime(err); let err = TranspileError::NotComptime(err);
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
err err
})?, })?,
) )
@ -569,7 +569,7 @@ impl Transpiler {
}, },
expression: expression.span(), expression: expression.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
Some(_) => { Some(_) => {
@ -579,7 +579,7 @@ impl Transpiler {
expected: ExpectedType::String, expected: ExpectedType::String,
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
None => { None => {
@ -588,7 +588,7 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Cannot assign to a scoreboard without indexing".to_string(), message: "Cannot assign to a scoreboard without indexing".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
}, },
@ -617,7 +617,7 @@ impl Transpiler {
length: targets.len(), length: targets.len(),
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
} }
@ -628,7 +628,7 @@ impl Transpiler {
expected: ExpectedType::Integer, expected: ExpectedType::Integer,
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
None => { None => {
@ -637,7 +637,7 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Cannot assign to an array without indexing".to_string(), message: "Cannot assign to an array without indexing".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
} }
@ -671,7 +671,7 @@ impl Transpiler {
length: paths.len(), length: paths.len(),
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
} }
@ -682,7 +682,7 @@ impl Transpiler {
expected: ExpectedType::Integer, expected: ExpectedType::Integer,
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
None => { None => {
@ -691,7 +691,7 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Cannot assign to an array without indexing".to_string(), message: "Cannot assign to an array without indexing".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
} }
@ -709,7 +709,7 @@ impl Transpiler {
expected: ExpectedType::String, expected: ExpectedType::String,
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
Some(_) => { Some(_) => {
@ -719,7 +719,7 @@ impl Transpiler {
expected: ExpectedType::String, expected: ExpectedType::String,
}, },
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
None => { None => {
@ -728,7 +728,7 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Cannot assign to a tag without indexing".to_string(), message: "Cannot assign to a tag without indexing".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
}, },
@ -738,13 +738,13 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Cannot assign to a read-only value.".to_string(), message: "Cannot assign to a read-only value.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
return Err(err); return Err(err);
} }
let comptime_value = let comptime_value =
expression.comptime_eval(scope, handler).map_err(|err| { expression.comptime_eval(scope, handler).map_err(|err| {
let err = TranspileError::NotComptime(err); let err = TranspileError::NotComptime(err);
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
err err
})?; })?;
*value.write().unwrap() = Some(comptime_value); *value.write().unwrap() = Some(comptime_value);
@ -765,7 +765,7 @@ impl Transpiler {
} }
), ),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}?; }?;
@ -775,7 +775,7 @@ impl Transpiler {
identifier: identifier.span(), identifier: identifier.span(),
message: "Variable does not exist.".to_string(), message: "Variable does not exist.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -796,12 +796,12 @@ impl Transpiler {
let deobfuscate_annotation = deobfuscate_annotations.next(); let deobfuscate_annotation = deobfuscate_annotations.next();
if let Some(duplicate) = deobfuscate_annotations.next() { if let Some(duplicate) = deobfuscate_annotations.next() {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: duplicate.span(), annotation: duplicate.span(),
message: "Multiple deobfuscate annotations are not allowed.".to_string(), message: "Multiple deobfuscate annotations are not allowed.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
if let Some(deobfuscate_annotation) = deobfuscate_annotation { if let Some(deobfuscate_annotation) = deobfuscate_annotation {
let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value( let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
@ -818,32 +818,33 @@ impl Transpiler {
{ {
// TODO: change invalid criteria if boolean // TODO: change invalid criteria if boolean
if !crate::util::is_valid_scoreboard_objective_name(&name_eval) { if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must be a valid scoreboard objective name.".to_string() message: "Deobfuscate annotation must be a valid scoreboard objective name.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
Ok(name_eval) Ok(name_eval)
} else { } else {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation could not have been evaluated at compile time.".to_string() message: "Deobfuscate annotation could not have been evaluated at compile time.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} }
TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()), TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()),
TranspileAnnotationValue::Map(_, _) => { TranspileAnnotationValue::Map(_, _) => {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must have no value or must be string." message: "Deobfuscate annotation must have no value or must be string."
.to_string(), .to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} }
} else { } else {
@ -880,12 +881,12 @@ impl Transpiler {
let deobfuscate_annotation = deobfuscate_annotations.next(); let deobfuscate_annotation = deobfuscate_annotations.next();
if let Some(duplicate) = deobfuscate_annotations.next() { if let Some(duplicate) = deobfuscate_annotations.next() {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: duplicate.span(), annotation: duplicate.span(),
message: "Multiple deobfuscate annotations are not allowed.".to_string(), message: "Multiple deobfuscate annotations are not allowed.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
if let Some(deobfuscate_annotation) = deobfuscate_annotation { if let Some(deobfuscate_annotation) = deobfuscate_annotation {
let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value( let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
@ -895,13 +896,14 @@ impl Transpiler {
if let TranspileAnnotationValue::Map(map, _) = deobfuscate_annotation_value { if let TranspileAnnotationValue::Map(map, _) = deobfuscate_annotation_value {
if map.len() > 2 { if map.len() > 2 {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must have at most 2 key-value pairs." message: "Deobfuscate annotation must have at most 2 key-value pairs."
.to_string(), .to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
if let (Some(name), Some(target)) = (map.get("name"), map.get("target")) { if let (Some(name), Some(target)) = (map.get("name"), map.get("target")) {
if let ( if let (
@ -921,54 +923,56 @@ impl Transpiler {
) { ) {
// TODO: change invalid criteria if boolean // TODO: change invalid criteria if boolean
if !crate::util::is_valid_scoreboard_objective_name(&name_eval) { if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation 'name' must be a valid scoreboard objective name.".to_string() message: "Deobfuscate annotation 'name' must be a valid scoreboard objective name.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
if !crate::util::is_valid_scoreboard_target(&target_eval) { if !crate::util::is_valid_scoreboard_target(&target_eval) {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation 'target' must be a valid scoreboard player name.".to_string() message: "Deobfuscate annotation 'target' must be a valid scoreboard player name.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
Ok((name_eval, target_eval)) Ok((name_eval, target_eval))
} else { } else {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation 'name' or 'target' could not have been evaluated at compile time.".to_string() message: "Deobfuscate annotation 'name' or 'target' could not have been evaluated at compile time.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} else { } else {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation 'name' and 'target' must be compile time expressions.".to_string() message: "Deobfuscate annotation 'name' and 'target' must be compile time expressions.".to_string()
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} else { } else {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must have both 'name' and 'target' keys." message:
"Deobfuscate annotation must have both 'name' and 'target' keys."
.to_string(), .to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} else { } else {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must be a map.".to_string(), message: "Deobfuscate annotation must be a map.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} else { } else {
let hashed = md5::hash(program_identifier).to_hex_lowercase(); let hashed = md5::hash(program_identifier).to_hex_lowercase();
@ -1013,12 +1017,12 @@ impl Transpiler {
let deobfuscate_annotation = deobfuscate_annotations.next(); let deobfuscate_annotation = deobfuscate_annotations.next();
if let Some(duplicate) = deobfuscate_annotations.next() { if let Some(duplicate) = deobfuscate_annotations.next() {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: duplicate.span(), annotation: duplicate.span(),
message: "Multiple deobfuscate annotations are not allowed.".to_string(), message: "Multiple deobfuscate annotations are not allowed.".to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
return Err(err); return Err(error);
} }
if let Some(deobfuscate_annotation) = deobfuscate_annotation { if let Some(deobfuscate_annotation) = deobfuscate_annotation {
let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value( let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
@ -1044,21 +1048,24 @@ impl Transpiler {
} }
TranspileAnnotationValue::Map(map, _) => { TranspileAnnotationValue::Map(map, _) => {
// TODO: implement when map deobfuscate annotation is implemented // TODO: implement when map deobfuscate annotation is implemented
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation value must be a string or none." message: "Deobfuscate annotation value must be a string or none."
.to_string(), .to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
TranspileAnnotationValue::Expression(_, _) => { TranspileAnnotationValue::Expression(_, _) => {
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation value must be a map or none.".to_string(), message: "Deobfuscate annotation value must be a map or none."
.to_string(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(error.clone());
Err(err) Err(error)
} }
} }
} else { } else {
@ -1161,7 +1168,7 @@ impl Transpiler {
expression: expression.span(), expression: expression.span(),
expected_type: to.value_type().into(), expected_type: to.value_type().into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1212,7 +1219,7 @@ impl Transpiler {
expression: expression.span(), expression: expression.span(),
expected_type: to.value_type().into(), expected_type: to.value_type().into(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
@ -1221,7 +1228,7 @@ impl Transpiler {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: expression.span(), expression: expression.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
@ -1230,7 +1237,7 @@ impl Transpiler {
expected_type: to.value_type().into(), expected_type: to.value_type().into(),
expression: expression.span(), expression: expression.span(),
}); });
handler.receive(Box::new(err.clone())); handler.receive(err.clone());
Err(err) Err(err)
} }
} }

View File

@ -4,7 +4,7 @@ use std::borrow::Cow;
/// Escapes `"` and `\` in a string. /// Escapes `"` and `\` in a string.
#[must_use] #[must_use]
pub fn escape_str(s: &str) -> Cow<'_, str> { pub fn escape_str(s: &str) -> Cow<str> {
if s.contains('"') || s.contains('\\') { if s.contains('"') || s.contains('\\') {
let mut escaped = String::with_capacity(s.len()); let mut escaped = String::with_capacity(s.len());
for c in s.chars() { for c in s.chars() {
@ -22,7 +22,7 @@ pub fn escape_str(s: &str) -> Cow<'_, str> {
/// Unescapes '\`', `\`, `\n`, `\r` and `\t` in a string. /// Unescapes '\`', `\`, `\n`, `\r` and `\t` in a string.
#[must_use] #[must_use]
pub fn unescape_macro_string(s: &str) -> Cow<'_, str> { pub fn unescape_macro_string(s: &str) -> Cow<str> {
if s.contains('\\') || s.contains('`') { if s.contains('\\') || s.contains('`') {
Cow::Owned( Cow::Owned(
s.replace("\\n", "\n") s.replace("\\n", "\n")
@ -39,7 +39,7 @@ pub fn unescape_macro_string(s: &str) -> Cow<'_, str> {
/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`. /// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
#[cfg(feature = "shulkerbox")] #[cfg(feature = "shulkerbox")]
#[must_use] #[must_use]
pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<'_, str> { pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<str> {
if ident.contains("__") if ident.contains("__")
|| ident || ident
.chars() .chars()
@ -82,7 +82,7 @@ pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<str> {
/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`. /// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
#[cfg(feature = "shulkerbox")] #[cfg(feature = "shulkerbox")]
#[must_use] #[must_use]
pub fn identifier_to_scoreboard_target(ident: &str) -> std::borrow::Cow<'_, str> { pub fn identifier_to_scoreboard_target(ident: &str) -> std::borrow::Cow<str> {
if !(..=16).contains(&ident.len()) if !(..=16).contains(&ident.len())
|| ident || ident
.chars() .chars()

View File

@ -20,7 +20,10 @@ fn parsing_test1() {
) )
.expect("Failed to parse"); .expect("Failed to parse");
assert_eq!(parsed.namespace().name().str_content(), "parsing-test"); assert_eq!(
parsed.namespace().namespace_name().str_content(),
"parsing-test"
);
let declarations = parsed.declarations(); let declarations = parsed.declarations();
assert_eq!(declarations.len(), 1); assert_eq!(declarations.len(), 1);