Continue major refactoring

This commit is contained in:
Jeff 2024-06-22 13:55:43 -04:00
parent d06a614cfa
commit 6bdefd0698
10 changed files with 223 additions and 127 deletions

View File

@ -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,

View File

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

View File

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

View File

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

View File

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

View File

@ -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),

View File

@ -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()),
) )
}, },

View File

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

View File

@ -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!()
}
} }

View File

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