Compare commits
5 Commits
3271ca514c
...
bd8270bd5d
Author | SHA1 | Date |
---|---|---|
|
bd8270bd5d | |
|
e0c3253ab6 | |
|
15dde037b7 | |
|
0ee456756a | |
|
d9ae985282 |
|
@ -19,6 +19,7 @@ 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
|
||||||
|
|
|
@ -99,7 +99,7 @@ FunctionParameterList:
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
ArrayVariableDeclaration:
|
ArrayVariableDeclaration:
|
||||||
('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
|
('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment?
|
||||||
```
|
```
|
||||||
|
|
||||||
## ComptimeValueDeclaration
|
## ComptimeValueDeclaration
|
||||||
|
|
|
@ -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] crate::syntax::error::Error),
|
ParseError(#[from] Box<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] crate::transpile::TranspileError),
|
TranspileError(#[from] Box<crate::transpile::TranspileError>),
|
||||||
#[error("An error occurred: {0}")]
|
#[error("An error occurred: {0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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<'a>(self: &'a Arc<Self>) -> SourceIterator<'a> {
|
pub fn iter(self: &Arc<Self>) -> SourceIterator<'_> {
|
||||||
SourceIterator {
|
SourceIterator {
|
||||||
source_file: self,
|
source_file: self,
|
||||||
iterator: self.content().char_indices().peekable(),
|
iterator: self.content().char_indices().peekable(),
|
||||||
|
|
|
@ -161,7 +161,7 @@ pub enum Token {
|
||||||
DocComment(DocComment),
|
DocComment(DocComment),
|
||||||
CommandLiteral(CommandLiteral),
|
CommandLiteral(CommandLiteral),
|
||||||
StringLiteral(StringLiteral),
|
StringLiteral(StringLiteral),
|
||||||
MacroStringLiteral(MacroStringLiteral),
|
MacroStringLiteral(Box<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(),
|
||||||
}));
|
}));
|
||||||
return Err(TokenizeError::FatalLexicalError);
|
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(MacroStringLiteral {
|
Ok(Box::new(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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)?;
|
let program = parser.parse_program(handler).map_err(Box::new)?;
|
||||||
|
|
||||||
if handler.has_received() {
|
if handler.has_received() {
|
||||||
return Err(Error::other(
|
return Err(Error::other(
|
||||||
|
@ -165,8 +165,9 @@ where
|
||||||
|
|
||||||
tracing::info!("Transpiling the source code.");
|
tracing::info!("Transpiling the source code.");
|
||||||
|
|
||||||
let datapack =
|
let datapack = Transpiler::new(main_namespace_name, pack_format)
|
||||||
Transpiler::new(main_namespace_name, pack_format).transpile(&programs, handler)?;
|
.transpile(&programs, handler)
|
||||||
|
.map_err(Box::new)?;
|
||||||
|
|
||||||
if handler.has_received() {
|
if handler.has_received() {
|
||||||
return Err(Error::other(
|
return Err(Error::other(
|
||||||
|
|
|
@ -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 Expression);
|
pub struct UnexpectedExpression(pub Box<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 {
|
||||||
|
|
|
@ -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.namespace_name();
|
let name = self.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,12 +393,22 @@ 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 | VariableType::Tag => ValueType::Boolean,
|
VariableType::BooleanStorage => 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(),
|
||||||
|
@ -561,7 +571,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(
|
||||||
Expression::Primary(self.clone()),
|
Box::new(Expression::Primary(self.clone())),
|
||||||
));
|
));
|
||||||
handler.receive(err.clone());
|
handler.receive(err.clone());
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -706,13 +716,14 @@ impl Primary {
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Self::MemberAccess(_) => {
|
Self::MemberAccess(_) => {
|
||||||
// TODO:
|
// TODO: correct return value after check
|
||||||
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() {
|
||||||
|
@ -930,9 +941,10 @@ 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 = error::Error::UnexpectedExpression(UnexpectedExpression(
|
let err =
|
||||||
Expression::Primary(Primary::Identifier(identifier.clone())),
|
error::Error::UnexpectedExpression(UnexpectedExpression(Box::new(
|
||||||
));
|
Expression::Primary(Primary::Identifier(identifier.clone())),
|
||||||
|
)));
|
||||||
handler.receive(err.clone());
|
handler.receive(err.clone());
|
||||||
errs.push(err);
|
errs.push(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Syntax tree nodes for declarations.
|
//! Syntax tree nodes for declarations.
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
#![expect(missing_docs)]
|
||||||
|
#![expect(clippy::struct_field_names)]
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
@ -391,7 +392,7 @@ impl Parser<'_> {
|
||||||
|
|
||||||
declaration
|
declaration
|
||||||
.with_annotation(annotation)
|
.with_annotation(annotation)
|
||||||
.inspect_err(|err| handler.receive(err.clone()))
|
.inspect_err(|err| handler.receive(Box::new(err.clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
Reading::Atomic(Token::Keyword(from_keyword))
|
Reading::Atomic(Token::Keyword(from_keyword))
|
||||||
|
@ -441,7 +442,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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
|
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
@ -511,7 +512,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::Declaration,
|
expected: SyntaxKind::Declaration,
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
|
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
@ -562,7 +563,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::Keyword(KeywordKind::Function),
|
expected: SyntaxKind::Keyword(KeywordKind::Function),
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,7 +616,7 @@ impl Parser<'_> {
|
||||||
]),
|
]),
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::Punctuation('#'),
|
expected: SyntaxKind::Punctuation('#'),
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,10 @@ pub struct ProgramFile {
|
||||||
pub struct Namespace {
|
pub struct Namespace {
|
||||||
/// The `namespace` keyword.
|
/// The `namespace` keyword.
|
||||||
#[get = "pub"]
|
#[get = "pub"]
|
||||||
namespace_keyword: Keyword,
|
keyword: Keyword,
|
||||||
/// The name of the namespace.
|
/// The name of the namespace.
|
||||||
#[get = "pub"]
|
#[get = "pub"]
|
||||||
namespace_name: StringLiteral,
|
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.namespace_keyword
|
self.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.namespace_keyword, self.namespace_name, self.semicolon)
|
(self.keyword, self.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(namespace_keyword))
|
Reading::Atomic(Token::Keyword(keyword))
|
||||||
if namespace_keyword.keyword == KeywordKind::Namespace =>
|
if keyword.keyword == KeywordKind::Namespace =>
|
||||||
{
|
{
|
||||||
// eat the keyword
|
// eat the keyword
|
||||||
self.forward();
|
self.forward();
|
||||||
|
|
||||||
let namespace_name = self.parse_string_literal(handler)?;
|
let name = self.parse_string_literal(handler)?;
|
||||||
|
|
||||||
let semicolon = self.parse_punctuation(';', true, handler)?;
|
let semicolon = self.parse_punctuation(';', true, handler)?;
|
||||||
|
|
||||||
Ok(Namespace {
|
Ok(Namespace {
|
||||||
namespace_keyword,
|
keyword,
|
||||||
namespace_name,
|
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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"Found namespace '{}', parsing declarations",
|
"Found namespace '{}', parsing declarations",
|
||||||
namespace.namespace_name.str_content()
|
namespace.name.str_content()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut declarations = Vec::new();
|
let mut declarations = Vec::new();
|
||||||
|
|
|
@ -493,7 +493,7 @@ impl SingleVariableDeclaration {
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// ArrayVariableDeclaration:
|
/// ArrayVariableDeclaration:
|
||||||
/// ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
|
/// ('int' | 'bool') '[' integer ']' identifier 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,9 +501,6 @@ 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,
|
||||||
|
@ -513,6 +510,9 @@ 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, Expression, Punctuation),
|
Indexed(Identifier, Punctuation, Box<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(err.clone()))
|
.inspect_err(|err| handler.receive(Box::new(err.clone())))
|
||||||
}
|
}
|
||||||
// variable declaration
|
// variable declaration
|
||||||
Reading::Atomic(Token::CommandLiteral(command)) => {
|
Reading::Atomic(Token::CommandLiteral(command)) => {
|
||||||
|
@ -971,7 +971,12 @@ impl Parser<'_> {
|
||||||
let close = tree.close;
|
let close = tree.close;
|
||||||
let expression = tree.tree?;
|
let expression = tree.tree?;
|
||||||
|
|
||||||
AssignmentDestination::Indexed(identifier, open, expression, close)
|
AssignmentDestination::Indexed(
|
||||||
|
identifier,
|
||||||
|
open,
|
||||||
|
Box::new(expression),
|
||||||
|
close,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => AssignmentDestination::Identifier(identifier),
|
_ => AssignmentDestination::Identifier(identifier),
|
||||||
}
|
}
|
||||||
|
@ -1036,7 +1041,7 @@ impl Parser<'_> {
|
||||||
]),
|
]),
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1053,11 +1058,7 @@ impl Parser<'_> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// read identifier
|
let index = match self.stop_at_significant() {
|
||||||
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) =>
|
||||||
|
@ -1080,7 +1081,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::Integer,
|
expected: SyntaxKind::Integer,
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1094,67 +1095,72 @@ impl Parser<'_> {
|
||||||
let close_bracket = tree.close;
|
let close_bracket = tree.close;
|
||||||
let inner = tree.tree?;
|
let inner = tree.tree?;
|
||||||
|
|
||||||
match inner {
|
Some((open_bracket, inner, close_bracket))
|
||||||
IndexingType::IntegerSize(size) => {
|
}
|
||||||
let assignment = self
|
_ => None,
|
||||||
.try_parse(|p| {
|
};
|
||||||
// read equals sign
|
|
||||||
let equals = p.parse_punctuation('=', true, &VoidHandler)?;
|
|
||||||
|
|
||||||
// read expression
|
// read identifier
|
||||||
let expression = p.parse_expression(&VoidHandler)?;
|
self.stop_at_significant();
|
||||||
|
let identifier = self.parse_identifier(handler)?;
|
||||||
|
|
||||||
Ok(VariableDeclarationAssignment { equals, expression })
|
// TODO: allow assignment when map and array literals have been implemented
|
||||||
})
|
let assignment = if index.is_none() {
|
||||||
.ok();
|
self.try_parse(|p| {
|
||||||
|
// read equals sign
|
||||||
|
let equals = p.parse_punctuation('=', true, &VoidHandler)?;
|
||||||
|
|
||||||
Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
|
// read expression
|
||||||
variable_type,
|
let expression = p.parse_expression(&VoidHandler)?;
|
||||||
identifier,
|
|
||||||
open_bracket,
|
Ok(VariableDeclarationAssignment { equals, expression })
|
||||||
size,
|
})
|
||||||
close_bracket,
|
.ok()
|
||||||
assignment,
|
} else {
|
||||||
annotations: VecDeque::new(),
|
None
|
||||||
}))
|
};
|
||||||
}
|
|
||||||
IndexingType::None => match variable_type.keyword {
|
match index {
|
||||||
KeywordKind::Int => {
|
Some((open_bracket, IndexingType::IntegerSize(size), close_bracket)) => {
|
||||||
Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
|
Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
|
||||||
int_keyword: variable_type,
|
variable_type,
|
||||||
criteria: criteria_selection,
|
identifier,
|
||||||
identifier,
|
open_bracket,
|
||||||
open_bracket,
|
size,
|
||||||
close_bracket,
|
close_bracket,
|
||||||
assignment: None,
|
assignment,
|
||||||
annotations: VecDeque::new(),
|
annotations: VecDeque::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
|
Some((open_bracket, IndexingType::None, close_bracket)) => {
|
||||||
bool_keyword: variable_type,
|
match variable_type.keyword {
|
||||||
identifier,
|
KeywordKind::Int => Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
|
||||||
open_bracket,
|
int_keyword: variable_type,
|
||||||
close_bracket,
|
criteria: criteria_selection,
|
||||||
target_assignment: None,
|
identifier,
|
||||||
annotations: VecDeque::new(),
|
open_bracket,
|
||||||
})),
|
close_bracket,
|
||||||
_ => unreachable!(),
|
assignment: None,
|
||||||
},
|
annotations: VecDeque::new(),
|
||||||
|
})),
|
||||||
|
KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
|
||||||
|
bool_keyword: variable_type,
|
||||||
|
identifier,
|
||||||
|
open_bracket,
|
||||||
|
close_bracket,
|
||||||
|
target_assignment: None,
|
||||||
|
annotations: VecDeque::new(),
|
||||||
|
})),
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SingleVariableDeclaration with Assignment
|
None => {
|
||||||
Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '=' => {
|
if matches!(variable_type.keyword, KeywordKind::Val) {
|
||||||
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: Some(assignment),
|
assignment,
|
||||||
annotations: VecDeque::new(),
|
annotations: VecDeque::new(),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -1162,18 +1168,11 @@ impl Parser<'_> {
|
||||||
Ok(VariableDeclaration::Single(SingleVariableDeclaration {
|
Ok(VariableDeclaration::Single(SingleVariableDeclaration {
|
||||||
variable_type,
|
variable_type,
|
||||||
identifier,
|
identifier,
|
||||||
assignment: Some(assignment),
|
assignment,
|
||||||
annotations: VecDeque::new(),
|
annotations: VecDeque::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SingleVariableDeclaration without Assignment
|
|
||||||
_ => Ok(VariableDeclaration::Single(SingleVariableDeclaration {
|
|
||||||
variable_type,
|
|
||||||
identifier,
|
|
||||||
assignment: None,
|
|
||||||
annotations: VecDeque::new(),
|
|
||||||
})),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! 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;
|
||||||
|
@ -824,7 +826,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::Punctuation('('),
|
expected: SyntaxKind::Punctuation('('),
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
@ -842,7 +844,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::ExecuteBlock,
|
expected: SyntaxKind::ExecuteBlock,
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -878,7 +880,7 @@ impl Parser<'_> {
|
||||||
expected: SyntaxKind::ExecuteBlockTail,
|
expected: SyntaxKind::ExecuteBlockTail,
|
||||||
found: unexpected.into_token(),
|
found: unexpected.into_token(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,8 @@ 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()
|
||||||
|
@ -118,7 +120,7 @@ impl Display for MissingFunctionDeclaration {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
message.push_str(", ");
|
message.push_str(", ");
|
||||||
}
|
}
|
||||||
message.push_str(&format!("`{}`", alternative.identifier_span.str()));
|
let _ = write!(message, "`{}`", alternative.identifier_span.str());
|
||||||
}
|
}
|
||||||
Some(message + "?")
|
Some(message + "?")
|
||||||
};
|
};
|
||||||
|
@ -398,6 +400,11 @@ 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 {
|
||||||
|
@ -421,6 +428,9 @@ 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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
})
|
})
|
||||||
.map_err(|_| NotComptime {
|
.map_err(|_| NotComptime {
|
||||||
expression: lua.span(),
|
expression: lua.span(),
|
||||||
|
@ -1191,7 +1191,7 @@ impl Transpiler {
|
||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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,7 +1225,18 @@ 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) =>
|
||||||
|
@ -1237,7 +1248,7 @@ impl Transpiler {
|
||||||
let err = TranspileError::MissingValue(MissingValue {
|
let err = TranspileError::MissingValue(MissingValue {
|
||||||
expression: lua.span(),
|
expression: lua.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1262,7 +1273,7 @@ impl Transpiler {
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1326,7 +1337,7 @@ impl Transpiler {
|
||||||
expression: prefix.span(),
|
expression: prefix.span(),
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1422,7 +1433,7 @@ impl Transpiler {
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
@ -1432,7 +1443,7 @@ impl Transpiler {
|
||||||
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1444,7 +1455,7 @@ impl Transpiler {
|
||||||
reason: IllegalIndexingReason::NotIdentifier,
|
reason: IllegalIndexingReason::NotIdentifier,
|
||||||
expression: indexed.object().span(),
|
expression: indexed.object().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}?;
|
}?;
|
||||||
let variable = scope.get_variable(ident.span.str());
|
let variable = scope.get_variable(ident.span.str());
|
||||||
|
@ -1466,7 +1477,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1502,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1501,7 +1512,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1530,7 +1541,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1540,7 +1551,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1549,7 +1560,7 @@ impl Transpiler {
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
@ -1559,7 +1570,7 @@ impl Transpiler {
|
||||||
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1636,7 +1647,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
Primary::StringLiteral(s) => Ok((
|
Primary::StringLiteral(s) => Ok((
|
||||||
|
@ -1659,7 +1670,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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
let (func_location, _) = self.get_or_transpile_function(
|
let (func_location, _) = self.get_or_transpile_function(
|
||||||
|
@ -1702,7 +1713,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1710,7 +1721,7 @@ impl Transpiler {
|
||||||
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1725,7 +1736,7 @@ impl Transpiler {
|
||||||
reason: IllegalIndexingReason::NotIdentifier,
|
reason: IllegalIndexingReason::NotIdentifier,
|
||||||
expression: indexed.object().span(),
|
expression: indexed.object().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}?;
|
}?;
|
||||||
#[expect(clippy::option_if_let_else)]
|
#[expect(clippy::option_if_let_else)]
|
||||||
|
@ -1759,7 +1770,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1769,7 +1780,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: indexed.index().span(),
|
expression: indexed.index().span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1778,7 +1789,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1786,7 +1797,7 @@ impl Transpiler {
|
||||||
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1794,7 +1805,18 @@ 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)))
|
||||||
|
@ -1804,7 +1826,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
ComptimeValue::String(s) => Ok((
|
ComptimeValue::String(s) => Ok((
|
||||||
|
@ -1860,7 +1882,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1881,7 +1903,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: primary.span(),
|
expression: primary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1911,7 +1933,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: binary.span(),
|
expression: binary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2000,7 +2022,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: binary.span(),
|
expression: binary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
DataLocation::Storage {
|
DataLocation::Storage {
|
||||||
|
@ -2027,7 +2049,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: binary.span(),
|
expression: binary.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2173,7 +2195,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: source.span(),
|
expression: source.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
DataLocation::Storage {
|
DataLocation::Storage {
|
||||||
|
@ -2197,7 +2219,7 @@ impl Transpiler {
|
||||||
expression: source.span(),
|
expression: source.span(),
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2223,7 +2245,7 @@ impl Transpiler {
|
||||||
expression: source.span(),
|
expression: source.span(),
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2258,7 +2280,7 @@ impl Transpiler {
|
||||||
expected_type: target.value_type().into(),
|
expected_type: target.value_type().into(),
|
||||||
expression: source.span(),
|
expression: source.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2294,7 +2316,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: source.span(),
|
expression: source.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use super::{
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TranspiledFunctionArguments {
|
pub enum TranspiledFunctionArguments {
|
||||||
None,
|
None,
|
||||||
Static(BTreeMap<String, MacroString>),
|
Static(BTreeMap<String, MacroString>, Vec<Command>),
|
||||||
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 error = TranspileError::MissingFunctionDeclaration(
|
let err = TranspileError::MissingFunctionDeclaration(
|
||||||
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
|
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
|
||||||
);
|
);
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
error
|
err
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let VariableData::Function {
|
let VariableData::Function {
|
||||||
|
@ -99,7 +99,7 @@ impl Transpiler {
|
||||||
.to_string(),
|
.to_string(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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 error = TranspileError::MissingFunctionDeclaration(
|
let err = TranspileError::MissingFunctionDeclaration(
|
||||||
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
|
MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
|
||||||
);
|
);
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
error
|
err
|
||||||
})
|
})
|
||||||
.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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
err
|
err
|
||||||
})?;
|
})?;
|
||||||
match var.as_ref() {
|
match var.as_ref() {
|
||||||
|
@ -353,7 +353,7 @@ impl Transpiler {
|
||||||
ExpectedType::String,
|
ExpectedType::String,
|
||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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 (mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
|
let (require_dyn_params, mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
|
||||||
(Vec::new(), Vec::new(), BTreeMap::new()),
|
(false, Vec::new(), Vec::new(), BTreeMap::new()),
|
||||||
|(mut acc_setup, mut acc_move, mut statics), (param, data)| {
|
|(mut require_dyn_params, 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,6 +455,7 @@ 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}")
|
||||||
|
@ -495,6 +496,7 @@ 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);
|
||||||
|
@ -524,50 +526,67 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
(acc_setup, acc_move, statics)},
|
(require_dyn_params, acc_setup, acc_move, statics)},
|
||||||
);
|
);
|
||||||
let statics_len = static_params.len();
|
if require_dyn_params {
|
||||||
let joined_statics =
|
let statics_len = static_params.len();
|
||||||
super::util::join_macro_strings(static_params.into_iter().enumerate().map(
|
let joined_statics = super::util::join_macro_strings(
|
||||||
|(i, (k, v))| match v {
|
static_params
|
||||||
MacroString::String(s) => {
|
.into_iter()
|
||||||
let mut s = format!(r#"{k}:"{s}""#);
|
.enumerate()
|
||||||
if i < statics_len - 1 {
|
.map(|(i, (k, v))| match v {
|
||||||
s.push(',');
|
MacroString::String(s) => {
|
||||||
|
let mut s = format!(r#"{k}:"{s}""#);
|
||||||
|
if i < statics_len - 1 {
|
||||||
|
s.push(',');
|
||||||
|
}
|
||||||
|
MacroString::String(s)
|
||||||
}
|
}
|
||||||
MacroString::String(s)
|
MacroString::MacroString(mut parts) => {
|
||||||
}
|
parts.insert(
|
||||||
MacroString::MacroString(mut parts) => {
|
0,
|
||||||
parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#)));
|
MacroStringPart::String(format!(r#"{k}:""#)),
|
||||||
let mut ending = '"'.to_string();
|
);
|
||||||
if i < statics_len - 1 {
|
let mut ending = '"'.to_string();
|
||||||
ending.push(',');
|
if i < statics_len - 1 {
|
||||||
|
ending.push(',');
|
||||||
|
}
|
||||||
|
parts.push(MacroStringPart::String(ending));
|
||||||
|
MacroString::MacroString(parts)
|
||||||
}
|
}
|
||||||
parts.push(MacroStringPart::String(ending));
|
}),
|
||||||
MacroString::MacroString(parts)
|
);
|
||||||
}
|
let storage_suffix = function_location.replace(['/', ':'], "_");
|
||||||
},
|
let statics_cmd = match joined_statics {
|
||||||
));
|
MacroString::String(s) => Command::Raw(format!(
|
||||||
let statics_cmd = match joined_statics {
|
r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}"
|
||||||
MacroString::String(s) => Command::Raw(format!(
|
)),
|
||||||
r"data merge storage shulkerscript:function_arguments {{{s}}}"
|
MacroString::MacroString(_) => {
|
||||||
)),
|
let prefix = MacroString::String(
|
||||||
MacroString::MacroString(_) => Command::UsesMacro(
|
format!("data merge storage shulkerscript:function_arguments_{storage_suffix} {{"),
|
||||||
super::util::join_macro_strings([
|
);
|
||||||
MacroString::String(
|
Command::UsesMacro(
|
||||||
"data merge storage shulkerscript:function_arguments {"
|
super::util::join_macro_strings([
|
||||||
.to_string(),
|
prefix,
|
||||||
),
|
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()
|
||||||
|
@ -579,7 +598,10 @@ 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(function_args))
|
Ok(TranspiledFunctionArguments::Static(
|
||||||
|
function_args,
|
||||||
|
Vec::new(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Ok(TranspiledFunctionArguments::None),
|
_ => Ok(TranspiledFunctionArguments::None),
|
||||||
|
|
|
@ -132,7 +132,7 @@ fn print_function(
|
||||||
Ok((false, cmd, value))
|
Ok((false, cmd, value))
|
||||||
}
|
}
|
||||||
_ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression(
|
_ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression(
|
||||||
Expression::Primary(Primary::Identifier(ident.to_owned())),
|
Box::new(Expression::Primary(Primary::Identifier(ident.to_owned()))),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -58,7 +58,7 @@ mod enabled {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.add_globals(&lua, scope)
|
self.add_globals(&lua, scope)
|
||||||
.inspect_err(|err| handler.receive(err.clone()))?;
|
.inspect_err(|err| handler.receive(Box::new(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(err.clone()));
|
handler.receive(crate::Error::from(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
@ -380,7 +380,7 @@ mod enabled {
|
||||||
&err,
|
&err,
|
||||||
self.span(),
|
self.span(),
|
||||||
));
|
));
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,13 +196,12 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
TranspileAnnotationValue::Expression(_, span)
|
TranspileAnnotationValue::Expression(_, span)
|
||||||
| TranspileAnnotationValue::Map(_, span) => {
|
| TranspileAnnotationValue::Map(_, span) => {
|
||||||
let error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
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<_>>>()?;
|
||||||
|
@ -273,7 +272,7 @@ impl Transpiler {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let function_data = FunctionData {
|
let function_data = FunctionData {
|
||||||
namespace: namespace.namespace_name().str_content().to_string(),
|
namespace: namespace.name().str_content().to_string(),
|
||||||
identifier_span: identifier_span.clone(),
|
identifier_span: identifier_span.clone(),
|
||||||
parameters: function
|
parameters: function
|
||||||
.parameters()
|
.parameters()
|
||||||
|
@ -318,9 +317,7 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Declaration::Tag(tag) => {
|
Declaration::Tag(tag) => {
|
||||||
let namespace = self
|
let namespace = self.datapack.namespace_mut(namespace.name().str_content());
|
||||||
.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 {
|
||||||
|
@ -344,7 +341,7 @@ impl Transpiler {
|
||||||
|
|
||||||
self.setup_cmds.extend(setup_variable_cmds);
|
self.setup_cmds.extend(setup_variable_cmds);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -415,11 +412,11 @@ impl Transpiler {
|
||||||
self.transpile_run_expression(prefix.operand(), scope, handler)
|
self.transpile_run_expression(prefix.operand(), scope, handler)
|
||||||
}
|
}
|
||||||
unexpected => {
|
unexpected => {
|
||||||
let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
let err = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
||||||
unexpected.clone(),
|
Box::new(unexpected.clone()),
|
||||||
));
|
));
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SemicolonStatement::VariableDeclaration(decl) => self
|
SemicolonStatement::VariableDeclaration(decl) => self
|
||||||
|
@ -495,11 +492,11 @@ impl Transpiler {
|
||||||
read_only: _,
|
read_only: _,
|
||||||
} => value.read().unwrap().as_ref().map_or_else(
|
} => value.read().unwrap().as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let error = TranspileError::MissingValue(MissingValue {
|
let err = TranspileError::MissingValue(MissingValue {
|
||||||
expression: ident.span.clone(),
|
expression: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
},
|
},
|
||||||
|val| {
|
|val| {
|
||||||
let cmd = val.to_string_no_macro().map_or_else(
|
let cmd = val.to_string_no_macro().map_or_else(
|
||||||
|
@ -532,20 +529,21 @@ impl Transpiler {
|
||||||
)))),
|
)))),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let error =
|
let err = TranspileError::UnexpectedExpression(
|
||||||
TranspileError::UnexpectedExpression(UnexpectedExpression(
|
UnexpectedExpression(Box::new(Expression::Primary(
|
||||||
Expression::Primary(Primary::Identifier(ident.clone())),
|
Primary::Identifier(ident.clone()),
|
||||||
));
|
))),
|
||||||
handler.receive(error.clone());
|
);
|
||||||
return Err(error);
|
handler.receive(Box::new(err.clone()));
|
||||||
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -590,11 +588,11 @@ impl Transpiler {
|
||||||
read_only: _,
|
read_only: _,
|
||||||
}) => value.read().unwrap().as_ref().map_or_else(
|
}) => value.read().unwrap().as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let error = TranspileError::MissingValue(MissingValue {
|
let err = TranspileError::MissingValue(MissingValue {
|
||||||
expression: ident.span.clone(),
|
expression: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
},
|
},
|
||||||
|val| {
|
|val| {
|
||||||
let cmd = val.to_string_no_macro().map_or_else(
|
let cmd = val.to_string_no_macro().map_or_else(
|
||||||
|
@ -605,18 +603,18 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new(
|
||||||
Expression::Primary(expression.clone()),
|
Expression::Primary(expression.clone()),
|
||||||
));
|
)));
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: ident.span.clone(),
|
identifier: ident.span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -625,11 +623,11 @@ impl Transpiler {
|
||||||
| Primary::Prefix(_)
|
| Primary::Prefix(_)
|
||||||
| Primary::Indexed(_)
|
| Primary::Indexed(_)
|
||||||
| Primary::MemberAccess(_) => {
|
| Primary::MemberAccess(_) => {
|
||||||
let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new(
|
||||||
Expression::Primary(expression.clone()),
|
Expression::Primary(expression.clone()),
|
||||||
));
|
)));
|
||||||
handler.receive(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
Primary::StringLiteral(string) => {
|
Primary::StringLiteral(string) => {
|
||||||
Ok(vec![Command::Raw(string.str_content().to_string())])
|
Ok(vec![Command::Raw(string.str_content().to_string())])
|
||||||
|
@ -643,14 +641,14 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::String,
|
expected_type: ExpectedType::String,
|
||||||
expression: code.span(),
|
expression: code.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -667,12 +665,12 @@ impl Transpiler {
|
||||||
expression: bin.span(),
|
expression: bin.span(),
|
||||||
expected_type: ExpectedType::String,
|
expected_type: ExpectedType::String,
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -694,7 +692,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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let (location, arguments) = self.get_or_transpile_function(
|
let (location, arguments) = self.get_or_transpile_function(
|
||||||
|
@ -705,48 +703,61 @@ impl Transpiler {
|
||||||
)?;
|
)?;
|
||||||
let mut function_call = format!("function {location}");
|
let mut function_call = format!("function {location}");
|
||||||
match arguments {
|
match arguments {
|
||||||
TranspiledFunctionArguments::Static(arguments) => {
|
TranspiledFunctionArguments::Static(arguments, mut setup_cmds) => {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let arguments_iter = arguments.iter().map(|(ident, v)| match v {
|
|
||||||
MacroString::String(s) => MacroString::String(format!(
|
|
||||||
r#"{macro_name}:"{escaped}""#,
|
|
||||||
macro_name = crate::util::identifier_to_macro(ident),
|
|
||||||
escaped = crate::util::escape_str(s)
|
|
||||||
)),
|
|
||||||
MacroString::MacroString(parts) => MacroString::MacroString(
|
|
||||||
std::iter::once(MacroStringPart::String(format!(
|
|
||||||
r#"{macro_name}:""#,
|
|
||||||
macro_name = crate::util::identifier_to_macro(ident)
|
|
||||||
)))
|
|
||||||
.chain(parts.clone().into_iter().map(|part| match part {
|
|
||||||
MacroStringPart::String(s) => {
|
|
||||||
MacroStringPart::String(crate::util::escape_str(&s).to_string())
|
|
||||||
}
|
|
||||||
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
|
|
||||||
}))
|
|
||||||
.chain(std::iter::once(MacroStringPart::String('"'.to_string())))
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
let arguments = super::util::join_macro_strings(arguments_iter);
|
|
||||||
|
|
||||||
let cmd = match arguments {
|
let cmd = if arguments.is_empty() {
|
||||||
MacroString::String(arguments) => {
|
Command::Raw(function_call)
|
||||||
write!(function_call, " {{{arguments}}}").unwrap();
|
} else {
|
||||||
Command::Raw(function_call)
|
let arguments_iter = arguments.iter().map(|(ident, v)| match v {
|
||||||
}
|
MacroString::String(s) => MacroString::String(format!(
|
||||||
MacroString::MacroString(mut parts) => {
|
r#"{macro_name}:"{escaped}""#,
|
||||||
function_call.push_str(" {");
|
macro_name = crate::util::identifier_to_macro(ident),
|
||||||
parts.insert(0, MacroStringPart::String(function_call));
|
escaped = crate::util::escape_str(s)
|
||||||
parts.push(MacroStringPart::String('}'.to_string()));
|
)),
|
||||||
Command::UsesMacro(MacroString::MacroString(parts).into())
|
MacroString::MacroString(parts) => MacroString::MacroString(
|
||||||
|
std::iter::once(MacroStringPart::String(format!(
|
||||||
|
r#"{macro_name}:""#,
|
||||||
|
macro_name = crate::util::identifier_to_macro(ident)
|
||||||
|
)))
|
||||||
|
.chain(parts.clone().into_iter().map(|part| match part {
|
||||||
|
MacroStringPart::String(s) => MacroStringPart::String(
|
||||||
|
crate::util::escape_str(&s).to_string(),
|
||||||
|
),
|
||||||
|
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
|
||||||
|
}))
|
||||||
|
.chain(std::iter::once(MacroStringPart::String('"'.to_string())))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
let arguments = super::util::join_macro_strings(arguments_iter);
|
||||||
|
|
||||||
|
match arguments {
|
||||||
|
MacroString::String(arguments) => {
|
||||||
|
write!(function_call, " {{{arguments}}}").unwrap();
|
||||||
|
Command::Raw(function_call)
|
||||||
|
}
|
||||||
|
MacroString::MacroString(mut parts) => {
|
||||||
|
function_call.push_str(" {");
|
||||||
|
parts.insert(0, MacroStringPart::String(function_call));
|
||||||
|
parts.push(MacroStringPart::String('}'.to_string()));
|
||||||
|
Command::UsesMacro(MacroString::MacroString(parts).into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(vec![cmd])
|
setup_cmds.push(cmd);
|
||||||
|
|
||||||
|
Ok(setup_cmds)
|
||||||
}
|
}
|
||||||
TranspiledFunctionArguments::Dynamic(mut cmds) => {
|
TranspiledFunctionArguments::Dynamic(mut cmds) => {
|
||||||
function_call.push_str(" with storage shulkerscript:function_arguments");
|
use std::fmt::Write as _;
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
err
|
err
|
||||||
})?,
|
})?,
|
||||||
)
|
)
|
||||||
|
@ -569,7 +569,7 @@ impl Transpiler {
|
||||||
},
|
},
|
||||||
expression: expression.span(),
|
expression: expression.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
@ -579,7 +579,7 @@ impl Transpiler {
|
||||||
expected: ExpectedType::String,
|
expected: ExpectedType::String,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -617,7 +617,7 @@ impl Transpiler {
|
||||||
length: targets.len(),
|
length: targets.len(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ impl Transpiler {
|
||||||
expected: ExpectedType::Integer,
|
expected: ExpectedType::Integer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,7 +671,7 @@ impl Transpiler {
|
||||||
length: paths.len(),
|
length: paths.len(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,7 +682,7 @@ impl Transpiler {
|
||||||
expected: ExpectedType::Integer,
|
expected: ExpectedType::Integer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,7 +709,7 @@ impl Transpiler {
|
||||||
expected: ExpectedType::String,
|
expected: ExpectedType::String,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
@ -719,7 +719,7 @@ impl Transpiler {
|
||||||
expected: ExpectedType::String,
|
expected: ExpectedType::String,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
err
|
err
|
||||||
})?;
|
})?;
|
||||||
*value.write().unwrap() = Some(comptime_value);
|
*value.write().unwrap() = Some(comptime_value);
|
||||||
|
@ -765,7 +765,7 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(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(err.clone());
|
handler.receive(Box::new(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 error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
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,33 +818,32 @@ 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 error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Ok(name_eval)
|
Ok(name_eval)
|
||||||
} else {
|
} else {
|
||||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()),
|
TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()),
|
||||||
TranspileAnnotationValue::Map(_, _) => {
|
TranspileAnnotationValue::Map(_, _) => {
|
||||||
let error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
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 {
|
||||||
|
@ -881,12 +880,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 error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
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(
|
||||||
|
@ -896,14 +895,13 @@ 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 error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
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 (
|
||||||
|
@ -923,56 +921,54 @@ 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 error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
if !crate::util::is_valid_scoreboard_target(&target_eval) {
|
if !crate::util::is_valid_scoreboard_target(&target_eval) {
|
||||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Ok((name_eval, target_eval))
|
Ok((name_eval, target_eval))
|
||||||
} else {
|
} else {
|
||||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
annotation: deobfuscate_annotation.span(),
|
||||||
annotation: deobfuscate_annotation.span(),
|
message: "Deobfuscate annotation must have both 'name' and 'target' keys."
|
||||||
message:
|
.to_string(),
|
||||||
"Deobfuscate annotation must have both 'name' and 'target' keys."
|
});
|
||||||
.to_string(),
|
handler.receive(Box::new(err.clone()));
|
||||||
});
|
Err(err)
|
||||||
handler.receive(error.clone());
|
|
||||||
Err(error)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(error)
|
Err(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let hashed = md5::hash(program_identifier).to_hex_lowercase();
|
let hashed = md5::hash(program_identifier).to_hex_lowercase();
|
||||||
|
@ -1017,12 +1013,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 error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
let err = 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(error.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
return Err(error);
|
return Err(err);
|
||||||
}
|
}
|
||||||
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(
|
||||||
|
@ -1048,24 +1044,21 @@ 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 error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
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 error =
|
let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||||
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()));
|
||||||
});
|
Err(err)
|
||||||
handler.receive(error.clone());
|
|
||||||
Err(error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1168,7 +1161,7 @@ impl Transpiler {
|
||||||
expression: expression.span(),
|
expression: expression.span(),
|
||||||
expected_type: to.value_type().into(),
|
expected_type: to.value_type().into(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1212,7 @@ impl Transpiler {
|
||||||
expression: expression.span(),
|
expression: expression.span(),
|
||||||
expected_type: to.value_type().into(),
|
expected_type: to.value_type().into(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1228,7 +1221,7 @@ impl Transpiler {
|
||||||
expected_type: ExpectedType::Boolean,
|
expected_type: ExpectedType::Boolean,
|
||||||
expression: expression.span(),
|
expression: expression.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1237,7 +1230,7 @@ impl Transpiler {
|
||||||
expected_type: to.value_type().into(),
|
expected_type: to.value_type().into(),
|
||||||
expression: expression.span(),
|
expression: expression.span(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(Box::new(err.clone()));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -20,10 +20,7 @@ fn parsing_test1() {
|
||||||
)
|
)
|
||||||
.expect("Failed to parse");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(parsed.namespace().name().str_content(), "parsing-test");
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue