[fine] Fix list variable binding
This commit is contained in:
parent
09a85596d8
commit
13aaca36c8
3 changed files with 46 additions and 28 deletions
|
|
@ -139,6 +139,7 @@ pub enum TreeKind {
|
||||||
Identifier,
|
Identifier,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
IsExpression,
|
IsExpression,
|
||||||
|
IteratorVariable,
|
||||||
LetStatement,
|
LetStatement,
|
||||||
ListConstructor,
|
ListConstructor,
|
||||||
ListConstructorElement,
|
ListConstructorElement,
|
||||||
|
|
@ -889,10 +890,7 @@ fn statement_for(p: &mut CParser) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
p.expect_start(TokenKind::For);
|
p.expect_start(TokenKind::For);
|
||||||
p.expect(
|
iterator_variable(p);
|
||||||
TokenKind::Identifier,
|
|
||||||
"expected an identifier for the loop variable",
|
|
||||||
);
|
|
||||||
p.expect(TokenKind::In, "expect an 'in' after the loop variable");
|
p.expect(TokenKind::In, "expect an 'in' after the loop variable");
|
||||||
if p.at_any(EXPRESSION_FIRST) {
|
if p.at_any(EXPRESSION_FIRST) {
|
||||||
expression(p);
|
expression(p);
|
||||||
|
|
@ -904,6 +902,17 @@ fn statement_for(p: &mut CParser) {
|
||||||
p.end(m, TreeKind::ForStatement);
|
p.end(m, TreeKind::ForStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iterator_variable(p: &mut CParser) {
|
||||||
|
let m = p.start();
|
||||||
|
|
||||||
|
p.expect(
|
||||||
|
TokenKind::Identifier,
|
||||||
|
"expected an identifier for the iterator variable",
|
||||||
|
);
|
||||||
|
|
||||||
|
p.end(m, TreeKind::IteratorVariable);
|
||||||
|
}
|
||||||
|
|
||||||
fn statement_expression(p: &mut CParser) {
|
fn statement_expression(p: &mut CParser) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -908,31 +908,19 @@ impl<'a> Semantics<'a> {
|
||||||
EnvironmentRef::new(environment)
|
EnvironmentRef::new(environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment_of_for(&self, parent: EnvironmentRef, _tree: &Tree) -> EnvironmentRef {
|
fn environment_of_for(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
// let Some(id) = tree.nth_token(1) else {
|
let Some(it) = tree.nth_tree(1) else {
|
||||||
// return parent;
|
return parent;
|
||||||
// };
|
};
|
||||||
|
|
||||||
// let Some(enumerable) = tree.nth_tree(3) else {
|
let iterator = &self.syntax_tree[it];
|
||||||
// return parent;
|
let Some(id) = iterator.nth_token(0) else {
|
||||||
// };
|
return parent;
|
||||||
|
};
|
||||||
|
|
||||||
// let item_type = match self.type_of(enumerable) {
|
let mut environment = Environment::new(Some(parent), Location::Local);
|
||||||
// Type::Error => Type::Error,
|
environment.insert(id, it);
|
||||||
// Type::List(x) => (&*x).clone(),
|
EnvironmentRef::new(environment)
|
||||||
// _ => {
|
|
||||||
// self.report_error_tree_ref(enumerable, "this expression is not enumerable");
|
|
||||||
// Type::Error
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// TODO: This is broken, need a sub-tree to point the decl at that
|
|
||||||
// has the right type.
|
|
||||||
//
|
|
||||||
// let mut environment = Environment::new(Some(parent), Location::Local);
|
|
||||||
// environment.insert(id, item_type);
|
|
||||||
// EnvironmentRef::new(environment)
|
|
||||||
parent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment_of_is_expression(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
fn environment_of_is_expression(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
|
|
@ -1277,6 +1265,7 @@ impl<'a> Semantics<'a> {
|
||||||
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::IsExpression => Some(Type::Bool),
|
||||||
|
TreeKind::IteratorVariable => self.type_of_iterator_variable(tree),
|
||||||
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),
|
||||||
|
|
@ -1938,6 +1927,24 @@ impl<'a> Semantics<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_of_iterator_variable(&self, tree: &Tree) -> Option<Type> {
|
||||||
|
assert_eq!(tree.kind, TreeKind::IteratorVariable);
|
||||||
|
let parent = &self.syntax_tree[tree.parent?];
|
||||||
|
assert_eq!(parent.kind, TreeKind::ForStatement);
|
||||||
|
|
||||||
|
let enumerable = parent.nth_tree(3)?;
|
||||||
|
let item_type = match self.type_of(enumerable) {
|
||||||
|
Type::Error => Type::Error,
|
||||||
|
Type::List(x) => (&*x).clone(),
|
||||||
|
_ => {
|
||||||
|
self.report_error_tree_ref(enumerable, "this expression is not enumerable");
|
||||||
|
Type::Error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(item_type)
|
||||||
|
}
|
||||||
|
|
||||||
fn type_of_list_constructor(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
fn type_of_list_constructor(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
||||||
assert_eq!(tree.kind, TreeKind::ListConstructor);
|
assert_eq!(tree.kind, TreeKind::ListConstructor);
|
||||||
let mut element_type = None;
|
let mut element_type = None;
|
||||||
|
|
@ -2346,7 +2353,9 @@ pub fn check(s: &Semantics) {
|
||||||
TreeKind::ListConstructorElement => {
|
TreeKind::ListConstructorElement => {
|
||||||
let _ = s.type_of(t);
|
let _ = s.type_of(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeKind::ForStatement => check_for_statement(s, t),
|
TreeKind::ForStatement => check_for_statement(s, t),
|
||||||
|
TreeKind::IteratorVariable => {}
|
||||||
|
|
||||||
TreeKind::ClassDecl => check_class_declaration(s, tree),
|
TreeKind::ClassDecl => check_class_declaration(s, tree),
|
||||||
TreeKind::FieldDecl => {}
|
TreeKind::FieldDecl => {}
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,4 @@ fun test() -> f64 {
|
||||||
|
|
||||||
// @ignore WIP
|
// @ignore WIP
|
||||||
// @no-errors
|
// @no-errors
|
||||||
// @type: 88 list<f64>
|
// @type: 155 list<f64>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue