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