Continue major refactoring
This commit is contained in:
parent
d06a614cfa
commit
6bdefd0698
@ -128,7 +128,10 @@ impl AbstractNode for Assignment {
|
|||||||
(&self.constructor, relevant_statement)
|
(&self.constructor, relevant_statement)
|
||||||
{
|
{
|
||||||
let declared_type = constructor.clone().construct(context)?;
|
let declared_type = constructor.clone().construct(context)?;
|
||||||
let function_type = function_call.node.function().expected_type(context)?;
|
let function_type = function_call
|
||||||
|
.node
|
||||||
|
.function_expression()
|
||||||
|
.expected_type(context)?;
|
||||||
|
|
||||||
if let Some(Type::Function {
|
if let Some(Type::Function {
|
||||||
return_type,
|
return_type,
|
||||||
|
@ -4,6 +4,7 @@ use crate::{
|
|||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -46,7 +47,24 @@ impl AbstractNode for Expression {
|
|||||||
Expression::As(inner) => inner.node.define_types(_context),
|
Expression::As(inner) => inner.node.define_types(_context),
|
||||||
Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context),
|
Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context),
|
||||||
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
||||||
Expression::Identifier(_) => Ok(()),
|
Expression::Identifier(identifier) => {
|
||||||
|
let found = _context.get_value(&identifier.node)?;
|
||||||
|
|
||||||
|
if let Some(value) = &found {
|
||||||
|
if let ValueInner::Function(function) = value.inner().as_ref() {
|
||||||
|
function.body().define_types(_context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found.is_some() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ValidationError::VariableNotFound {
|
||||||
|
identifier: identifier.node.clone(),
|
||||||
|
position: identifier.position,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
||||||
Expression::ListIndex(inner) => inner.node.define_types(_context),
|
Expression::ListIndex(inner) => inner.node.define_types(_context),
|
||||||
Expression::Logic(inner) => inner.node.define_types(_context),
|
Expression::Logic(inner) => inner.node.define_types(_context),
|
||||||
@ -65,13 +83,15 @@ impl AbstractNode for Expression {
|
|||||||
function_call.node.validate(context, manage_memory)
|
function_call.node.validate(context, manage_memory)
|
||||||
}
|
}
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let found = if manage_memory {
|
let found = context.get_value(&identifier.node)?;
|
||||||
context.add_expected_use(&identifier.node)?
|
|
||||||
} else {
|
|
||||||
context.contains(&identifier.node)?
|
|
||||||
};
|
|
||||||
|
|
||||||
if found {
|
if let Some(value) = &found {
|
||||||
|
if let ValueInner::Function(function) = value.inner().as_ref() {
|
||||||
|
function.body().validate(context, manage_memory)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found.is_some() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::VariableNotFound {
|
Err(ValidationError::VariableNotFound {
|
||||||
|
@ -37,7 +37,7 @@ impl FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(&self) -> &Box<Expression> {
|
pub fn function_expression(&self) -> &Box<Expression> {
|
||||||
&self.function_expression
|
&self.function_expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,22 +126,6 @@ impl AbstractNode for FunctionCall {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let mut arguments = Vec::with_capacity(self.value_arguments.len());
|
|
||||||
|
|
||||||
for expression in self.value_arguments {
|
|
||||||
let expression_position = expression.position();
|
|
||||||
let evaluation = expression.evaluate(context, clear_variables)?;
|
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
arguments.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let function_context = if let Some(context) = self.context.lock()?.clone() {
|
let function_context = if let Some(context) = self.context.lock()?.clone() {
|
||||||
context
|
context
|
||||||
} else {
|
} else {
|
||||||
@ -161,9 +145,25 @@ impl AbstractNode for FunctionCall {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function
|
for ((identifier, _), expression) in function
|
||||||
.clone()
|
.value_parameters()
|
||||||
.call(arguments, &function_context, clear_variables)
|
.into_iter()
|
||||||
|
.zip(self.value_arguments.iter())
|
||||||
|
{
|
||||||
|
let expression_position = expression.position();
|
||||||
|
let evaluation = expression.clone().evaluate(context, clear_variables)?;
|
||||||
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
function_context.set_value(identifier.clone(), value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
function.clone().call(&function_context, clear_variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
@ -32,7 +32,7 @@ impl AbstractNode for ListIndex {
|
|||||||
self.collection.validate(context, _manage_memory)?;
|
self.collection.validate(context, _manage_memory)?;
|
||||||
self.index.validate(context, _manage_memory)?;
|
self.index.validate(context, _manage_memory)?;
|
||||||
|
|
||||||
let collection_type = if let Some(r#type) = self.index.expected_type(context)? {
|
let collection_type = if let Some(r#type) = self.collection.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedExpression(
|
||||||
|
@ -31,12 +31,23 @@ pub enum ValueNode {
|
|||||||
name: WithPosition<Identifier>,
|
name: WithPosition<Identifier>,
|
||||||
fields: Vec<(WithPosition<Identifier>, Expression)>,
|
fields: Vec<(WithPosition<Identifier>, Expression)>,
|
||||||
},
|
},
|
||||||
Function {
|
Function(FunctionNode),
|
||||||
|
}
|
||||||
|
impl ValueNode {
|
||||||
|
pub fn function(
|
||||||
type_parameters: Option<Vec<Identifier>>,
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
value_parameters: Vec<(Identifier, TypeConstructor)>,
|
value_parameters: Vec<(Identifier, TypeConstructor)>,
|
||||||
return_type: Option<TypeConstructor>,
|
return_type: Option<TypeConstructor>,
|
||||||
body: WithPosition<Block>,
|
body: WithPosition<Block>,
|
||||||
},
|
) -> Self {
|
||||||
|
ValueNode::Function(FunctionNode {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
context_template: Context::new(None),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for ValueNode {
|
impl AbstractNode for ValueNode {
|
||||||
@ -64,7 +75,31 @@ impl AbstractNode for ValueNode {
|
|||||||
expression.define_types(_context)?;
|
expression.define_types(_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Function { body, .. } => {
|
ValueNode::Function(FunctionNode {
|
||||||
|
body,
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
context_template,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if let Some(type_parameters) = type_parameters {
|
||||||
|
for identifier in type_parameters {
|
||||||
|
context_template.set_type(
|
||||||
|
identifier.clone(),
|
||||||
|
Type::Generic {
|
||||||
|
identifier: identifier.clone(),
|
||||||
|
concrete_type: None,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (identifier, type_constructor) in value_parameters {
|
||||||
|
let r#type = type_constructor.clone().construct(&context_template)?;
|
||||||
|
|
||||||
|
context_template.set_type(identifier.clone(), r#type)?;
|
||||||
|
}
|
||||||
|
|
||||||
body.node.define_types(_context)?;
|
body.node.define_types(_context)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -122,37 +157,17 @@ impl AbstractNode for ValueNode {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ValueNode::Function {
|
if let ValueNode::Function(FunctionNode {
|
||||||
type_parameters,
|
|
||||||
value_parameters,
|
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
} = self
|
context_template,
|
||||||
|
..
|
||||||
|
}) = self
|
||||||
{
|
{
|
||||||
let mut function_context = context.create_child();
|
body.node.validate(&context_template, _manage_memory)?;
|
||||||
|
|
||||||
if let Some(type_parameters) = type_parameters {
|
|
||||||
for identifier in type_parameters {
|
|
||||||
function_context.set_type(
|
|
||||||
identifier.clone(),
|
|
||||||
Type::Generic {
|
|
||||||
identifier: identifier.clone(),
|
|
||||||
concrete_type: None,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (identifier, type_constructor) in value_parameters {
|
|
||||||
let r#type = type_constructor.clone().construct(&function_context)?;
|
|
||||||
|
|
||||||
function_context.set_type(identifier.clone(), r#type)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.node.validate(&mut function_context, _manage_memory)?;
|
|
||||||
|
|
||||||
let ((expected_return, expected_position), actual_return) =
|
let ((expected_return, expected_position), actual_return) =
|
||||||
match (return_type, body.node.expected_type(context)?) {
|
match (return_type, body.node.expected_type(&context_template)?) {
|
||||||
(Some(constructor), Some(r#type)) => (
|
(Some(constructor), Some(r#type)) => (
|
||||||
(constructor.construct(context)?, constructor.position()),
|
(constructor.construct(context)?, constructor.position()),
|
||||||
r#type,
|
r#type,
|
||||||
@ -289,26 +304,15 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
ValueNode::Range(range) => Value::range(range),
|
ValueNode::Range(range) => Value::range(range),
|
||||||
ValueNode::String(string) => Value::string(string),
|
ValueNode::String(string) => Value::string(string),
|
||||||
ValueNode::Function {
|
ValueNode::Function(FunctionNode {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters: constructors,
|
value_parameters: constructors,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
} => {
|
context_template,
|
||||||
let function_context = context.create_child();
|
}) => {
|
||||||
|
let outer_context = context;
|
||||||
if let Some(identifiers) = &type_parameters {
|
let function_context = context_template.create_child();
|
||||||
for identifier in identifiers {
|
|
||||||
function_context.set_type(
|
|
||||||
identifier.clone(),
|
|
||||||
Type::Generic {
|
|
||||||
identifier: identifier.clone(),
|
|
||||||
concrete_type: None,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut value_parameters = Vec::with_capacity(constructors.len());
|
let mut value_parameters = Vec::with_capacity(constructors.len());
|
||||||
|
|
||||||
for (identifier, constructor) in constructors {
|
for (identifier, constructor) in constructors {
|
||||||
@ -318,12 +322,18 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let return_type = if let Some(constructor) = return_type {
|
let return_type = if let Some(constructor) = return_type {
|
||||||
Some(constructor.construct(&function_context)?)
|
Some(constructor.construct(&outer_context)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Value::function(type_parameters, value_parameters, return_type, body.node)
|
Value::function(
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
body.node,
|
||||||
|
context_template,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ValueNode::Structure {
|
ValueNode::Structure {
|
||||||
name,
|
name,
|
||||||
@ -383,12 +393,12 @@ impl AbstractNode for ValueNode {
|
|||||||
ValueNode::Map(_) => Type::Map,
|
ValueNode::Map(_) => Type::Map,
|
||||||
ValueNode::Range(_) => Type::Range,
|
ValueNode::Range(_) => Type::Range,
|
||||||
ValueNode::String(_) => Type::String,
|
ValueNode::String(_) => Type::String,
|
||||||
ValueNode::Function {
|
ValueNode::Function(FunctionNode {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
|
let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
|
||||||
|
|
||||||
for (_, type_constructor) in value_parameters {
|
for (_, type_constructor) in value_parameters {
|
||||||
@ -511,18 +521,20 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
(EnumInstance { .. }, _) => Ordering::Greater,
|
(EnumInstance { .. }, _) => Ordering::Greater,
|
||||||
(
|
(
|
||||||
Function {
|
Function(FunctionNode {
|
||||||
type_parameters: left_type_arguments,
|
type_parameters: left_type_arguments,
|
||||||
value_parameters: left_parameters,
|
value_parameters: left_parameters,
|
||||||
return_type: left_return,
|
return_type: left_return,
|
||||||
body: left_body,
|
body: left_body,
|
||||||
},
|
..
|
||||||
Function {
|
}),
|
||||||
|
Function(FunctionNode {
|
||||||
type_parameters: right_type_arguments,
|
type_parameters: right_type_arguments,
|
||||||
value_parameters: right_parameters,
|
value_parameters: right_parameters,
|
||||||
return_type: right_return,
|
return_type: right_return,
|
||||||
body: right_body,
|
body: right_body,
|
||||||
},
|
..
|
||||||
|
}),
|
||||||
) => {
|
) => {
|
||||||
let parameter_cmp = left_parameters.cmp(right_parameters);
|
let parameter_cmp = left_parameters.cmp(right_parameters);
|
||||||
|
|
||||||
@ -567,3 +579,22 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct FunctionNode {
|
||||||
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
|
value_parameters: Vec<(Identifier, TypeConstructor)>,
|
||||||
|
return_type: Option<TypeConstructor>,
|
||||||
|
body: WithPosition<Block>,
|
||||||
|
#[serde(skip)]
|
||||||
|
context_template: Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FunctionNode {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.type_parameters == other.type_parameters
|
||||||
|
&& self.value_parameters == other.value_parameters
|
||||||
|
&& self.return_type == other.return_type
|
||||||
|
&& self.body == other.body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -152,19 +152,12 @@ impl Context {
|
|||||||
self.data
|
self.data
|
||||||
.write()?
|
.write()?
|
||||||
.variables
|
.variables
|
||||||
.retain(|identifier, (value_data, usage_data)| {
|
.retain(|_, (value_data, usage_data)| match value_data {
|
||||||
if let VariableData::Value(_) = value_data {
|
VariableData::Type(_) => true,
|
||||||
|
VariableData::Value(_) => {
|
||||||
let usage = usage_data.inner().read().unwrap();
|
let usage = usage_data.inner().read().unwrap();
|
||||||
|
|
||||||
if usage.actual < usage.expected {
|
usage.actual < usage.expected
|
||||||
true
|
|
||||||
} else {
|
|
||||||
log::trace!("Removing variable {identifier}.");
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -178,6 +171,12 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Context {
|
||||||
|
fn default() -> Self {
|
||||||
|
Context::new(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum VariableData {
|
pub enum VariableData {
|
||||||
Type(Type),
|
Type(Type),
|
||||||
|
@ -291,12 +291,12 @@ pub fn parser<'src>(
|
|||||||
.map_with(
|
.map_with(
|
||||||
|(((type_parameters, value_parameters), return_type), body), state| {
|
|(((type_parameters, value_parameters), return_type), body), state| {
|
||||||
Expression::Value(
|
Expression::Value(
|
||||||
ValueNode::Function {
|
ValueNode::function(
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
}
|
)
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -528,17 +528,17 @@ fn function() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("fn () -> int { 0 }").unwrap()).unwrap()[0],
|
parse(&lex("fn () -> int { 0 }").unwrap()).unwrap()[0],
|
||||||
Statement::Expression(Expression::Value(
|
Statement::Expression(Expression::Value(
|
||||||
ValueNode::Function {
|
ValueNode::function(
|
||||||
type_parameters: None,
|
None,
|
||||||
value_parameters: vec![],
|
vec![],
|
||||||
return_type: Some(TypeConstructor::Raw(
|
Some(TypeConstructor::Raw(
|
||||||
RawTypeConstructor::Integer.with_position((9, 12))
|
RawTypeConstructor::Integer.with_position((9, 12))
|
||||||
)),
|
)),
|
||||||
body: Block::new(vec![Statement::Expression(Expression::Value(
|
Block::new(vec![Statement::Expression(Expression::Value(
|
||||||
ValueNode::Integer(0).with_position((15, 16))
|
ValueNode::Integer(0).with_position((15, 16))
|
||||||
))])
|
))])
|
||||||
.with_position((13, 18))
|
.with_position((13, 18)),
|
||||||
}
|
)
|
||||||
.with_position((0, 18))
|
.with_position((0, 18))
|
||||||
),)
|
),)
|
||||||
);
|
);
|
||||||
@ -546,20 +546,20 @@ fn function() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("fn (x: int) -> int { x }").unwrap()).unwrap()[0],
|
parse(&lex("fn (x: int) -> int { x }").unwrap()).unwrap()[0],
|
||||||
Statement::Expression(Expression::Value(
|
Statement::Expression(Expression::Value(
|
||||||
ValueNode::Function {
|
ValueNode::function(
|
||||||
type_parameters: None,
|
None,
|
||||||
value_parameters: vec![(
|
vec![(
|
||||||
Identifier::new("x"),
|
Identifier::new("x"),
|
||||||
TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10)))
|
TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10)))
|
||||||
)],
|
)],
|
||||||
return_type: Some(TypeConstructor::Raw(
|
Some(TypeConstructor::Raw(
|
||||||
RawTypeConstructor::Integer.with_position((15, 18))
|
RawTypeConstructor::Integer.with_position((15, 18))
|
||||||
)),
|
)),
|
||||||
body: Block::new(vec![Statement::Expression(Expression::Identifier(
|
Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||||
Identifier::new("x").with_position((21, 22))
|
Identifier::new("x").with_position((21, 22))
|
||||||
))])
|
))])
|
||||||
.with_position((19, 24)),
|
.with_position((19, 24)),
|
||||||
}
|
)
|
||||||
.with_position((0, 24))
|
.with_position((0, 24))
|
||||||
),)
|
),)
|
||||||
);
|
);
|
||||||
@ -570,9 +570,9 @@ fn function_with_type_arguments() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("fn |T, U| (x: T, y: U) -> T { x }").unwrap()).unwrap()[0],
|
parse(&lex("fn |T, U| (x: T, y: U) -> T { x }").unwrap()).unwrap()[0],
|
||||||
Statement::Expression(Expression::Value(
|
Statement::Expression(Expression::Value(
|
||||||
ValueNode::Function {
|
ValueNode::function(
|
||||||
type_parameters: Some(vec![Identifier::new("T"), Identifier::new("U"),]),
|
Some(vec![Identifier::new("T"), Identifier::new("U"),]),
|
||||||
value_parameters: vec![
|
vec![
|
||||||
(
|
(
|
||||||
Identifier::new("x"),
|
Identifier::new("x"),
|
||||||
TypeConstructor::Invokation(TypeInvokationConstructor {
|
TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||||
@ -588,15 +588,15 @@ fn function_with_type_arguments() {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
return_type: Some(TypeConstructor::Invokation(TypeInvokationConstructor {
|
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||||
identifier: Identifier::new("T").with_position((26, 27)),
|
identifier: Identifier::new("T").with_position((26, 27)),
|
||||||
type_arguments: None,
|
type_arguments: None,
|
||||||
})),
|
})),
|
||||||
body: Block::new(vec![Statement::Expression(Expression::Identifier(
|
Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||||
Identifier::new("x").with_position((30, 31))
|
Identifier::new("x").with_position((30, 31))
|
||||||
))])
|
))])
|
||||||
.with_position((28, 33)),
|
.with_position((28, 33)),
|
||||||
}
|
)
|
||||||
.with_position((0, 33))
|
.with_position((0, 33))
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ use serde::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{PoisonError, RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,12 +73,14 @@ impl Value {
|
|||||||
value_parameters: Vec<(Identifier, Type)>,
|
value_parameters: Vec<(Identifier, Type)>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
body: Block,
|
body: Block,
|
||||||
|
context_template: Context,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Value(Arc::new(ValueInner::Function(Function {
|
Value(Arc::new(ValueInner::Function(Function {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
|
context_template,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +169,7 @@ impl Display for Value {
|
|||||||
value_parameters: parameters,
|
value_parameters: parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if let Some(type_parameters) = type_parameters {
|
if let Some(type_parameters) = type_parameters {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
@ -249,6 +252,7 @@ impl Serialize for Value {
|
|||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let mut struct_ser = serializer.serialize_struct("Function", 4)?;
|
let mut struct_ser = serializer.serialize_struct("Function", 4)?;
|
||||||
|
|
||||||
@ -541,7 +545,7 @@ impl<'de> Deserialize<'de> for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueInner {
|
pub enum ValueInner {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
EnumInstance {
|
EnumInstance {
|
||||||
@ -707,15 +711,20 @@ impl Ord for ValueInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
type_parameters: Option<Vec<Identifier>>,
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
value_parameters: Vec<(Identifier, Type)>,
|
value_parameters: Vec<(Identifier, Type)>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
body: Block,
|
body: Block,
|
||||||
|
context_template: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
|
pub fn context_template(&self) -> &Context {
|
||||||
|
&self.context_template
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_parameters(&self) -> &Option<Vec<Identifier>> {
|
pub fn type_parameters(&self) -> &Option<Vec<Identifier>> {
|
||||||
&self.type_parameters
|
&self.type_parameters
|
||||||
}
|
}
|
||||||
@ -730,18 +739,50 @@ impl Function {
|
|||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
self,
|
self,
|
||||||
value_arguments: Vec<Value>,
|
|
||||||
context: &Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
for ((identifier, _), value) in self
|
|
||||||
.value_parameters
|
|
||||||
.into_iter()
|
|
||||||
.zip(value_arguments.into_iter())
|
|
||||||
{
|
|
||||||
context.set_value(identifier.clone(), value)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.body.evaluate(context, manage_memory)
|
self.body.evaluate(context, manage_memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn populate_context_template(&self) -> Result<(), PoisonError> {
|
||||||
|
if let Some(type_parameters) = &self.type_parameters {
|
||||||
|
for identifier in type_parameters {
|
||||||
|
self.context_template.set_type(
|
||||||
|
identifier.clone(),
|
||||||
|
Type::Generic {
|
||||||
|
identifier: identifier.clone(),
|
||||||
|
concrete_type: None,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (identifier, r#type) in &self.value_parameters {
|
||||||
|
self.context_template
|
||||||
|
.set_type(identifier.clone(), r#type.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Function {}
|
||||||
|
|
||||||
|
impl PartialEq for Function {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Function {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Function {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
abstract_tree::{Block, Expression, Statement, Type, WithPos},
|
abstract_tree::{Block, Expression, Statement, Type, WithPos},
|
||||||
|
context::Context,
|
||||||
error::{DustError, TypeConflict, ValidationError},
|
error::{DustError, TypeConflict, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
*,
|
*,
|
||||||
@ -51,7 +52,8 @@ fn function_variable() {
|
|||||||
Some(Type::Integer),
|
Some(Type::Integer),
|
||||||
Block::new(vec![Statement::Expression(Expression::Identifier(
|
Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||||
Identifier::new("x").with_position((30, 31))
|
Identifier::new("x").with_position((30, 31))
|
||||||
))])
|
))]),
|
||||||
|
Context::new(None)
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user