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_expression.validate(context)?;
self.if_block.node.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)?; let if_expression_type = self.if_expression.expected_type(context)?;
if let Type::Boolean = if_expression_type { if let Type::Boolean = if_expression_type {
if let Some(else_block) = &self.else_block { if let Some(else_block) = &self.else_block {
else_block.node.validate(context)?; else_block.node.validate(context)?;
let expected = self.if_block.node.expected_type(context)?;
let actual = else_block.node.expected_type(context)?; let actual = else_block.node.expected_type(context)?;
expected expected_type
.check(&actual) .check(&actual)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
@ -56,14 +56,37 @@ impl AbstractNode for IfElse {
expected_position: self.if_expression.position(), expected_position: self.if_expression.position(),
})?; })?;
} }
Ok(())
} else { } else {
Err(ValidationError::ExpectedBoolean { return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type, actual: if_expression_type,
position: self.if_expression.position(), 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> { 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 let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean { if *if_boolean {
self.if_block.node.run(context) self.if_block.node.run(context)
} else if let Some(else_statement) = self.else_block {
else_statement.node.run(context)
} else { } 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 { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(

View File

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

View File

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

View File

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