[fine] fix some bugs, semantics for is
This commit is contained in:
parent
ba5b37f5ff
commit
b5b56b49a9
4 changed files with 59 additions and 7 deletions
|
|
@ -1183,7 +1183,14 @@ fn field_list(p: &mut CParser) {
|
||||||
|
|
||||||
p.expect_start(TokenKind::LeftBrace);
|
p.expect_start(TokenKind::LeftBrace);
|
||||||
while !p.at(TokenKind::RightBrace) && !p.eof() {
|
while !p.at(TokenKind::RightBrace) && !p.eof() {
|
||||||
field_value(p);
|
if p.at(TokenKind::Identifier) {
|
||||||
|
field_value(p);
|
||||||
|
} else {
|
||||||
|
if p.at_any(STATEMENT_RECOVERY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p.advance_with_error("expected an identifier in a field list");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.expect(
|
p.expect(
|
||||||
TokenKind::RightBrace,
|
TokenKind::RightBrace,
|
||||||
|
|
@ -1196,7 +1203,7 @@ fn field_list(p: &mut CParser) {
|
||||||
fn field_value(p: &mut CParser) {
|
fn field_value(p: &mut CParser) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
p.expect(TokenKind::Identifier, "expected a field name");
|
p.expect_start(TokenKind::Identifier);
|
||||||
if p.eat(TokenKind::Colon) {
|
if p.eat(TokenKind::Colon) {
|
||||||
expression(p);
|
expression(p);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -604,14 +604,13 @@ impl<'a> Semantics<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = match tree.kind {
|
let result = match tree.kind {
|
||||||
TreeKind::LetStatement => self.environment_of_let(parent, tree),
|
TreeKind::IsExpression => self.environment_of_is_expression(parent, tree),
|
||||||
TreeKind::ParamList => self.environment_of_paramlist(parent, tree),
|
|
||||||
TreeKind::File => self.environment_of_file(parent, tree),
|
|
||||||
TreeKind::Block => self.environment_of_block(parent, tree),
|
TreeKind::Block => self.environment_of_block(parent, tree),
|
||||||
|
TreeKind::File => self.environment_of_file(parent, tree),
|
||||||
TreeKind::ForStatement => self.environment_of_for(parent, tree),
|
TreeKind::ForStatement => self.environment_of_for(parent, tree),
|
||||||
|
TreeKind::LetStatement => self.environment_of_let(parent, tree),
|
||||||
TreeKind::MemberAccess => self.environment_of_member_access(tree),
|
TreeKind::MemberAccess => self.environment_of_member_access(tree),
|
||||||
|
TreeKind::ParamList => self.environment_of_paramlist(parent, tree),
|
||||||
|
|
||||||
_ => parent,
|
_ => parent,
|
||||||
};
|
};
|
||||||
|
|
@ -819,6 +818,24 @@ impl<'a> Semantics<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn environment_of_is_expression(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
|
assert_eq!(tree.kind, TreeKind::IsExpression);
|
||||||
|
let Some(binding) = tree.child_tree_of_kind(self.syntax_tree, TreeKind::VariableBinding)
|
||||||
|
else {
|
||||||
|
return parent;
|
||||||
|
};
|
||||||
|
let Some(variable) = binding.nth_token(0) else {
|
||||||
|
return Environment::error();
|
||||||
|
};
|
||||||
|
let Some(type_expr) = binding.nth_tree(2) else {
|
||||||
|
return Environment::error();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut env = Environment::new(Some(parent), Location::Local);
|
||||||
|
env.insert(variable, type_expr);
|
||||||
|
return EnvironmentRef::new(env);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn class_of(&self, t: TreeRef) -> ClassRef {
|
pub fn class_of(&self, t: TreeRef) -> ClassRef {
|
||||||
{
|
{
|
||||||
// I want to make sure that this borrow is dropped after this block.
|
// I want to make sure that this borrow is dropped after this block.
|
||||||
|
|
@ -968,6 +985,9 @@ impl<'a> Semantics<'a> {
|
||||||
(Type::Error, _) => true,
|
(Type::Error, _) => true,
|
||||||
(_, Type::Error) => true,
|
(_, Type::Error) => true,
|
||||||
|
|
||||||
|
// Can... I... convert unreachable always? Is this sound?
|
||||||
|
(Type::Unreachable, _) => true,
|
||||||
|
|
||||||
// TODO: Unification on type variables! :D
|
// TODO: Unification on type variables! :D
|
||||||
(_, _) => false,
|
(_, _) => false,
|
||||||
}
|
}
|
||||||
|
|
@ -1010,6 +1030,7 @@ impl<'a> Semantics<'a> {
|
||||||
TreeKind::GroupingExpression => self.type_of_grouping(tree),
|
TreeKind::GroupingExpression => self.type_of_grouping(tree),
|
||||||
TreeKind::Identifier => self.type_of_identifier(t, tree),
|
TreeKind::Identifier => self.type_of_identifier(t, tree),
|
||||||
TreeKind::IfStatement => self.type_of_if_statement(tree),
|
TreeKind::IfStatement => self.type_of_if_statement(tree),
|
||||||
|
TreeKind::IsExpression => Some(Type::Bool),
|
||||||
TreeKind::LetStatement => Some(Type::Nothing),
|
TreeKind::LetStatement => Some(Type::Nothing),
|
||||||
TreeKind::ListConstructor => self.type_of_list_constructor(t, tree),
|
TreeKind::ListConstructor => self.type_of_list_constructor(t, tree),
|
||||||
TreeKind::ListConstructorElement => self.type_of_list_constructor_element(tree),
|
TreeKind::ListConstructorElement => self.type_of_list_constructor_element(tree),
|
||||||
|
|
|
||||||
18
fine/tests/expression/is.fine
Normal file
18
fine/tests/expression/is.fine
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
class Foo {
|
||||||
|
a: f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() -> f64 {
|
||||||
|
let b = new Foo { a : 23 };
|
||||||
|
|
||||||
|
let result = 0;
|
||||||
|
if b is c:Foo and c.a == 23 {
|
||||||
|
result = result + 1;
|
||||||
|
}
|
||||||
|
if b is c:Foo and c.a == 24 {
|
||||||
|
result = result + 1;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// @no-errors
|
||||||
6
fine/tests/expression/return_expression.fine
Normal file
6
fine/tests/expression/return_expression.fine
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
fun explicit_return() -> f64 {
|
||||||
|
return 10.0;
|
||||||
|
// No error: after this point code is unreachable.
|
||||||
|
}
|
||||||
|
|
||||||
|
// @no-errors
|
||||||
Loading…
Add table
Add a link
Reference in a new issue