diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 2265715..b43323f 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -155,7 +155,10 @@ pub struct UsedScoreboard { impl UsedScoreboard { pub fn new_dummy(name: EcoString) -> UsedScoreboard { - UsedScoreboard{name, criteria: "dummy".into()} + UsedScoreboard { + name, + criteria: "dummy".into(), + } } } @@ -198,16 +201,21 @@ impl Compiler { } fn use_scoreboard(&mut self, name: EcoString, criteria: EcoString) { - let exists = self.used_scoreboards.insert(UsedScoreboard{name: name.clone(), criteria: criteria.clone()}); + let exists = self.used_scoreboards.insert(UsedScoreboard { + name: name.clone(), + criteria: criteria.clone(), + }); if criteria != "dummy" && !exists { - let scoreboard = UsedScoreboard{name, criteria}; + let scoreboard = UsedScoreboard { name, criteria }; self.used_scoreboards.remove(&scoreboard); self.used_scoreboards.insert(scoreboard); } } fn use_scoreboard_dummy(&mut self, name: EcoString) { - self.used_scoreboards.insert(UsedScoreboard::new_dummy(name)); + self + .used_scoreboards + .insert(UsedScoreboard::new_dummy(name)); } fn lookup_resource(&self, resource: &ZoglinResource, comptime: bool) -> Option { @@ -446,8 +454,13 @@ impl Compiler { name: "load".to_eco_string(), commands: take(&mut self.used_scoreboards) .into_iter() - .map(|scoreboard| - eco_format!("scoreboard objectives add {} {}", scoreboard.name, scoreboard.criteria)) + .map(|scoreboard| { + eco_format!( + "scoreboard objectives add {} {}", + scoreboard.name, + scoreboard.criteria + ) + }) .collect(), location: Location::blank(), }); @@ -835,7 +848,21 @@ impl Compiler { context: &mut FunctionContext, ) -> Result<(EcoString, bool)> { match expr { - StaticExpr::FunctionCall(call) => Ok((self.compile_function_call(call, context)?.0, false)), + StaticExpr::FunctionCall(call) => { + if call.comptime { + let value = self + .compile_comptime_call(call, context)? + .kind + .to_comptime_string(true) + .ok_or(raise_floating_error( + // TODO: Add location + "This value cannot be statically resolved.", + ))?; + Ok((value, false)) + } else { + Ok((self.compile_function_call(call, context)?.0, false)) + } + } StaticExpr::FunctionRef { path } => Ok(( if let Some(path) = path { self @@ -920,15 +947,12 @@ impl Compiler { match parameter.kind { ParameterKind::Storage => { let storage = StorageLocation::new(parameter_storage.clone(), parameter.name); - self.set_storage( - &mut context.code, - &storage, - &argument, - )?; + self.set_storage(&mut context.code, &storage, &argument)?; } ParameterKind::Scoreboard => { let scoreboard = ScoreboardLocation::new( - parameter_storage.clone(), &eco_format!("${}", ¶meter.name) + parameter_storage.clone(), + &eco_format!("${}", ¶meter.name), ); self.set_scoreboard(&mut context.code, &scoreboard, &argument)?; } @@ -937,11 +961,7 @@ impl Compiler { parameter_storage.clone(), eco_format!("__{}", parameter.name), ); - self.set_storage( - &mut context.code, - &storage, - &argument, - )?; + self.set_storage(&mut context.code, &storage, &argument)?; } ParameterKind::CompileTime => todo!(), } @@ -1178,11 +1198,7 @@ impl Compiler { ReturnType::Storage => { let return_storage = StorageLocation::new(context.location.clone(), "return".to_eco_string()); - self.set_storage( - &mut context.code, - &return_storage, - &expression, - )?; + self.set_storage(&mut context.code, &return_storage, &expression)?; } ReturnType::Scoreboard => { let scoreboard = ScoreboardLocation::new(context.location.clone(), "$return"); diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 7694b5b..2e6d0ff 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -431,11 +431,7 @@ impl Lexer { match entry { Ok(path) => { let path_str = path.to_str().expect("Path should be valid"); - if let Some(index) = self - .include_chain - .iter() - .position(|file| path_str == file) - { + if let Some(index) = self.include_chain.iter().position(|file| path_str == file) { if index != (self.include_chain.len() - 1) { raise_warning( token.location.clone(), @@ -468,42 +464,86 @@ impl Lexer { let mut column = self.column; while !self.current_is_delim() { - if self.current() == '\\' && self.peek(1) == '&' { - self.consume(); - current_part.push(self.current()); - self.consume(); - continue; - } - - if self.current() == '&' && self.peek(1) == '{' { - tokens.push(Token { - kind: TokenKind::CommandString, - value: None, - raw: current_part, - location: self.location(line, column), - }); - current_part = EcoString::new(); - - self.consume(); - self.consume(); - let mut brace_level = 0; - while self.current() != '}' || brace_level > 0 { - let next = self.next_token()?; - if next.kind == TokenKind::LeftBrace { - brace_level += 1; - } else if next.kind == TokenKind::RightBrace { - brace_level -= 1; + match (self.current(), self.peek(1)) { + ('\\', '\\' | '&' | '%') => { + self.consume(); + current_part.push(self.current()); + self.consume(); + } + ('&', '{') => { + tokens.push(Token { + kind: TokenKind::CommandString, + value: None, + raw: current_part, + location: self.location(line, column), + }); + current_part = EcoString::new(); + + self.consume(); + self.consume(); + let mut brace_level = 0; + while self.current() != '}' || brace_level > 0 { + let next = self.next_token()?; + if next.kind == TokenKind::LeftBrace { + brace_level += 1; + } else if next.kind == TokenKind::RightBrace { + brace_level -= 1; + } + tokens.push(next); } - tokens.push(next); + self.consume(); + + line = self.line; + column = self.column; } - self.consume(); + ('&', next) if valid_identifier_start(next) => { + tokens.push(Token { + kind: TokenKind::CommandString, + value: None, + raw: current_part, + location: self.location(line, column), + }); + current_part = EcoString::new(); + + tokens.push(self.next_token()?); + tokens.push(self.next_token()?); + + if self.current() == '(' { + tokens.push(self.next_token()?); + let mut bracket_level = 1; + while bracket_level > 0 { + let next = self.next_token()?; + if next.kind == TokenKind::LeftParen { + bracket_level += 1; + } else if next.kind == TokenKind::RightParen { + bracket_level -= 1; + } + tokens.push(next); + } + } - line = self.line; - column = self.column; - continue; + line = self.line; + column = self.column; + } + ('%', next) if valid_identifier_start(next) => { + tokens.push(Token { + kind: TokenKind::CommandString, + value: None, + raw: current_part, + location: self.location(line, column), + }); + current_part = EcoString::new(); + + tokens.push(self.next_token()?); + tokens.push(self.next_token()?); + + line = self.line; + column = self.column; + } + _ => { + current_part.push(self.consume()); + } } - - current_part.push(self.consume()); } tokens.push(Token { diff --git a/test-project/main.zog b/test-project/main.zog index 5f5e34f..11c4e24 100644 --- a/test-project/main.zog +++ b/test-project/main.zog @@ -1,8 +1,12 @@ namespace example -fn load() { - foo = 1 - $bar = 2b - a = {a: 1, b: 2, c: foo} - b = [L; 1L, 2L, 3L, $bar] +fn &foo(something) { + return &something +} + +fn load(%text) { + &value = 10 + data modify storage example:load something set value &value + scoreboard players set @s example.load &foo(12) + tellraw @a "%text" }