Fix function context bug

This commit is contained in:
Jeff 2024-01-28 18:42:27 -05:00
parent 34173c261b
commit bd6ca6a6c1
4 changed files with 28 additions and 22 deletions

View File

@ -1,4 +1,4 @@
fib = (i <int>, fib <(int) -> int>) <int> { fib = (i <int>) <int> {
if i <= 1 { if i <= 1 {
1 1
} else { } else {
@ -6,4 +6,4 @@ fib = (i <int>, fib <(int) -> int>) <int> {
} }
} }
fib(8, fib) fib(8)

View File

@ -97,9 +97,7 @@ impl AbstractTree for Assignment {
} }
} }
self.statement self.statement.check_type(source, context)?;
.check_type(source, context)
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
Ok(()) Ok(())
} }

View File

@ -61,6 +61,7 @@ impl FunctionNode {
pub fn call(&self, arguments: &[Value], source: &str, outer_context: &Map) -> Result<Value> { pub fn call(&self, arguments: &[Value], source: &str, outer_context: &Map) -> Result<Value> {
let function_context = Map::new(); let function_context = Map::new();
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
for (key, (value, r#type)) in outer_context.variables()?.iter() { for (key, (value, r#type)) in outer_context.variables()?.iter() {
if r#type.is_function() { if r#type.is_function() {
@ -68,8 +69,6 @@ impl FunctionNode {
} }
} }
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
for (identifier, value) in parameter_argument_pairs { for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone(); let key = identifier.inner().clone();
@ -116,6 +115,12 @@ impl AbstractTree for FunctionNode {
function_context.set_type(parameter.inner().clone(), parameter_type.clone())?; function_context.set_type(parameter.inner().clone(), parameter_type.clone())?;
} }
for (key, (value, r#type)) in outer_context.variables()?.iter() {
if r#type.is_function() {
function_context.set(key.clone(), value.clone())?;
}
}
let body_node = node.child(child_count - 1).unwrap(); let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax(body_node, source, &function_context)?; let body = Block::from_syntax(body_node, source, &function_context)?;
@ -130,32 +135,35 @@ impl AbstractTree for FunctionNode {
}) })
} }
fn check_type(&self, source: &str, _context: &Map) -> Result<()> { fn check_type(&self, source: &str, context: &Map) -> Result<()> {
let function_context = Map::new(); let function_context = Map::new();
for (key, (_value, r#type)) in context.variables()?.iter() {
if r#type.is_function() {
function_context.set_type(key.clone(), r#type.clone())?;
}
}
if let Type::Function { if let Type::Function {
parameter_types, parameter_types,
return_type: _, return_type,
} = &self.r#type } = &self.r#type
{ {
for (parameter, parameter_type) in self.parameters.iter().zip(parameter_types.iter()) { for (parameter, parameter_type) in self.parameters.iter().zip(parameter_types.iter()) {
function_context.set_type(parameter.inner().clone(), parameter_type.clone())?; function_context.set_type(parameter.inner().clone(), parameter_type.clone())?;
} }
self.return_type() return_type
.check(&self.body.expected_type(&function_context)?) .check(&self.body.expected_type(&function_context)?)
.map_err(|error| error.at_source_position(source, self.syntax_position))?; .map_err(|error| error.at_source_position(source, self.syntax_position))?;
} else { self.body.check_type(source, &function_context)?;
return Err(Error::TypeCheckExpectedFunction {
actual: self.r#type.clone(),
});
};
self.body
.check_type(source, &function_context)
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
Ok(()) Ok(())
} else {
Err(Error::TypeCheckExpectedFunction {
actual: self.r#type.clone(),
})
}
} }
fn run(&self, _source: &str, _context: &Map) -> Result<Value> { fn run(&self, _source: &str, _context: &Map) -> Result<Value> {

View File

@ -137,13 +137,13 @@ fn recursion() {
if i <= 1 { if i <= 1 {
1 1
} else { } else {
self(i - 1) + self(i - 2) fib(i - 1) + fib(i - 2)
} }
} }
fib(3) fib(8)
" "
), ),
Ok(Value::Integer(3)) Ok(Value::Integer(34))
); );
} }