[fine] Fix list variable binding

This commit is contained in:
John Doty 2024-02-08 06:34:02 -08:00
parent 09a85596d8
commit 13aaca36c8
3 changed files with 46 additions and 28 deletions

View file

@ -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();

View file

@ -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 => {}

View file

@ -13,4 +13,4 @@ fun test() -> f64 {
// @ignore WIP // @ignore WIP
// @no-errors // @no-errors
// @type: 88 list<f64> // @type: 155 list<f64>