1
0

Make fizzbuzz example work

This commit is contained in:
Jeff 2024-03-25 01:56:06 -04:00
parent f1f4d48d3a
commit e728aa8fbb
4 changed files with 72 additions and 24 deletions

View File

@ -39,16 +39,16 @@ impl AbstractNode for IfElse {
self.if_expression.validate(context)?;
self.if_block.node.validate(context)?;
let expected_type = self.if_block.node.expected_type(context)?;
let if_expression_type = self.if_expression.expected_type(context)?;
if let Type::Boolean = if_expression_type {
if let Some(else_block) = &self.else_block {
else_block.node.validate(context)?;
let expected = self.if_block.node.expected_type(context)?;
let actual = else_block.node.expected_type(context)?;
expected
expected_type
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
@ -56,14 +56,37 @@ impl AbstractNode for IfElse {
expected_position: self.if_expression.position(),
})?;
}
Ok(())
} else {
Err(ValidationError::ExpectedBoolean {
return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type,
position: self.if_expression.position(),
})
});
}
for (expression, block) in &self.else_ifs {
let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type {
block.node.validate(context)?;
let actual = block.node.expected_type(context)?;
expected_type
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
expected_position: self.if_expression.position(),
})?;
} else {
return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type,
position: self.if_expression.position(),
});
}
}
Ok(())
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
@ -80,10 +103,37 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean {
self.if_block.node.run(context)
} else if let Some(else_statement) = self.else_block {
else_statement.node.run(context)
} else {
Ok(Action::None)
for (expression, block) in self.else_ifs {
let expression_position = expression.position();
let action = expression.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
if *else_if_boolean {
return block.node.run(context);
}
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedBoolean {
actual: value.r#type(context)?,
position: expression_position,
},
));
}
}
if let Some(else_statement) = self.else_block {
else_statement.node.run(context)
} else {
Ok(Action::None)
}
}
} else {
Err(RuntimeError::ValidationFailure(

View File

@ -40,7 +40,7 @@ impl AbstractNode for While {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> {
let expression_position = self.expression.position();
let action = self.expression.run(_context)?;
let action = self.expression.clone().run(_context)?;
if let Action::Return(value) = action {
Ok(value)
@ -51,16 +51,14 @@ impl AbstractNode for While {
}
};
if let ValueInner::Boolean(boolean) = get_boolean()?.inner().as_ref() {
while *boolean {
for statement in &self.statements {
let action = statement.clone().run(_context)?;
while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() {
for statement in &self.statements {
let action = statement.clone().run(_context)?;
match action {
Action::Return(_) => {}
Action::None => {}
Action::Break => return Ok(Action::Break),
}
match action {
Action::Return(_) => {}
Action::None => {}
Action::Break => return Ok(Action::Break),
}
}
}

View File

@ -5,13 +5,13 @@ while count <= 15 {
divides_by_5 = count % 5 == 0
if divides_by_3 && divides_by_5 {
output('fizzbuzz')
io.write_line('fizzbuzz')
} else if divides_by_3 {
output('fizz')
io.write_line('fizz')
} else if divides_by_5 {
output('buzz')
io.write_line('buzz')
} else {
output(count)
io.write_line(count)
}
count += 1

View File

@ -3,7 +3,7 @@ io = {
__READ_LINE__()
}
write_line = (output: str) none {
write_line = (output: any) none {
__WRITE_LINE__(output)
}
}