Begin refactoring built-ins
This commit is contained in:
parent
6bdefd0698
commit
34cea3518d
@ -70,60 +70,6 @@ impl AbstractNode for Assignment {
|
|||||||
context.set_type(self.identifier.node.clone(), statement_type.clone())?;
|
context.set_type(self.identifier.node.clone(), statement_type.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
|
||||||
let relevant_statement = self.statement.last_evaluated_statement();
|
|
||||||
let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
|
|
||||||
r#type
|
|
||||||
} else {
|
|
||||||
return Err(ValidationError::CannotAssignToNone(
|
|
||||||
self.statement.position(),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(constructor) = &self.constructor {
|
|
||||||
let r#type = constructor.clone().construct(&context)?;
|
|
||||||
|
|
||||||
r#type
|
|
||||||
.check(&statement_type)
|
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
|
||||||
conflict,
|
|
||||||
actual_position: self.statement.position(),
|
|
||||||
expected_position: Some(constructor.position()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
context.set_type(self.identifier.node.clone(), r#type.clone())?;
|
|
||||||
} else {
|
|
||||||
context.set_type(self.identifier.node.clone(), statement_type.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.statement.validate(context, manage_memory)?;
|
|
||||||
|
|
||||||
if let (
|
|
||||||
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
|
|
||||||
identifier,
|
|
||||||
type_arguments,
|
|
||||||
})),
|
|
||||||
Statement::Expression(Expression::Value(_)),
|
|
||||||
Type::Enum {
|
|
||||||
type_parameters, ..
|
|
||||||
},
|
|
||||||
) = (&self.constructor, relevant_statement, &statement_type)
|
|
||||||
{
|
|
||||||
if let (Some(parameters), Some(arguments)) = (type_parameters, type_arguments) {
|
|
||||||
if parameters.len() != arguments.len() {
|
|
||||||
return Err(ValidationError::FullTypeNotKnown {
|
|
||||||
identifier: identifier.node.clone(),
|
|
||||||
position: self.constructor.clone().unwrap().position(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) =
|
if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) =
|
||||||
(&self.constructor, relevant_statement)
|
(&self.constructor, relevant_statement)
|
||||||
{
|
{
|
||||||
@ -161,6 +107,43 @@ impl AbstractNode for Assignment {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
let relevant_statement = self.statement.last_evaluated_statement();
|
||||||
|
let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::CannotAssignToNone(
|
||||||
|
self.statement.position(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.statement.validate(context, manage_memory)?;
|
||||||
|
|
||||||
|
if let (
|
||||||
|
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||||
|
identifier,
|
||||||
|
type_arguments,
|
||||||
|
})),
|
||||||
|
Type::Enum {
|
||||||
|
type_parameters, ..
|
||||||
|
},
|
||||||
|
) = (&self.constructor, &statement_type)
|
||||||
|
{
|
||||||
|
if let (Some(parameters), Some(arguments)) = (type_parameters, type_arguments) {
|
||||||
|
if parameters.len() != arguments.len() {
|
||||||
|
return Err(ValidationError::FullTypeNotKnown {
|
||||||
|
identifier: identifier.node.clone(),
|
||||||
|
position: self.constructor.clone().unwrap().position(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
|
118
dust-lang/src/abstract_tree/built_in_function.rs
Normal file
118
dust-lang/src/abstract_tree/built_in_function.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
use std::{
|
||||||
|
array,
|
||||||
|
fs::read_to_string,
|
||||||
|
io::{stdin, stdout, Write},
|
||||||
|
slice,
|
||||||
|
sync::OnceLock,
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rayon::iter::IntoParallelIterator;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
context::Context,
|
||||||
|
error::{RuntimeError, ValidationError},
|
||||||
|
identifier::Identifier,
|
||||||
|
value::{Function, ValueInner},
|
||||||
|
Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
AbstractNode, Block, Evaluation, Expression, Statement, Type, TypeConstructor, WithPos,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum BuiltInExpression {
|
||||||
|
Length(BuiltInFunctionCall<Length>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BuiltInFunctionCall<F> {
|
||||||
|
function: F,
|
||||||
|
context: Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FunctionLogic {
|
||||||
|
fn type_parameters() -> Option<impl IntoIterator<Item = (Identifier, Type)>>;
|
||||||
|
fn value_parameters() -> impl IntoIterator<Item = Identifier>;
|
||||||
|
fn return_type() -> Type;
|
||||||
|
fn call(
|
||||||
|
self,
|
||||||
|
context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: FunctionLogic> AbstractNode for BuiltInFunctionCall<F> {
|
||||||
|
fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
|
||||||
|
if let Some(type_arguments) = F::type_parameters() {
|
||||||
|
for (identifier, r#type) in type_arguments {
|
||||||
|
self.context.set_type(identifier, r#type)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
self,
|
||||||
|
_: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
self.function.call(&self.context, manage_memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(Some(F::return_type()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Length {
|
||||||
|
argument: Expression,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionLogic for Length {
|
||||||
|
fn type_parameters() -> Option<impl IntoIterator<Item = (Identifier, Type)>> {
|
||||||
|
None::<array::IntoIter<(Identifier, Type), 0>>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_parameters() -> impl IntoIterator<Item = Identifier> {
|
||||||
|
[(Identifier::new("list"))].into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type() -> Type {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(
|
||||||
|
self,
|
||||||
|
context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
let position = self.argument.position();
|
||||||
|
let evaluation = self.argument.evaluate(context, manage_memory)?;
|
||||||
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::ExpectedExpression(position),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let list = if let ValueInner::List(list) = value.inner().as_ref() {
|
||||||
|
list
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::ExpectedList {
|
||||||
|
actual: value.r#type(context)?,
|
||||||
|
position,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(Evaluation::Return(Value::integer(list.len() as i64))))
|
||||||
|
}
|
||||||
|
}
|
@ -1,165 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fs::read_to_string,
|
|
||||||
io::{stdin, stdout, Write},
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
context::Context,
|
|
||||||
error::{RuntimeError, ValidationError},
|
|
||||||
value::ValueInner,
|
|
||||||
Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
||||||
pub enum BuiltInFunctionCall {
|
|
||||||
JsonParse(TypeConstructor, Expression),
|
|
||||||
Length(Expression),
|
|
||||||
ReadFile(Expression),
|
|
||||||
ReadLine,
|
|
||||||
Sleep(Expression),
|
|
||||||
WriteLine(Expression),
|
|
||||||
}
|
|
||||||
impl AbstractNode for BuiltInFunctionCall {
|
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
|
||||||
match self {
|
|
||||||
BuiltInFunctionCall::JsonParse(_, expression) => expression.define_types(_context),
|
|
||||||
BuiltInFunctionCall::Length(expression) => expression.define_types(_context),
|
|
||||||
BuiltInFunctionCall::ReadFile(expression) => expression.define_types(_context),
|
|
||||||
BuiltInFunctionCall::ReadLine => Ok(()),
|
|
||||||
BuiltInFunctionCall::Sleep(expression) => expression.define_types(_context),
|
|
||||||
BuiltInFunctionCall::WriteLine(expression) => expression.define_types(_context),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
|
||||||
match self {
|
|
||||||
BuiltInFunctionCall::JsonParse(_, expression) => {
|
|
||||||
expression.validate(_context, _manage_memory)
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::Length(expression) => {
|
|
||||||
expression.validate(_context, _manage_memory)
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::ReadFile(expression) => {
|
|
||||||
expression.validate(_context, _manage_memory)
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::ReadLine => Ok(()),
|
|
||||||
BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory),
|
|
||||||
BuiltInFunctionCall::WriteLine(expression) => {
|
|
||||||
expression.validate(_context, _manage_memory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evaluate(
|
|
||||||
self,
|
|
||||||
context: &Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
fn evaluate_expression(
|
|
||||||
expression: Expression,
|
|
||||||
context: &Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Value, RuntimeError> {
|
|
||||||
let position = expression.position();
|
|
||||||
let evaluation = expression.evaluate(context, _manage_memory)?;
|
|
||||||
|
|
||||||
if let Some(Evaluation::Return(value)) = evaluation {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedExpression(position),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
|
||||||
BuiltInFunctionCall::JsonParse(_type, expression) => {
|
|
||||||
let position = expression.position();
|
|
||||||
let value = evaluate_expression(expression, context, _manage_memory)?;
|
|
||||||
|
|
||||||
if let ValueInner::String(string) = value.inner().as_ref() {
|
|
||||||
let deserialized = serde_json::from_str(&string)?;
|
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(deserialized)))
|
|
||||||
} else {
|
|
||||||
Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedString {
|
|
||||||
actual: value.r#type(context)?,
|
|
||||||
position,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::Length(expression) => {
|
|
||||||
let value = evaluate_expression(expression, context, _manage_memory)?;
|
|
||||||
let length = if let ValueInner::List(list) = value.inner().as_ref() {
|
|
||||||
list.len() as i64
|
|
||||||
} else {
|
|
||||||
todo!("Create an error for this occurence.")
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::integer(length))))
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::ReadFile(expression) => {
|
|
||||||
let value = evaluate_expression(expression, context, _manage_memory)?;
|
|
||||||
let file_contents = if let ValueInner::String(path) = value.inner().as_ref() {
|
|
||||||
read_to_string(path)?
|
|
||||||
} else {
|
|
||||||
String::with_capacity(0)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::string(file_contents))))
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::ReadLine => {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
|
|
||||||
stdin().read_line(&mut buffer)?;
|
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::string(
|
|
||||||
buffer.strip_suffix('\n').unwrap_or(&buffer),
|
|
||||||
))))
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::Sleep(expression) => {
|
|
||||||
let value = evaluate_expression(expression, context, _manage_memory)?;
|
|
||||||
|
|
||||||
if let ValueInner::Integer(milliseconds) = value.inner().as_ref() {
|
|
||||||
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::WriteLine(expression) => {
|
|
||||||
let value = evaluate_expression(expression, context, _manage_memory)?;
|
|
||||||
|
|
||||||
if let ValueInner::String(output) = value.inner().as_ref() {
|
|
||||||
let mut stdout = stdout();
|
|
||||||
|
|
||||||
stdout.write_all(output.as_bytes())?;
|
|
||||||
stdout.write(b"\n")?;
|
|
||||||
stdout.flush()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
|
||||||
match self {
|
|
||||||
BuiltInFunctionCall::JsonParse(r#type, _) => {
|
|
||||||
Ok(Some(r#type.clone().construct(&context)?))
|
|
||||||
}
|
|
||||||
BuiltInFunctionCall::Length(_) => Ok(Some(Type::Integer)),
|
|
||||||
BuiltInFunctionCall::ReadFile(_) => Ok(Some(Type::String)),
|
|
||||||
BuiltInFunctionCall::ReadLine => Ok(Some(Type::String)),
|
|
||||||
BuiltInFunctionCall::Sleep(_) => Ok(None),
|
|
||||||
BuiltInFunctionCall::WriteLine(_) => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ use crate::{
|
|||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
value::ValueInner,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -47,24 +46,7 @@ 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(identifier) => {
|
Expression::Identifier(_) => Ok(()),
|
||||||
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),
|
||||||
@ -83,15 +65,9 @@ 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 = context.get_value(&identifier.node)?;
|
let found = context.add_expected_use(&identifier.node)?;
|
||||||
|
|
||||||
if let Some(value) = &found {
|
if 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 {
|
||||||
|
@ -2,7 +2,7 @@ pub mod r#as;
|
|||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
pub mod async_block;
|
pub mod async_block;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod built_in_function_call;
|
pub mod built_in_function;
|
||||||
pub mod enum_declaration;
|
pub mod enum_declaration;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
pub mod function_call;
|
pub mod function_call;
|
||||||
@ -29,7 +29,7 @@ pub use self::{
|
|||||||
assignment::{Assignment, AssignmentOperator},
|
assignment::{Assignment, AssignmentOperator},
|
||||||
async_block::AsyncBlock,
|
async_block::AsyncBlock,
|
||||||
block::Block,
|
block::Block,
|
||||||
built_in_function_call::BuiltInFunctionCall,
|
built_in_function::FunctionLogic,
|
||||||
enum_declaration::{EnumDeclaration, EnumVariant},
|
enum_declaration::{EnumDeclaration, EnumVariant},
|
||||||
expression::Expression,
|
expression::Expression,
|
||||||
function_call::FunctionCall,
|
function_call::FunctionCall,
|
||||||
|
@ -33,6 +33,7 @@ pub enum ValueNode {
|
|||||||
},
|
},
|
||||||
Function(FunctionNode),
|
Function(FunctionNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueNode {
|
impl ValueNode {
|
||||||
pub fn function(
|
pub fn function(
|
||||||
type_parameters: Option<Vec<Identifier>>,
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
@ -51,28 +52,28 @@ impl ValueNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for ValueNode {
|
impl AbstractNode for ValueNode {
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, outer_context: &Context) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
ValueNode::EnumInstance { content, .. } => {
|
ValueNode::EnumInstance { content, .. } => {
|
||||||
if let Some(expressions) = content {
|
if let Some(expressions) = content {
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
expression.define_types(_context)?;
|
expression.define_types(outer_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::List(expressions) => {
|
ValueNode::List(expressions) => {
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
expression.define_types(_context)?;
|
expression.define_types(outer_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Map(fields) => {
|
ValueNode::Map(fields) => {
|
||||||
for (_, _, expression) in fields {
|
for (_, _, expression) in fields {
|
||||||
expression.define_types(_context)?;
|
expression.define_types(outer_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Structure { fields, .. } => {
|
ValueNode::Structure { fields, .. } => {
|
||||||
for (_, expression) in fields {
|
for (_, expression) in fields {
|
||||||
expression.define_types(_context)?;
|
expression.define_types(outer_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Function(FunctionNode {
|
ValueNode::Function(FunctionNode {
|
||||||
@ -95,12 +96,12 @@ 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(&context_template)?;
|
let r#type = type_constructor.clone().construct(outer_context)?;
|
||||||
|
|
||||||
context_template.set_type(identifier.clone(), r#type)?;
|
context_template.set_type(identifier.clone(), r#type)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.node.define_types(_context)?;
|
body.node.define_types(context_template)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -169,7 +170,10 @@ impl AbstractNode for ValueNode {
|
|||||||
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(&context_template)?) {
|
||||||
(Some(constructor), Some(r#type)) => (
|
(Some(constructor), Some(r#type)) => (
|
||||||
(constructor.construct(context)?, constructor.position()),
|
(
|
||||||
|
constructor.construct(context_template)?,
|
||||||
|
constructor.position(),
|
||||||
|
),
|
||||||
r#type,
|
r#type,
|
||||||
),
|
),
|
||||||
(None, Some(_)) => return Err(ValidationError::ExpectedValue(body.position)),
|
(None, Some(_)) => return Err(ValidationError::ExpectedValue(body.position)),
|
||||||
@ -312,11 +316,10 @@ impl AbstractNode for ValueNode {
|
|||||||
context_template,
|
context_template,
|
||||||
}) => {
|
}) => {
|
||||||
let outer_context = context;
|
let outer_context = context;
|
||||||
let function_context = context_template.create_child();
|
|
||||||
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 {
|
||||||
let r#type = constructor.construct(&function_context)?;
|
let r#type = constructor.construct(&outer_context)?;
|
||||||
|
|
||||||
value_parameters.push((identifier, r#type));
|
value_parameters.push((identifier, r#type));
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,10 @@ pub enum ValidationError {
|
|||||||
actual: Type,
|
actual: Type,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
},
|
},
|
||||||
|
ExpectedList {
|
||||||
|
actual: Type,
|
||||||
|
position: SourcePosition,
|
||||||
|
},
|
||||||
ExpectedBoolean {
|
ExpectedBoolean {
|
||||||
actual: Type,
|
actual: Type,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
|
@ -49,7 +49,6 @@ pub enum Keyword {
|
|||||||
If,
|
If,
|
||||||
JsonParse,
|
JsonParse,
|
||||||
Length,
|
Length,
|
||||||
List,
|
|
||||||
Map,
|
Map,
|
||||||
None,
|
None,
|
||||||
Range,
|
Range,
|
||||||
@ -78,7 +77,6 @@ impl Display for Keyword {
|
|||||||
Keyword::Fn => write!(f, "fn"),
|
Keyword::Fn => write!(f, "fn"),
|
||||||
Keyword::Int => write!(f, "int"),
|
Keyword::Int => write!(f, "int"),
|
||||||
Keyword::If => write!(f, "if"),
|
Keyword::If => write!(f, "if"),
|
||||||
Keyword::List => write!(f, "list"),
|
|
||||||
Keyword::Map => write!(f, "map"),
|
Keyword::Map => write!(f, "map"),
|
||||||
Keyword::None => write!(f, "none"),
|
Keyword::None => write!(f, "none"),
|
||||||
Keyword::Range => write!(f, "range"),
|
Keyword::Range => write!(f, "range"),
|
||||||
@ -263,7 +261,6 @@ pub fn lexer<'src>() -> impl Parser<
|
|||||||
just("fn").to(Token::Keyword(Keyword::Fn)),
|
just("fn").to(Token::Keyword(Keyword::Fn)),
|
||||||
just("int").to(Token::Keyword(Keyword::Int)),
|
just("int").to(Token::Keyword(Keyword::Int)),
|
||||||
just("if").to(Token::Keyword(Keyword::If)),
|
just("if").to(Token::Keyword(Keyword::If)),
|
||||||
just("list").to(Token::Keyword(Keyword::List)),
|
|
||||||
just("map").to(Token::Keyword(Keyword::Map)),
|
just("map").to(Token::Keyword(Keyword::Map)),
|
||||||
just("none").to(Token::Keyword(Keyword::None)),
|
just("none").to(Token::Keyword(Keyword::None)),
|
||||||
just("range").to(Token::Keyword(Keyword::Range)),
|
just("range").to(Token::Keyword(Keyword::Range)),
|
||||||
|
@ -721,6 +721,22 @@ pub struct Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
|
pub fn new(
|
||||||
|
type_parameters: Option<Vec<Identifier>>,
|
||||||
|
value_parameters: Vec<(Identifier, Type)>,
|
||||||
|
return_type: Option<Type>,
|
||||||
|
body: Block,
|
||||||
|
context_template: Context,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
context_template,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn context_template(&self) -> &Context {
|
pub fn context_template(&self) -> &Context {
|
||||||
&self.context_template
|
&self.context_template
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user