Add list type check; Clean up
This commit is contained in:
parent
fe0bb0a0b5
commit
adfd3aa5d4
@ -30,19 +30,16 @@ impl As {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for As {
|
impl AbstractNode for As {
|
||||||
fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
Ok(())
|
self.expression.define_types(_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
self.expression.validate(_context, _manage_memory)?;
|
||||||
|
|
||||||
match self.constructor {
|
match self.constructor {
|
||||||
TypeConstructor::Raw(_) => {}
|
TypeConstructor::Raw(_) => {}
|
||||||
_ => todo!("Create an error for this occurence."),
|
_ => todo!("Create an error for this occurence"),
|
||||||
};
|
|
||||||
|
|
||||||
match self.expression.expected_type(_context)? {
|
|
||||||
Some(Type::Boolean) | Some(Type::Float) | Some(Type::Integer) | Some(Type::String) => {}
|
|
||||||
_ => todo!("Create an error for this occurence."),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -66,9 +63,8 @@ impl AbstractNode for As {
|
|||||||
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), r#type);
|
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), r#type);
|
||||||
|
|
||||||
let converted = match (from_value, to_type) {
|
let converted = match (from_value, to_type) {
|
||||||
(ValueInner::Boolean(boolean), Type::String) => Value::string(boolean.to_string()),
|
(_, Type::String) => Value::string(value.to_string()),
|
||||||
(ValueInner::Integer(integer), Type::String) => Value::string(integer.to_string()),
|
_ => todo!("Create an error for this occurence"),
|
||||||
_ => todo!("Create an error for this occurence."),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(converted)))
|
Ok(Some(Evaluation::Return(converted)))
|
||||||
|
@ -36,10 +36,6 @@ impl FunctionCall {
|
|||||||
context: Context::new(None),
|
context: Context::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_expression(&self) -> &Box<Expression> {
|
|
||||||
&self.function_expression
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for FunctionCall {
|
impl AbstractNode for FunctionCall {
|
||||||
@ -57,17 +53,22 @@ impl AbstractNode for FunctionCall {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(
|
||||||
self.function_expression.validate(context, manage_memory)?;
|
&self,
|
||||||
|
outer_context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<(), ValidationError> {
|
||||||
|
self.function_expression
|
||||||
|
.validate(outer_context, manage_memory)?;
|
||||||
|
|
||||||
if let Some(value_arguments) = &self.value_arguments {
|
if let Some(value_arguments) = &self.value_arguments {
|
||||||
for expression in value_arguments {
|
for expression in value_arguments {
|
||||||
expression.validate(context, manage_memory)?;
|
expression.validate(outer_context, manage_memory)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let function_node_type =
|
let function_node_type =
|
||||||
if let Some(r#type) = self.function_expression.expected_type(context)? {
|
if let Some(r#type) = self.function_expression.expected_type(outer_context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedExpression(
|
||||||
@ -90,7 +91,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (identifier, constructor) in parameters.into_iter().zip(arguments.into_iter()) {
|
for (identifier, constructor) in parameters.into_iter().zip(arguments.into_iter()) {
|
||||||
let r#type = constructor.construct(context)?;
|
let r#type = constructor.construct(outer_context)?;
|
||||||
|
|
||||||
self.context.set_type(identifier, r#type)?;
|
self.context.set_type(identifier, r#type)?;
|
||||||
}
|
}
|
||||||
@ -101,7 +102,9 @@ impl AbstractNode for FunctionCall {
|
|||||||
for ((identifier, _), expression) in
|
for ((identifier, _), expression) in
|
||||||
parameters.iter().zip(arguments.into_iter())
|
parameters.iter().zip(arguments.into_iter())
|
||||||
{
|
{
|
||||||
let r#type = if let Some(r#type) = expression.expected_type(context)? {
|
let r#type = if let Some(r#type) =
|
||||||
|
expression.expected_type(outer_context)?
|
||||||
|
{
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
@ -143,11 +146,13 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &Context,
|
outer_context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let function_position = self.function_expression.position();
|
let function_position = self.function_expression.position();
|
||||||
let evaluation = self.function_expression.evaluate(context, manage_memory)?;
|
let evaluation = self
|
||||||
|
.function_expression
|
||||||
|
.evaluate(outer_context, manage_memory)?;
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -163,7 +168,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
for (identifier, constructor) in
|
for (identifier, constructor) in
|
||||||
type_parameters.into_iter().zip(type_arguments.into_iter())
|
type_parameters.into_iter().zip(type_arguments.into_iter())
|
||||||
{
|
{
|
||||||
let r#type = constructor.construct(context)?;
|
let r#type = constructor.construct(outer_context)?;
|
||||||
|
|
||||||
self.context.set_type(identifier.clone(), r#type)?;
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
}
|
}
|
||||||
@ -176,7 +181,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
parameters.into_iter().zip(arguments.into_iter())
|
parameters.into_iter().zip(arguments.into_iter())
|
||||||
{
|
{
|
||||||
let position = expression.position();
|
let position = expression.position();
|
||||||
let evaluation = expression.evaluate(context, manage_memory)?;
|
let evaluation = expression.evaluate(outer_context, manage_memory)?;
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -215,7 +220,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
for (identifier, constructor) in
|
for (identifier, constructor) in
|
||||||
type_parameters.into_iter().zip(type_arguments.into_iter())
|
type_parameters.into_iter().zip(type_arguments.into_iter())
|
||||||
{
|
{
|
||||||
let r#type = constructor.construct(context)?;
|
let r#type = constructor.construct(outer_context)?;
|
||||||
|
|
||||||
self.context.set_type(identifier.clone(), r#type)?;
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
}
|
}
|
||||||
@ -226,7 +231,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
parameters.into_iter().zip(arguments.into_iter())
|
parameters.into_iter().zip(arguments.into_iter())
|
||||||
{
|
{
|
||||||
let position = expression.position();
|
let position = expression.position();
|
||||||
let evaluation = expression.evaluate(context, manage_memory)?;
|
let evaluation = expression.evaluate(outer_context, manage_memory)?;
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -246,7 +251,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedFunction {
|
ValidationError::ExpectedFunction {
|
||||||
actual: value.r#type(context)?,
|
actual: value.r#type(outer_context)?,
|
||||||
position: function_position,
|
position: function_position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
@ -257,13 +262,13 @@ impl AbstractNode for FunctionCall {
|
|||||||
ValidationError::ExpectedExpression(self.function_expression.position()),
|
ValidationError::ExpectedExpression(self.function_expression.position()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (type_parameters, value_parameters, return_type) = if let Type::Function {
|
let (type_parameters, return_type) = if let Type::Function {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
|
||||||
return_type,
|
return_type,
|
||||||
|
..
|
||||||
} = expression_type
|
} = expression_type
|
||||||
{
|
{
|
||||||
(type_parameters, value_parameters, return_type)
|
(type_parameters, return_type)
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedFunction {
|
return Err(ValidationError::ExpectedFunction {
|
||||||
actual: expression_type,
|
actual: expression_type,
|
||||||
@ -300,7 +305,7 @@ impl Display for FunctionCall {
|
|||||||
function_expression,
|
function_expression,
|
||||||
type_arguments,
|
type_arguments,
|
||||||
value_arguments,
|
value_arguments,
|
||||||
context,
|
..
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
write!(f, "{function_expression}")?;
|
write!(f, "{function_expression}")?;
|
||||||
|
@ -53,7 +53,7 @@ impl ValueNode {
|
|||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
context_template: Context::new(None),
|
validation_context: Context::new(None),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,14 +87,14 @@ impl AbstractNode for ValueNode {
|
|||||||
body,
|
body,
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
value_parameters,
|
||||||
context_template,
|
validation_context,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
context_template.set_parent(outer_context.clone())?;
|
validation_context.set_parent(outer_context.clone())?;
|
||||||
|
|
||||||
if let Some(type_parameters) = type_parameters {
|
if let Some(type_parameters) = type_parameters {
|
||||||
for identifier in type_parameters {
|
for identifier in type_parameters {
|
||||||
context_template.set_type(
|
validation_context.set_type(
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
Type::Generic {
|
Type::Generic {
|
||||||
identifier: identifier.clone(),
|
identifier: identifier.clone(),
|
||||||
@ -108,11 +108,11 @@ impl AbstractNode for ValueNode {
|
|||||||
for (identifier, type_constructor) in value_parameters {
|
for (identifier, type_constructor) in value_parameters {
|
||||||
let r#type = type_constructor.clone().construct(outer_context)?;
|
let r#type = type_constructor.clone().construct(outer_context)?;
|
||||||
|
|
||||||
context_template.set_type(identifier.clone(), r#type)?;
|
validation_context.set_type(identifier.clone(), r#type)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body.node.define_types(context_template)?;
|
body.node.define_types(validation_context)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -121,6 +121,32 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
if let ValueNode::List(list) = self {
|
||||||
|
let mut items = list.into_iter();
|
||||||
|
let first_item = items.next().unwrap();
|
||||||
|
let first_item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(first_item.position()));
|
||||||
|
};
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
let item_type = if let Some(r#type) = item.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(item.position()));
|
||||||
|
};
|
||||||
|
|
||||||
|
first_item_type.check(&item_type).map_err(|conflict| {
|
||||||
|
ValidationError::TypeCheck {
|
||||||
|
conflict,
|
||||||
|
actual_position: item.position(),
|
||||||
|
expected_position: Some(first_item.position()),
|
||||||
|
}
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let ValueNode::EnumInstance {
|
if let ValueNode::EnumInstance {
|
||||||
type_name, variant, ..
|
type_name, variant, ..
|
||||||
} = self
|
} = self
|
||||||
@ -154,9 +180,9 @@ impl AbstractNode for ValueNode {
|
|||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
};
|
};
|
||||||
let exprected_type = constructor.clone().construct(&context)?;
|
let expected_type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
exprected_type.check(&actual_type).map_err(|conflict| {
|
expected_type.check(&actual_type).map_err(|conflict| {
|
||||||
ValidationError::TypeCheck {
|
ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: expression.position(),
|
actual_position: expression.position(),
|
||||||
@ -172,17 +198,17 @@ impl AbstractNode for ValueNode {
|
|||||||
if let ValueNode::Function(FunctionNode {
|
if let ValueNode::Function(FunctionNode {
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
context_template,
|
validation_context,
|
||||||
..
|
..
|
||||||
}) = self
|
}) = self
|
||||||
{
|
{
|
||||||
body.node.validate(&context_template, _manage_memory)?;
|
body.node.validate(&validation_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_template)?) {
|
match (return_type, body.node.expected_type(&validation_context)?) {
|
||||||
(Some(constructor), Some(r#type)) => (
|
(Some(constructor), Some(r#type)) => (
|
||||||
(
|
(
|
||||||
constructor.construct(context_template)?,
|
constructor.construct(validation_context)?,
|
||||||
constructor.position(),
|
constructor.position(),
|
||||||
),
|
),
|
||||||
r#type,
|
r#type,
|
||||||
@ -324,7 +350,7 @@ impl AbstractNode for ValueNode {
|
|||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
context_template,
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let outer_context = context;
|
let outer_context = context;
|
||||||
let value_parameters = if let Some(value_parameters) = value_parameters {
|
let value_parameters = if let Some(value_parameters) = value_parameters {
|
||||||
@ -346,13 +372,7 @@ impl AbstractNode for ValueNode {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Value::function(
|
Value::function(type_parameters, value_parameters, return_type, body.node)
|
||||||
type_parameters,
|
|
||||||
value_parameters,
|
|
||||||
return_type,
|
|
||||||
body.node,
|
|
||||||
context_template,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ValueNode::Structure {
|
ValueNode::Structure {
|
||||||
name,
|
name,
|
||||||
@ -450,7 +470,6 @@ impl AbstractNode for ValueNode {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_parameters = type_parameters.clone().map(|parameters| {
|
let type_parameters = type_parameters.clone().map(|parameters| {
|
||||||
parameters
|
parameters
|
||||||
.iter()
|
.iter()
|
||||||
@ -687,7 +706,7 @@ impl Display for ValueNode {
|
|||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
context_template: _,
|
validation_context: _,
|
||||||
}) => {
|
}) => {
|
||||||
write!(f, "fn ")?;
|
write!(f, "fn ")?;
|
||||||
|
|
||||||
@ -728,7 +747,7 @@ pub struct FunctionNode {
|
|||||||
return_type: Option<TypeConstructor>,
|
return_type: Option<TypeConstructor>,
|
||||||
body: WithPosition<Block>,
|
body: WithPosition<Block>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
context_template: Context,
|
validation_context: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for FunctionNode {
|
impl PartialEq for FunctionNode {
|
||||||
|
@ -34,6 +34,18 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_variables_from(other: &Context) -> Result<Self, PoisonError> {
|
||||||
|
let variables = other.data.read()?.variables.clone();
|
||||||
|
|
||||||
|
Ok(Context {
|
||||||
|
data: Arc::new(RwLock::new(ContextData {
|
||||||
|
variables,
|
||||||
|
parent: None,
|
||||||
|
})),
|
||||||
|
is_clean: Arc::new(RwLock::new(true)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_child(&self) -> Context {
|
pub fn create_child(&self) -> Context {
|
||||||
Context::new(Some(self.clone()))
|
Context::new(Some(self.clone()))
|
||||||
}
|
}
|
||||||
@ -91,7 +103,8 @@ impl Context {
|
|||||||
match value.inner().as_ref() {
|
match value.inner().as_ref() {
|
||||||
ValueInner::EnumInstance { .. }
|
ValueInner::EnumInstance { .. }
|
||||||
| ValueInner::Function(_)
|
| ValueInner::Function(_)
|
||||||
| ValueInner::Structure { .. } => return Ok(Some(value)),
|
| ValueInner::Structure { .. }
|
||||||
|
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +125,8 @@ impl Context {
|
|||||||
match value.inner().as_ref() {
|
match value.inner().as_ref() {
|
||||||
ValueInner::EnumInstance { .. }
|
ValueInner::EnumInstance { .. }
|
||||||
| ValueInner::Function(_)
|
| ValueInner::Function(_)
|
||||||
| ValueInner::Structure { .. } => return Ok(Some(value)),
|
| ValueInner::Structure { .. }
|
||||||
|
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +154,7 @@ impl Context {
|
|||||||
.variables
|
.variables
|
||||||
.remove(&identifier)
|
.remove(&identifier)
|
||||||
.map(|(_, usage_data)| usage_data)
|
.map(|(_, usage_data)| usage_data)
|
||||||
.unwrap_or(UsageData::new());
|
.unwrap_or_else(|| UsageData::new());
|
||||||
|
|
||||||
data.variables
|
data.variables
|
||||||
.insert(identifier, (VariableData::Value(value), usage_data));
|
.insert(identifier, (VariableData::Value(value), usage_data));
|
||||||
@ -156,13 +170,23 @@ impl Context {
|
|||||||
|
|
||||||
usage_data.inner().write()?.expected += 1;
|
usage_data.inner().write()?.expected += 1;
|
||||||
|
|
||||||
Ok(true)
|
return Ok(true);
|
||||||
} else if let Some(parent) = &data.parent {
|
} else if let Some(parent) = &data.parent {
|
||||||
parent.add_expected_use(identifier)
|
let parent_data = parent.data.read()?;
|
||||||
} else {
|
|
||||||
Ok(false)
|
if let Some((variable_data, usage_data)) = parent_data.variables.get(identifier) {
|
||||||
|
if let VariableData::Value(value) = variable_data {
|
||||||
|
if let ValueInner::Function(_) = value.inner().as_ref() {
|
||||||
|
usage_data.inner().write()?.expected += 1;
|
||||||
|
|
||||||
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clean(&self) -> Result<(), PoisonError> {
|
pub fn clean(&self) -> Result<(), PoisonError> {
|
||||||
if *self.is_clean.read()? {
|
if *self.is_clean.read()? {
|
||||||
|
@ -16,7 +16,7 @@ use serde::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Block, BuiltInFunction, Evaluation, Type, WithPosition},
|
abstract_tree::{AbstractNode, Block, BuiltInFunction, Evaluation, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{PoisonError, RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,14 +77,12 @@ impl Value {
|
|||||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
value_parameters: Option<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,
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,13 +739,12 @@ impl Ord for ValueInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
type_parameters: Option<Vec<Identifier>>,
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
body: Block,
|
body: Block,
|
||||||
context_template: Context,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
@ -756,21 +753,15 @@ impl Function {
|
|||||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
body: Block,
|
body: Block,
|
||||||
context_template: Context,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_parameters,
|
value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
context_template,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -790,68 +781,4 @@ impl Function {
|
|||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
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,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(value_parameters) = &self.value_parameters {
|
|
||||||
for (identifier, r#type) in 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 {
|
|
||||||
self.type_parameters == other.type_parameters
|
|
||||||
&& self.value_parameters == other.value_parameters
|
|
||||||
&& self.return_type == other.return_type
|
|
||||||
&& self.body == other.body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for Function {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Function {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
let type_params_cmp = self.type_parameters.cmp(&other.type_parameters);
|
|
||||||
|
|
||||||
if type_params_cmp.is_eq() {
|
|
||||||
let value_params_cmp = self.value_parameters.cmp(&other.value_parameters);
|
|
||||||
|
|
||||||
if value_params_cmp.is_eq() {
|
|
||||||
let return_cmp = self.return_type.cmp(&other.return_type);
|
|
||||||
|
|
||||||
if return_cmp.is_eq() {
|
|
||||||
self.body.cmp(&other.body)
|
|
||||||
} else {
|
|
||||||
return_cmp
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value_params_cmp
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type_params_cmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
error::{DustError, TypeConflict, ValidationError},
|
error::{DustError, TypeConflict, ValidationError},
|
||||||
|
identifier::Identifier,
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,15 +70,11 @@ fn scope() {
|
|||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.errors(),
|
.errors(),
|
||||||
&vec![DustError::Validation {
|
&vec![DustError::Validation {
|
||||||
error: ValidationError::TypeCheck {
|
error: ValidationError::VariableNotFound {
|
||||||
conflict: TypeConflict {
|
identifier: Identifier::new("x"),
|
||||||
actual: Type::String,
|
position: (69, 70).into()
|
||||||
expected: Type::Integer
|
|
||||||
},
|
},
|
||||||
actual_position: (66, 71).into(),
|
position: (32, 102).into()
|
||||||
expected_position: Some((60, 63).into())
|
|
||||||
},
|
|
||||||
position: (55, 71).into()
|
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
abstract_tree::{Block, Expression, Statement, Type, WithPos},
|
abstract_tree::{Block, Expression, Statement, Type, WithPos},
|
||||||
context::Context,
|
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
@ -32,7 +31,6 @@ fn function_variable() {
|
|||||||
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)
|
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
count_slowly = fn (multiplier: int) {
|
count_slowly = fn (
|
||||||
|
multiplier: int,
|
||||||
|
sleep: fn (milliseconds: int),
|
||||||
|
write_line: fn (output: str),
|
||||||
|
) {
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
while i < 10 {
|
while i < 10 {
|
||||||
sleep_time = i * multiplier;
|
sleep_time = i * multiplier;
|
||||||
|
|
||||||
thread.sleep(sleep_time)
|
sleep(sleep_time)
|
||||||
io.write_line(i as str)
|
write_line(i as str)
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async {
|
async {
|
||||||
count_slowly(50)
|
count_slowly(50, thread.sleep, io.write_line)
|
||||||
count_slowly(100)
|
count_slowly(100, thread.sleep, io.write_line)
|
||||||
count_slowly(200)
|
count_slowly(200, thread.sleep, io.write_line)
|
||||||
count_slowly(250)
|
count_slowly(250, thread.sleep, io.write_line)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user