[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,
|
||||
IfStatement,
|
||||
IsExpression,
|
||||
IteratorVariable,
|
||||
LetStatement,
|
||||
ListConstructor,
|
||||
ListConstructorElement,
|
||||
|
|
@ -889,10 +890,7 @@ fn statement_for(p: &mut CParser) {
|
|||
let m = p.start();
|
||||
|
||||
p.expect_start(TokenKind::For);
|
||||
p.expect(
|
||||
TokenKind::Identifier,
|
||||
"expected an identifier for the loop variable",
|
||||
);
|
||||
iterator_variable(p);
|
||||
p.expect(TokenKind::In, "expect an 'in' after the loop variable");
|
||||
if p.at_any(EXPRESSION_FIRST) {
|
||||
expression(p);
|
||||
|
|
@ -904,6 +902,17 @@ fn statement_for(p: &mut CParser) {
|
|||
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) {
|
||||
let m = p.start();
|
||||
|
||||
|
|
|
|||
|
|
@ -908,31 +908,19 @@ impl<'a> Semantics<'a> {
|
|||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
||||
fn environment_of_for(&self, parent: EnvironmentRef, _tree: &Tree) -> EnvironmentRef {
|
||||
// let Some(id) = tree.nth_token(1) else {
|
||||
// return parent;
|
||||
// };
|
||||
fn environment_of_for(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||
let Some(it) = tree.nth_tree(1) else {
|
||||
return parent;
|
||||
};
|
||||
|
||||
// let Some(enumerable) = tree.nth_tree(3) else {
|
||||
// return parent;
|
||||
// };
|
||||
let iterator = &self.syntax_tree[it];
|
||||
let Some(id) = iterator.nth_token(0) else {
|
||||
return parent;
|
||||
};
|
||||
|
||||
// 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
|
||||
// }
|
||||
// };
|
||||
|
||||
// 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
|
||||
let mut environment = Environment::new(Some(parent), Location::Local);
|
||||
environment.insert(id, it);
|
||||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
||||
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::IfStatement => self.type_of_if_statement(tree),
|
||||
TreeKind::IsExpression => Some(Type::Bool),
|
||||
TreeKind::IteratorVariable => self.type_of_iterator_variable(tree),
|
||||
TreeKind::LetStatement => Some(Type::Nothing),
|
||||
TreeKind::ListConstructor => self.type_of_list_constructor(t, 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> {
|
||||
assert_eq!(tree.kind, TreeKind::ListConstructor);
|
||||
let mut element_type = None;
|
||||
|
|
@ -2346,7 +2353,9 @@ pub fn check(s: &Semantics) {
|
|||
TreeKind::ListConstructorElement => {
|
||||
let _ = s.type_of(t);
|
||||
}
|
||||
|
||||
TreeKind::ForStatement => check_for_statement(s, t),
|
||||
TreeKind::IteratorVariable => {}
|
||||
|
||||
TreeKind::ClassDecl => check_class_declaration(s, tree),
|
||||
TreeKind::FieldDecl => {}
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ fun test() -> f64 {
|
|||
|
||||
// @ignore WIP
|
||||
// @no-errors
|
||||
// @type: 88 list<f64>
|
||||
// @type: 155 list<f64>
|
||||
Loading…
Add table
Add a link
Reference in a new issue