diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 5597a7c..3d5ed4d 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -15,6 +15,10 @@ impl Block { Self { statements } } + pub fn first_statement(&self) -> &Statement { + self.statements.first().unwrap() + } + pub fn last_statement(&self) -> &Statement { self.statements.last().unwrap() } diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index bae77b2..0c75aa9 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -52,8 +52,8 @@ impl AbstractNode for IfElse { .check(&actual) .map_err(|conflict| ValidationError::TypeCheck { conflict, - actual_position: self.if_block.item.last_statement().position(), - expected_position: self.if_expression.position(), + actual_position: else_block.item.last_statement().position(), + expected_position: self.if_block.item.first_statement().position(), })?; } } else { @@ -89,9 +89,9 @@ impl AbstractNode for IfElse { Ok(()) } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { let if_position = self.if_expression.position(); - let action = self.if_expression.run(context, _clear_variables)?; + let action = self.if_expression.run(context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { @@ -102,11 +102,11 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if *if_boolean { - self.if_block.item.run(context, _clear_variables) + self.if_block.item.run(context, _manage_memory) } else { for (expression, block) in self.else_ifs { let expression_position = expression.position(); - let action = expression.run(context, _clear_variables)?; + let action = expression.run(context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { @@ -117,7 +117,7 @@ impl AbstractNode for IfElse { if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() { if *else_if_boolean { - return block.item.run(context, _clear_variables); + return block.item.run(context, _manage_memory); } } else { return Err(RuntimeError::ValidationFailure( @@ -130,7 +130,7 @@ impl AbstractNode for IfElse { } if let Some(else_statement) = self.else_block { - else_statement.item.run(context, _clear_variables) + else_statement.item.run(context, _manage_memory) } else { Ok(Action::None) } diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index 7a42c31..1f9a3e5 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -32,10 +32,10 @@ impl AbstractNode for While { _context: &mut Context, _manage_memory: bool, ) -> Result<(), ValidationError> { - self.expression.validate(_context, _manage_memory)?; + self.expression.validate(_context, false)?; for statement in &self.statements { - statement.validate(_context, _manage_memory)?; + statement.validate(_context, false)?; } Ok(()) @@ -44,10 +44,7 @@ impl AbstractNode for While { fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { let get_boolean = || -> Result { let expression_position = self.expression.position(); - let action = self - .expression - .clone() - .run(&mut _context.clone(), _manage_memory)?; + let action = self.expression.clone().run(&mut _context.clone(), false)?; if let Action::Return(value) = action { Ok(value) @@ -60,9 +57,7 @@ impl AbstractNode for While { while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() { for statement in &self.statements { - let action = statement - .clone() - .run(&mut _context.clone(), _manage_memory)?; + let action = statement.clone().run(&mut _context.clone(), false)?; match action { Action::Return(_) => {} diff --git a/dust-lang/src/lexer.rs b/dust-lang/src/lexer.rs index 2de60f0..2ecbd75 100644 --- a/dust-lang/src/lexer.rs +++ b/dust-lang/src/lexer.rs @@ -254,7 +254,30 @@ pub fn lexer<'src>() -> impl Parser< delimited_string('`'), )); - let identifier = text::ident().map(|text: &str| Token::Identifier(text)); + let identifier_and_keyword = text::ident().map(|text: &str| match text { + "any" => Token::Keyword(Keyword::Any), + "async" => Token::Keyword(Keyword::Async), + "bool" => Token::Keyword(Keyword::Bool), + "break" => Token::Keyword(Keyword::Break), + "else" => Token::Keyword(Keyword::Else), + "float" => Token::Keyword(Keyword::Float), + "fn" => Token::Keyword(Keyword::Fn), + "int" => Token::Keyword(Keyword::Int), + "if" => Token::Keyword(Keyword::If), + "list" => Token::Keyword(Keyword::List), + "map" => Token::Keyword(Keyword::Map), + "none" => Token::Keyword(Keyword::None), + "range" => Token::Keyword(Keyword::Range), + "struct" => Token::Keyword(Keyword::Struct), + "str" => Token::Keyword(Keyword::Str), + "type" => Token::Keyword(Keyword::Type), + "loop" => Token::Keyword(Keyword::Loop), + "while" => Token::Keyword(Keyword::While), + "READ_LINE" => Token::Keyword(Keyword::ReadLine), + "SLEEP" => Token::Keyword(Keyword::Sleep), + "WRITE_LINE" => Token::Keyword(Keyword::WriteLine), + _ => Token::Identifier(text), + }); let operator = choice(( // logic @@ -302,31 +325,6 @@ pub fn lexer<'src>() -> impl Parser< )) .map(Token::Control); - let keyword = choice(( - just("any").to(Keyword::Any), - just("async").to(Keyword::Async), - just("bool").to(Keyword::Bool), - just("break").to(Keyword::Break), - just("else").to(Keyword::Else), - just("float").to(Keyword::Float), - just("fn").to(Keyword::Fn), - just("int").to(Keyword::Int), - just("if").to(Keyword::If), - just("list").to(Keyword::List), - just("map").to(Keyword::Map), - just("none").to(Keyword::None), - just("range").to(Keyword::Range), - just("struct").to(Keyword::Struct), - just("str").to(Keyword::Str), - just("type").to(Keyword::Type), - just("loop").to(Keyword::Loop), - just("while").to(Keyword::While), - just("READ_LINE").to(Keyword::ReadLine), - just("SLEEP").to(Keyword::Sleep), - just("WRITE_LINE").to(Keyword::WriteLine), - )) - .map(Token::Keyword); - choice(( line_comment, multi_line_comment, @@ -334,8 +332,7 @@ pub fn lexer<'src>() -> impl Parser< float, integer, string, - keyword, - identifier, + identifier_and_keyword, control, operator, )) diff --git a/examples/fizzbuzz.ds b/examples/fizzbuzz.ds index 37b4017..cb79d50 100644 --- a/examples/fizzbuzz.ds +++ b/examples/fizzbuzz.ds @@ -4,15 +4,17 @@ while count <= 15 { divides_by_3 = count % 3 == 0 divides_by_5 = count % 5 == 0 - if divides_by_3 && divides_by_5 { - io.write_line('fizzbuzz') + output = if divides_by_3 && divides_by_5 { + 'fizzbuzz' } else if divides_by_3 { - io.write_line('fizz') + 'fizz' } else if divides_by_5 { - io.write_line('buzz') - } else { - io.write_line(count) + 'buzz' + } else { + string.new(count) } + + io.write_line(output) count += 1 }