implement global variables (without imports)
This commit is contained in:
parent
469b8d3875
commit
0a8bf37e40
|
@ -99,6 +99,25 @@ impl Declaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Self::GlobalVariable((var, _)) => {
|
||||||
|
let name = var.identifier();
|
||||||
|
let var_type = match var {
|
||||||
|
VariableDeclaration::Array(arr) => match arr.variable_type().keyword {
|
||||||
|
KeywordKind::Bool => VariableType::BooleanStorageArray,
|
||||||
|
KeywordKind::Int => VariableType::ScoreboardArray,
|
||||||
|
_ => unreachable!("variable type is not a valid type"),
|
||||||
|
},
|
||||||
|
VariableDeclaration::Score(_) => VariableType::Scoreboard,
|
||||||
|
VariableDeclaration::Tag(_) => VariableType::Tag,
|
||||||
|
VariableDeclaration::Single(single) => match single.variable_type().keyword {
|
||||||
|
KeywordKind::Bool => VariableType::BooleanStorage,
|
||||||
|
KeywordKind::Int => VariableType::ScoreboardValue,
|
||||||
|
_ => unreachable!("variable type is not a valid type"),
|
||||||
|
},
|
||||||
|
VariableDeclaration::ComptimeValue(_) => VariableType::ComptimeValue,
|
||||||
|
};
|
||||||
|
scope.set_variable(name.span.str(), var_type);
|
||||||
|
}
|
||||||
Self::Tag(_) => {}
|
Self::Tag(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,6 +156,8 @@ impl Declaration {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Self::GlobalVariable((var, _)) => var.analyze_semantics(scope, handler),
|
||||||
|
|
||||||
Self::Tag(_) => Ok(()),
|
Self::Tag(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,16 +570,26 @@ impl Primary {
|
||||||
Self::Boolean(_) | Self::Integer(_) | Self::StringLiteral(_) => Ok(()),
|
Self::Boolean(_) | Self::Integer(_) | Self::StringLiteral(_) => Ok(()),
|
||||||
Self::MacroStringLiteral(lit) => lit.analyze_semantics(scope, handler),
|
Self::MacroStringLiteral(lit) => lit.analyze_semantics(scope, handler),
|
||||||
Self::FunctionCall(call) => {
|
Self::FunctionCall(call) => {
|
||||||
if scope.get_variable(call.identifier().span.str()) == Some(VariableType::Function)
|
let var = scope.get_variable(call.identifier().span.str());
|
||||||
{
|
var.map_or_else(
|
||||||
Ok(())
|
|| {
|
||||||
} else {
|
|
||||||
let err = error::Error::UnknownIdentifier(UnknownIdentifier {
|
let err = error::Error::UnknownIdentifier(UnknownIdentifier {
|
||||||
identifier: call.identifier().span.clone(),
|
identifier: call.identifier().span.clone(),
|
||||||
});
|
});
|
||||||
handler.receive(err.clone());
|
handler.receive(err.clone());
|
||||||
Err(err)
|
Err(err)
|
||||||
|
},
|
||||||
|
|var| match var {
|
||||||
|
VariableType::Function | VariableType::InternalFunction => Ok(()),
|
||||||
|
_ => {
|
||||||
|
let err = error::Error::UnexpectedExpression(UnexpectedExpression(
|
||||||
|
Expression::Primary(self.clone()),
|
||||||
|
));
|
||||||
|
handler.receive(err.clone());
|
||||||
|
Err(err)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Self::Indexed(indexed) => {
|
Self::Indexed(indexed) => {
|
||||||
if let Self::Identifier(ident) = indexed.object().as_ref() {
|
if let Self::Identifier(ident) = indexed.object().as_ref() {
|
||||||
|
|
|
@ -23,7 +23,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{statement::Block, Annotation, ConnectedList, DelimitedList};
|
use super::{
|
||||||
|
statement::{Block, VariableDeclaration},
|
||||||
|
Annotation, ConnectedList, DelimitedList,
|
||||||
|
};
|
||||||
|
|
||||||
/// Represents a declaration in the syntax tree.
|
/// Represents a declaration in the syntax tree.
|
||||||
///
|
///
|
||||||
|
@ -33,6 +36,8 @@ use super::{statement::Block, Annotation, ConnectedList, DelimitedList};
|
||||||
/// Declaration:
|
/// Declaration:
|
||||||
/// Function
|
/// Function
|
||||||
/// | Import
|
/// | Import
|
||||||
|
/// | Tag
|
||||||
|
/// | (VariableDeclaration ';')
|
||||||
/// ;
|
/// ;
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
@ -41,6 +46,7 @@ pub enum Declaration {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
Import(Import),
|
Import(Import),
|
||||||
Tag(Tag),
|
Tag(Tag),
|
||||||
|
GlobalVariable((VariableDeclaration, Punctuation)),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceElement for Declaration {
|
impl SourceElement for Declaration {
|
||||||
|
@ -49,6 +55,10 @@ impl SourceElement for Declaration {
|
||||||
Self::Function(function) => function.span(),
|
Self::Function(function) => function.span(),
|
||||||
Self::Import(import) => import.span(),
|
Self::Import(import) => import.span(),
|
||||||
Self::Tag(tag) => tag.span(),
|
Self::Tag(tag) => tag.span(),
|
||||||
|
Self::GlobalVariable((variable, semicolon)) => variable
|
||||||
|
.span()
|
||||||
|
.join(&semicolon.span)
|
||||||
|
.expect("invalid declaration span"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,13 +69,17 @@ impl Declaration {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// - if the annotation is invalid for the target declaration.
|
/// - if the annotation is invalid for the target declaration.
|
||||||
pub fn with_annotation(self, annotation: Annotation) -> ParseResult<Self> {
|
pub fn with_annotation(self, annotation: Annotation) -> ParseResult<Self> {
|
||||||
#[expect(clippy::single_match_else)]
|
|
||||||
match self {
|
match self {
|
||||||
Self::Function(mut function) => {
|
Self::Function(mut function) => {
|
||||||
function.annotations.push_front(annotation);
|
function.annotations.push_front(annotation);
|
||||||
|
|
||||||
Ok(Self::Function(function))
|
Ok(Self::Function(function))
|
||||||
}
|
}
|
||||||
|
Self::GlobalVariable((var, semi)) => {
|
||||||
|
let var_with_annotation = var.with_annotation(annotation)?;
|
||||||
|
|
||||||
|
Ok(Self::GlobalVariable((var_with_annotation, semi)))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let err = Error::InvalidAnnotation(InvalidAnnotation {
|
let err = Error::InvalidAnnotation(InvalidAnnotation {
|
||||||
annotation: annotation.assignment.identifier.span,
|
annotation: annotation.assignment.identifier.span,
|
||||||
|
@ -457,6 +471,18 @@ impl Parser<'_> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reading::Atomic(Token::Keyword(keyword))
|
||||||
|
if matches!(
|
||||||
|
keyword.keyword,
|
||||||
|
KeywordKind::Int | KeywordKind::Bool | KeywordKind::Val
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
let var = self.parse_variable_declaration(handler)?;
|
||||||
|
let semi = self.parse_punctuation(';', true, handler)?;
|
||||||
|
|
||||||
|
Ok(Declaration::GlobalVariable((var, semi)))
|
||||||
|
}
|
||||||
|
|
||||||
unexpected => {
|
unexpected => {
|
||||||
// make progress
|
// make progress
|
||||||
self.forward();
|
self.forward();
|
||||||
|
|
|
@ -358,11 +358,12 @@ impl Primary {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|var| match var.as_ref() {
|
|var| match var.as_ref() {
|
||||||
VariableData::ComptimeValue { value } => {
|
VariableData::ComptimeValue {
|
||||||
value.read().unwrap().clone().ok_or_else(|| NotComptime {
|
value,
|
||||||
|
read_only: _,
|
||||||
|
} => value.read().unwrap().clone().ok_or_else(|| NotComptime {
|
||||||
expression: ident.span.clone(),
|
expression: ident.span.clone(),
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
_ => Err(NotComptime {
|
_ => Err(NotComptime {
|
||||||
expression: self.span(),
|
expression: self.span(),
|
||||||
}),
|
}),
|
||||||
|
@ -1276,6 +1277,7 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::too_many_lines)]
|
||||||
fn transpile_scoreboard_operation(
|
fn transpile_scoreboard_operation(
|
||||||
&mut self,
|
&mut self,
|
||||||
binary: &Binary,
|
binary: &Binary,
|
||||||
|
@ -1303,6 +1305,15 @@ impl Transpiler {
|
||||||
scope,
|
scope,
|
||||||
handler,
|
handler,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let (right_cmds, rhs_score) =
|
||||||
|
if let Ok(ComptimeValue::Integer(int)) = right.comptime_eval(scope, handler) {
|
||||||
|
self.initialize_constant_score(int);
|
||||||
|
(
|
||||||
|
Vec::new(),
|
||||||
|
("shu_constants", std::borrow::Cow::Owned(int.to_string())),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
let right_cmds = self.transpile_expression(
|
let right_cmds = self.transpile_expression(
|
||||||
right,
|
right,
|
||||||
&DataLocation::ScoreboardValue {
|
&DataLocation::ScoreboardValue {
|
||||||
|
@ -1313,10 +1324,19 @@ impl Transpiler {
|
||||||
handler,
|
handler,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
(
|
||||||
|
right_cmds,
|
||||||
|
(
|
||||||
|
temp_objective.as_str(),
|
||||||
|
std::borrow::Cow::Borrowed(&temp_locations[1]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let calc_cmds = {
|
let calc_cmds = {
|
||||||
let (target_objective, target) = score_target_location;
|
let (target_objective, target) = score_target_location;
|
||||||
let source = &temp_locations[1];
|
let source = rhs_score.1.as_ref();
|
||||||
let source_objective = &temp_objective;
|
let source_objective = rhs_score.0;
|
||||||
|
|
||||||
let operation = match operator {
|
let operation = match operator {
|
||||||
BinaryOperator::Add(_) => "+=",
|
BinaryOperator::Add(_) => "+=",
|
||||||
|
|
|
@ -266,7 +266,10 @@ mod enabled {
|
||||||
.map_err(|err| LuaRuntimeError::from_lua_err(&err, self.span()))?;
|
.map_err(|err| LuaRuntimeError::from_lua_err(&err, self.span()))?;
|
||||||
Value::Table(table)
|
Value::Table(table)
|
||||||
}
|
}
|
||||||
Some(VariableData::ComptimeValue { value }) => {
|
Some(VariableData::ComptimeValue {
|
||||||
|
value,
|
||||||
|
read_only: _,
|
||||||
|
}) => {
|
||||||
let value = value.read().unwrap();
|
let value = value.read().unwrap();
|
||||||
match &*value {
|
match &*value {
|
||||||
Some(ComptimeValue::Boolean(b)) => Value::Boolean(*b),
|
Some(ComptimeValue::Boolean(b)) => Value::Boolean(*b),
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl Transpiler {
|
||||||
.entry(program_identifier)
|
.entry(program_identifier)
|
||||||
.or_insert_with(Scope::with_internal_functions)
|
.or_insert_with(Scope::with_internal_functions)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
self.transpile_program_declarations(program, &scope, handler);
|
self.transpile_program_declarations(program, &scope, handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut always_transpile_functions = Vec::new();
|
let mut always_transpile_functions = Vec::new();
|
||||||
|
@ -143,12 +143,14 @@ impl Transpiler {
|
||||||
program: &ProgramFile,
|
program: &ProgramFile,
|
||||||
scope: &Arc<Scope>,
|
scope: &Arc<Scope>,
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) {
|
) -> TranspileResult<()> {
|
||||||
let namespace = program.namespace();
|
let namespace = program.namespace();
|
||||||
|
|
||||||
for declaration in program.declarations() {
|
for declaration in program.declarations() {
|
||||||
self.transpile_declaration(declaration, namespace, scope, handler);
|
self.transpile_declaration(declaration, namespace, scope, handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transpiles the given declaration.
|
/// Transpiles the given declaration.
|
||||||
|
@ -159,7 +161,7 @@ impl Transpiler {
|
||||||
namespace: &Namespace,
|
namespace: &Namespace,
|
||||||
scope: &Arc<Scope>,
|
scope: &Arc<Scope>,
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) {
|
) -> TranspileResult<()> {
|
||||||
let program_identifier = declaration.span().source_file().identifier().clone();
|
let program_identifier = declaration.span().source_file().identifier().clone();
|
||||||
match declaration {
|
match declaration {
|
||||||
Declaration::Function(function) => {
|
Declaration::Function(function) => {
|
||||||
|
@ -241,9 +243,21 @@ impl Transpiler {
|
||||||
if tag.replace().is_some() {
|
if tag.replace().is_some() {
|
||||||
sb_tag.set_replace(true);
|
sb_tag.set_replace(true);
|
||||||
}
|
}
|
||||||
// TODO: handle global variables
|
}
|
||||||
|
Declaration::GlobalVariable((declaration, _)) => {
|
||||||
|
let setup_variable_cmds = self.transpile_variable_declaration(
|
||||||
|
declaration,
|
||||||
|
true,
|
||||||
|
&program_identifier,
|
||||||
|
scope,
|
||||||
|
handler,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.setup_cmds.extend(setup_variable_cmds);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn transpile_statement(
|
pub(super) fn transpile_statement(
|
||||||
|
@ -317,9 +331,14 @@ impl Transpiler {
|
||||||
Err(error)
|
Err(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SemicolonStatement::VariableDeclaration(decl) => {
|
SemicolonStatement::VariableDeclaration(decl) => self
|
||||||
self.transpile_variable_declaration(decl, program_identifier, scope, handler)
|
.transpile_variable_declaration(
|
||||||
}
|
decl,
|
||||||
|
false,
|
||||||
|
program_identifier,
|
||||||
|
scope,
|
||||||
|
handler,
|
||||||
|
),
|
||||||
SemicolonStatement::Assignment(assignment) => self.transpile_assignment(
|
SemicolonStatement::Assignment(assignment) => self.transpile_assignment(
|
||||||
TranspileAssignmentTarget::from(assignment.destination()),
|
TranspileAssignmentTarget::from(assignment.destination()),
|
||||||
assignment.expression(),
|
assignment.expression(),
|
||||||
|
@ -344,8 +363,10 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
Expression::Primary(Primary::Identifier(ident)) => {
|
Expression::Primary(Primary::Identifier(ident)) => {
|
||||||
match scope.get_variable(ident.span.str()).as_deref() {
|
match scope.get_variable(ident.span.str()).as_deref() {
|
||||||
Some(VariableData::ComptimeValue { value }) => {
|
Some(VariableData::ComptimeValue {
|
||||||
value.read().unwrap().as_ref().map_or_else(
|
value,
|
||||||
|
read_only: _,
|
||||||
|
}) => value.read().unwrap().as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let error = TranspileError::MissingValue(MissingValue {
|
let error = TranspileError::MissingValue(MissingValue {
|
||||||
expression: ident.span.clone(),
|
expression: ident.span.clone(),
|
||||||
|
@ -360,8 +381,7 @@ impl Transpiler {
|
||||||
);
|
);
|
||||||
Ok(vec![cmd])
|
Ok(vec![cmd])
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
}
|
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
|
||||||
expression.clone(),
|
expression.clone(),
|
||||||
|
|
|
@ -104,6 +104,8 @@ pub enum VariableData {
|
||||||
ComptimeValue {
|
ComptimeValue {
|
||||||
/// The value.
|
/// The value.
|
||||||
value: Arc<RwLock<Option<ComptimeValue>>>,
|
value: Arc<RwLock<Option<ComptimeValue>>>,
|
||||||
|
/// Whether the value is read-only.
|
||||||
|
read_only: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +260,7 @@ impl Transpiler {
|
||||||
pub(super) fn transpile_variable_declaration(
|
pub(super) fn transpile_variable_declaration(
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration: &VariableDeclaration,
|
declaration: &VariableDeclaration,
|
||||||
|
is_global: bool,
|
||||||
program_identifier: &str,
|
program_identifier: &str,
|
||||||
scope: &Arc<Scope>,
|
scope: &Arc<Scope>,
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
|
@ -265,6 +268,7 @@ impl Transpiler {
|
||||||
match declaration {
|
match declaration {
|
||||||
VariableDeclaration::Single(declaration) => self.transpile_single_variable_declaration(
|
VariableDeclaration::Single(declaration) => self.transpile_single_variable_declaration(
|
||||||
declaration,
|
declaration,
|
||||||
|
is_global,
|
||||||
program_identifier,
|
program_identifier,
|
||||||
scope,
|
scope,
|
||||||
handler,
|
handler,
|
||||||
|
@ -277,6 +281,7 @@ impl Transpiler {
|
||||||
),
|
),
|
||||||
VariableDeclaration::Array(declaration) => self.transpile_array_variable_declaration(
|
VariableDeclaration::Array(declaration) => self.transpile_array_variable_declaration(
|
||||||
declaration,
|
declaration,
|
||||||
|
is_global,
|
||||||
program_identifier,
|
program_identifier,
|
||||||
scope,
|
scope,
|
||||||
handler,
|
handler,
|
||||||
|
@ -307,6 +312,7 @@ impl Transpiler {
|
||||||
declaration.identifier().span.str(),
|
declaration.identifier().span.str(),
|
||||||
VariableData::ComptimeValue {
|
VariableData::ComptimeValue {
|
||||||
value: Arc::new(RwLock::new(value)),
|
value: Arc::new(RwLock::new(value)),
|
||||||
|
read_only: is_global,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -318,6 +324,7 @@ impl Transpiler {
|
||||||
fn transpile_single_variable_declaration(
|
fn transpile_single_variable_declaration(
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration: &SingleVariableDeclaration,
|
declaration: &SingleVariableDeclaration,
|
||||||
|
is_global: bool,
|
||||||
program_identifier: &str,
|
program_identifier: &str,
|
||||||
scope: &Arc<Scope>,
|
scope: &Arc<Scope>,
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
|
@ -342,7 +349,7 @@ impl Transpiler {
|
||||||
declaration.identifier().span.str(),
|
declaration.identifier().span.str(),
|
||||||
VariableData::ScoreboardValue {
|
VariableData::ScoreboardValue {
|
||||||
objective: name.clone(),
|
objective: name.clone(),
|
||||||
target,
|
target: target.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -350,25 +357,49 @@ impl Transpiler {
|
||||||
scope.set_variable(
|
scope.set_variable(
|
||||||
declaration.identifier().span.str(),
|
declaration.identifier().span.str(),
|
||||||
VariableData::BooleanStorage {
|
VariableData::BooleanStorage {
|
||||||
storage_name: name,
|
storage_name: name.clone(),
|
||||||
path: target,
|
path: target.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => unreachable!("no other variable types"),
|
_ => unreachable!("no other variable types"),
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration.assignment().as_ref().map_or_else(
|
if let Some(assignment) = declaration.assignment().as_ref() {
|
||||||
|| Ok(Vec::new()),
|
let cmds = self.transpile_assignment(
|
||||||
|assignment| {
|
|
||||||
self.transpile_assignment(
|
|
||||||
TranspileAssignmentTarget::Identifier(declaration.identifier()),
|
TranspileAssignmentTarget::Identifier(declaration.identifier()),
|
||||||
assignment.expression(),
|
assignment.expression(),
|
||||||
scope,
|
scope,
|
||||||
handler,
|
handler,
|
||||||
)
|
)?;
|
||||||
},
|
if is_global {
|
||||||
)
|
let (temp_objective, temp_targets) = self.get_temp_scoreboard_locations(1);
|
||||||
|
let temp_target = &temp_targets[0];
|
||||||
|
let test_cmd = match declaration.variable_type().keyword {
|
||||||
|
KeywordKind::Int => {
|
||||||
|
Command::Raw(format!("scoreboard players get {name} {target}"))
|
||||||
|
}
|
||||||
|
KeywordKind::Bool => Command::Raw(format!("data get storage {name} {target}")),
|
||||||
|
_ => unreachable!("no other variable types"),
|
||||||
|
};
|
||||||
|
let test_exists_cmd = Command::Execute(Execute::Store(
|
||||||
|
format!("success score {temp_target} {temp_objective}").into(),
|
||||||
|
Box::new(Execute::Run(Box::new(test_cmd))),
|
||||||
|
));
|
||||||
|
let cond_cmd = Command::Execute(Execute::If(
|
||||||
|
Condition::Atom(
|
||||||
|
format!("score {temp_target} {temp_objective} matches 0").into(),
|
||||||
|
),
|
||||||
|
Box::new(Execute::Run(Box::new(Command::Group(cmds)))),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
Ok(vec![test_exists_cmd, cond_cmd])
|
||||||
|
} else {
|
||||||
|
Ok(cmds)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile_score_variable_declaration(
|
fn transpile_score_variable_declaration(
|
||||||
|
@ -411,6 +442,7 @@ impl Transpiler {
|
||||||
fn transpile_array_variable_declaration(
|
fn transpile_array_variable_declaration(
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration: &ArrayVariableDeclaration,
|
declaration: &ArrayVariableDeclaration,
|
||||||
|
_is_global: bool,
|
||||||
program_identifier: &str,
|
program_identifier: &str,
|
||||||
scope: &Arc<Scope>,
|
scope: &Arc<Scope>,
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
|
@ -450,6 +482,7 @@ impl Transpiler {
|
||||||
declaration.assignment().as_ref().map_or_else(
|
declaration.assignment().as_ref().map_or_else(
|
||||||
|| Ok(Vec::new()),
|
|| Ok(Vec::new()),
|
||||||
|assignment| {
|
|assignment| {
|
||||||
|
// TODO: implement global already exists check when array assignments are implemented
|
||||||
self.transpile_assignment(
|
self.transpile_assignment(
|
||||||
TranspileAssignmentTarget::Identifier(declaration.identifier()),
|
TranspileAssignmentTarget::Identifier(declaration.identifier()),
|
||||||
assignment.expression(),
|
assignment.expression(),
|
||||||
|
@ -692,7 +725,15 @@ impl Transpiler {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
VariableData::ComptimeValue { value } => {
|
VariableData::ComptimeValue { value, read_only } => {
|
||||||
|
if *read_only {
|
||||||
|
let err = TranspileError::AssignmentError(AssignmentError {
|
||||||
|
identifier: identifier.span(),
|
||||||
|
message: "Cannot assign to a read-only value.".to_string(),
|
||||||
|
});
|
||||||
|
handler.receive(err.clone());
|
||||||
|
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);
|
||||||
|
@ -1097,9 +1138,14 @@ impl Transpiler {
|
||||||
DataLocation::Storage {
|
DataLocation::Storage {
|
||||||
storage_name: target_storage_name,
|
storage_name: target_storage_name,
|
||||||
path: target_path,
|
path: target_path,
|
||||||
r#type,
|
r#type: target_type,
|
||||||
} => {
|
} => {
|
||||||
if matches!(r#type, StorageType::Boolean) {
|
if storage_name == target_storage_name
|
||||||
|
&& path == target_path
|
||||||
|
&& r#type == target_type
|
||||||
|
{
|
||||||
|
Ok(Vec::new())
|
||||||
|
} else if matches!(target_type, StorageType::Boolean) {
|
||||||
let cmd = Command::Raw(format!(
|
let cmd = Command::Raw(format!(
|
||||||
"data modify storage {target_storage_name} {target_path} set from storage {storage_name} {path}"
|
"data modify storage {target_storage_name} {target_path} set from storage {storage_name} {path}"
|
||||||
));
|
));
|
||||||
|
@ -1123,11 +1169,15 @@ impl Transpiler {
|
||||||
objective: target_objective,
|
objective: target_objective,
|
||||||
target: target_target,
|
target: target_target,
|
||||||
} => {
|
} => {
|
||||||
|
if objective == target_objective && score_target == target_target {
|
||||||
|
Ok(Vec::new())
|
||||||
|
} else {
|
||||||
let cmd = Command::Raw(format!(
|
let cmd = Command::Raw(format!(
|
||||||
"scoreboard players operation {target_target} {target_objective} = {score_target} {objective}"
|
"scoreboard players operation {target_target} {target_objective} = {score_target} {objective}"
|
||||||
));
|
));
|
||||||
Ok(vec![cmd])
|
Ok(vec![cmd])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
DataLocation::Storage {
|
DataLocation::Storage {
|
||||||
storage_name,
|
storage_name,
|
||||||
path,
|
path,
|
||||||
|
|
Loading…
Reference in New Issue