[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,
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();

View file

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

View file

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