Fix recursion
This commit is contained in:
parent
6a9ce76007
commit
34173c261b
@ -16,7 +16,6 @@ pub struct FunctionNode {
|
|||||||
body: Block,
|
body: Block,
|
||||||
r#type: Type,
|
r#type: Type,
|
||||||
syntax_position: SyntaxPosition,
|
syntax_position: SyntaxPosition,
|
||||||
context: Map,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionNode {
|
impl FunctionNode {
|
||||||
@ -26,21 +25,14 @@ impl FunctionNode {
|
|||||||
r#type: Type,
|
r#type: Type,
|
||||||
syntax_position: SyntaxPosition,
|
syntax_position: SyntaxPosition,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let context = Map::new();
|
|
||||||
|
|
||||||
FunctionNode {
|
FunctionNode {
|
||||||
parameters,
|
parameters,
|
||||||
body,
|
body,
|
||||||
r#type,
|
r#type,
|
||||||
syntax_position,
|
syntax_position,
|
||||||
context,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
|
|
||||||
self.context.set(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parameters(&self) -> &Vec<Identifier> {
|
pub fn parameters(&self) -> &Vec<Identifier> {
|
||||||
&self.parameters
|
&self.parameters
|
||||||
}
|
}
|
||||||
@ -57,10 +49,6 @@ impl FunctionNode {
|
|||||||
&self.syntax_position
|
&self.syntax_position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context(&self) -> &Map {
|
|
||||||
&self.context
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn return_type(&self) -> &Type {
|
pub fn return_type(&self) -> &Type {
|
||||||
match &self.r#type {
|
match &self.r#type {
|
||||||
Type::Function {
|
Type::Function {
|
||||||
@ -72,15 +60,11 @@ 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> {
|
||||||
for (key, (value, r#type)) in outer_context.variables()?.iter() {
|
let function_context = Map::new();
|
||||||
if let Value::Function(Function::ContextDefined(function_node)) = value {
|
|
||||||
if self == function_node.as_ref() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (key, (value, r#type)) in outer_context.variables()?.iter() {
|
||||||
if r#type.is_function() {
|
if r#type.is_function() {
|
||||||
self.context.set(key.clone(), value.clone())?;
|
function_context.set(key.clone(), value.clone())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +73,10 @@ impl FunctionNode {
|
|||||||
for (identifier, value) in parameter_argument_pairs {
|
for (identifier, value) in parameter_argument_pairs {
|
||||||
let key = identifier.inner().clone();
|
let key = identifier.inner().clone();
|
||||||
|
|
||||||
self.context.set(key, value.clone())?;
|
function_context.set(key, value.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_value = self.body.run(source, &self.context)?;
|
let return_value = self.body.run(source, &function_context)?;
|
||||||
|
|
||||||
Ok(return_value)
|
Ok(return_value)
|
||||||
}
|
}
|
||||||
@ -143,15 +127,33 @@ impl AbstractTree for FunctionNode {
|
|||||||
body,
|
body,
|
||||||
r#type,
|
r#type,
|
||||||
syntax_position,
|
syntax_position,
|
||||||
context: function_context,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, source: &str, _context: &Map) -> Result<()> {
|
fn check_type(&self, source: &str, _context: &Map) -> Result<()> {
|
||||||
self.return_type()
|
let function_context = Map::new();
|
||||||
.check(&self.body.expected_type(&self.context)?)
|
|
||||||
|
if let Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: _,
|
||||||
|
} = &self.r#type
|
||||||
|
{
|
||||||
|
for (parameter, parameter_type) in self.parameters.iter().zip(parameter_types.iter()) {
|
||||||
|
function_context.set_type(parameter.inner().clone(), parameter_type.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.return_type()
|
||||||
|
.check(&self.body.expected_type(&function_context)?)
|
||||||
|
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
|
||||||
|
} else {
|
||||||
|
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))?;
|
.map_err(|error| error.at_source_position(source, self.syntax_position))?;
|
||||||
self.body.check_type(source, &self.context)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,6 @@ impl Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&self, key: String, value: Value) -> Result<Option<(Value, Type)>> {
|
|
||||||
match self {
|
|
||||||
Function::BuiltIn(_) => todo!(),
|
|
||||||
Function::ContextDefined(function_node) => function_node.set(key, value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Format for Function {
|
impl Format for Function {
|
||||||
|
Loading…
Reference in New Issue
Block a user