Improve type inference
This commit is contained in:
parent
0de25215b8
commit
fecc62811d
@ -52,8 +52,13 @@ impl Evaluate for Assignment {
|
||||
));
|
||||
}
|
||||
|
||||
let statement = self
|
||||
.statement
|
||||
.last_child_statement()
|
||||
.unwrap_or(&self.statement);
|
||||
|
||||
if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) =
|
||||
(&self.constructor, self.statement.as_ref())
|
||||
(&self.constructor, statement)
|
||||
{
|
||||
let declared_type = constructor.clone().construct(context)?;
|
||||
let function_type = function_call.node.function().expected_type(context)?;
|
||||
@ -79,18 +84,6 @@ impl Evaluate for Assignment {
|
||||
position: function_call.position,
|
||||
});
|
||||
}
|
||||
} else if let Some(constructor) = &self.constructor {
|
||||
let r#type = constructor.clone().construct(&context)?;
|
||||
|
||||
r#type
|
||||
.check(&statement_type)
|
||||
.map_err(|conflict| ValidationError::TypeCheck {
|
||||
conflict,
|
||||
actual_position: self.statement.position(),
|
||||
expected_position: Some(constructor.position()),
|
||||
})?;
|
||||
|
||||
context.set_type(self.identifier.node.clone(), r#type.clone())?;
|
||||
} else {
|
||||
context.set_type(self.identifier.node.clone(), statement_type)?;
|
||||
}
|
||||
|
@ -16,6 +16,10 @@ impl Loop {
|
||||
pub fn new(statements: Vec<Statement>) -> Self {
|
||||
Self { statements }
|
||||
}
|
||||
|
||||
pub fn last_statement(&self) -> &Statement {
|
||||
self.statements.last().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for Loop {
|
||||
|
@ -39,6 +39,14 @@ impl Statement {
|
||||
Statement::While(inner) => inner.position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn last_child_statement(&self) -> Option<&Self> {
|
||||
match self {
|
||||
Statement::Block(block) => Some(block.node.last_statement()),
|
||||
Statement::Loop(r#loop) => Some(r#loop.node.last_statement()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for Statement {
|
||||
|
@ -41,6 +41,15 @@ pub enum ValueNode {
|
||||
|
||||
impl Evaluate for ValueNode {
|
||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||
if let ValueNode::EnumInstance { type_name, .. } = self {
|
||||
if let Some(_) = context.get_type(&type_name.node)? {
|
||||
} else {
|
||||
return Err(ValidationError::EnumDefinitionNotFound(
|
||||
type_name.node.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if let ValueNode::Map(map_assignments) = self {
|
||||
for (_identifier, constructor_option, expression) in map_assignments {
|
||||
expression.validate(context, _manage_memory)?;
|
||||
@ -147,7 +156,6 @@ impl Evaluate for ValueNode {
|
||||
) -> Result<Evaluation, RuntimeError> {
|
||||
let value = match self {
|
||||
ValueNode::Boolean(boolean) => Value::boolean(boolean),
|
||||
|
||||
ValueNode::EnumInstance {
|
||||
type_name,
|
||||
variant,
|
||||
|
@ -13,7 +13,7 @@ use std::{
|
||||
};
|
||||
|
||||
use abstract_tree::{AbstractTree, Type};
|
||||
use ariadne::{Color, Fmt, Label, Report, ReportKind};
|
||||
use ariadne::{Color, Config, Fmt, Label, Report, ReportKind};
|
||||
use chumsky::prelude::*;
|
||||
use context::Context;
|
||||
use error::{DustError, RuntimeError, TypeConflict, ValidationError};
|
||||
@ -429,6 +429,8 @@ impl InterpreterError {
|
||||
}
|
||||
}
|
||||
|
||||
builder = builder.with_config(Config::default().with_multiline_arrows(false));
|
||||
|
||||
let report = builder.finish();
|
||||
|
||||
reports.push(report);
|
||||
|
@ -21,3 +21,26 @@ fn simple_enum() {
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn big_enum() {
|
||||
assert_eq!(
|
||||
interpret(
|
||||
"test",
|
||||
"
|
||||
type FooBarBaz = enum |T, U, V| {
|
||||
Foo(T),
|
||||
Bar(U),
|
||||
Baz(V),
|
||||
}
|
||||
|
||||
FooBarBaz::Baz(42.0)
|
||||
"
|
||||
),
|
||||
Ok(Some(Value::enum_instance(
|
||||
Identifier::new("FooBarBaz"),
|
||||
Identifier::new("Baz"),
|
||||
Some(vec![Value::float(42.0)]),
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
@ -14,3 +14,7 @@ x = json.parse::(int)::("1")
|
||||
|
||||
// Use type annotation
|
||||
x: int = json.parse("1")
|
||||
|
||||
x: int = {
|
||||
json.parse("1")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user