Make fizzbuzz example work
This commit is contained in:
parent
f1f4d48d3a
commit
e728aa8fbb
@ -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,11 +103,38 @@ 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 {
|
||||||
|
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_statement.node.run(context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedBoolean {
|
ValidationError::ExpectedBoolean {
|
||||||
|
@ -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,8 +51,7 @@ 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)?;
|
||||||
|
|
||||||
@ -63,7 +62,6 @@ impl AbstractNode for While {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user