Continue standard library implementation
This commit is contained in:
parent
699576c4c7
commit
7e152f9f51
@ -56,7 +56,7 @@ impl AbstractNode for As {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
ValidationError::ExpectedValueStatement(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let r#type = self.constructor.construct(&context)?;
|
let r#type = self.constructor.construct(&context)?;
|
||||||
|
@ -71,7 +71,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
if let Some(r#type) = self.function_expression.expected_type(outer_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::ExpectedValueStatement(
|
||||||
self.function_expression.position(),
|
self.function_expression.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
@ -102,12 +102,13 @@ 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) =
|
let r#type =
|
||||||
expression.expected_type(outer_context)?
|
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::ExpectedValueStatement(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
self.context.set_type(identifier.clone(), r#type)?;
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
@ -157,7 +158,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(function_position),
|
ValidationError::ExpectedValueStatement(function_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -186,7 +187,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedValue(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -236,7 +237,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedValue(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
let expression_type = self.function_expression.expected_type(context)?.ok_or(
|
let expression_type = self.function_expression.expected_type(context)?.ok_or(
|
||||||
ValidationError::ExpectedExpression(self.function_expression.position()),
|
ValidationError::ExpectedValueStatement(self.function_expression.position()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (type_parameters, return_type) = if let Type::Function {
|
let (type_parameters, return_type) = if let Type::Function {
|
||||||
|
@ -60,7 +60,7 @@ impl AbstractNode for IfElse {
|
|||||||
let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? {
|
let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
self.if_expression.position(),
|
self.if_expression.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
@ -123,7 +123,7 @@ impl AbstractNode for IfElse {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(if_position),
|
ValidationError::ExpectedValueStatement(if_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ impl AbstractNode for IfElse {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
ValidationError::ExpectedValueStatement(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,14 +37,16 @@ impl AbstractNode for ListIndex {
|
|||||||
let collection_type = if let Some(r#type) = self.collection.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::ExpectedValueStatement(
|
||||||
self.collection.position(),
|
self.collection.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let index_type = if let Some(r#type) = self.index.expected_type(context)? {
|
let index_type = if let Some(r#type) = self.index.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(self.index.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
self.index.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
match collection_type {
|
match collection_type {
|
||||||
@ -82,7 +84,7 @@ impl AbstractNode for ListIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(left_position),
|
ValidationError::ExpectedValueStatement(left_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let right_position = self.index.position();
|
let right_position = self.index.position();
|
||||||
@ -91,7 +93,7 @@ impl AbstractNode for ListIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(right_position),
|
ValidationError::ExpectedValueStatement(right_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,7 +121,7 @@ impl AbstractNode for ListIndex {
|
|||||||
let left_type = if let Some(r#type) = self.collection.expected_type(_context)? {
|
let left_type = if let Some(r#type) = self.collection.expected_type(_context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
self.collection.position(),
|
self.collection.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
@ -77,12 +77,12 @@ impl AbstractNode for Logic {
|
|||||||
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(left.position()));
|
return Err(ValidationError::ExpectedValueStatement(left.position()));
|
||||||
};
|
};
|
||||||
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(right.position()));
|
return Err(ValidationError::ExpectedValueStatement(right.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
left_type
|
left_type
|
||||||
@ -102,12 +102,12 @@ impl AbstractNode for Logic {
|
|||||||
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(left.position()));
|
return Err(ValidationError::ExpectedValueStatement(left.position()));
|
||||||
};
|
};
|
||||||
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(right.position()));
|
return Err(ValidationError::ExpectedValueStatement(right.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Boolean = left_type {
|
if let Type::Boolean = left_type {
|
||||||
@ -134,7 +134,9 @@ impl AbstractNode for Logic {
|
|||||||
let expression_type = if let Some(r#type) = expression.expected_type(context)? {
|
let expression_type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Boolean = expression_type {
|
if let Type::Boolean = expression_type {
|
||||||
@ -161,7 +163,7 @@ impl AbstractNode for Logic {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
ValidationError::ExpectedValueStatement(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,7 +177,7 @@ impl AbstractNode for Logic {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
ValidationError::ExpectedValueStatement(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ impl AbstractNode for MapIndex {
|
|||||||
let collection_type = if let Some(r#type) = self.collection.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::ExpectedValueStatement(
|
||||||
self.collection.position(),
|
self.collection.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
@ -71,7 +71,7 @@ impl AbstractNode for MapIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(collection_position),
|
ValidationError::ExpectedValueStatement(collection_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ impl AbstractNode for MapIndex {
|
|||||||
let collection_type = if let Some(r#type) = self.collection.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::ExpectedValueStatement(
|
||||||
self.collection.position(),
|
self.collection.position(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
@ -52,12 +52,12 @@ impl AbstractNode for Math {
|
|||||||
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(left.position()));
|
return Err(ValidationError::ExpectedValueStatement(left.position()));
|
||||||
};
|
};
|
||||||
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(right.position()));
|
return Err(ValidationError::ExpectedValueStatement(right.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Integer | Type::Float | Type::String = left_type {
|
if let Type::Integer | Type::Float | Type::String = left_type {
|
||||||
@ -83,12 +83,12 @@ impl AbstractNode for Math {
|
|||||||
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
let left_type = if let Some(r#type) = left.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(left.position()));
|
return Err(ValidationError::ExpectedValueStatement(left.position()));
|
||||||
};
|
};
|
||||||
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
let right_type = if let Some(r#type) = right.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(right.position()));
|
return Err(ValidationError::ExpectedValueStatement(right.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Integer | Type::Float = left_type {
|
if let Type::Integer | Type::Float = left_type {
|
||||||
@ -116,7 +116,7 @@ impl AbstractNode for Math {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -341,12 +341,12 @@ impl AbstractNode for Math {
|
|||||||
let left_type = if let Some(r#type) = left.expected_type(_context)? {
|
let left_type = if let Some(r#type) = left.expected_type(_context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(left.position()));
|
return Err(ValidationError::ExpectedValueStatement(left.position()));
|
||||||
};
|
};
|
||||||
let right_type = if let Some(r#type) = right.expected_type(_context)? {
|
let right_type = if let Some(r#type) = right.expected_type(_context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(right.position()));
|
return Err(ValidationError::ExpectedValueStatement(right.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Float = left_type {
|
if let Type::Float = left_type {
|
||||||
|
@ -120,26 +120,6 @@ impl AbstractTree {
|
|||||||
AbstractTree(statements)
|
AbstractTree(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
|
||||||
for statement in &self.0 {
|
|
||||||
statement.define_types(context)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn validate(
|
|
||||||
&self,
|
|
||||||
context: &Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
for statement in &self.0 {
|
|
||||||
statement.validate(context, manage_memory)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
self,
|
self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@ -206,6 +186,42 @@ impl Index<usize> for AbstractTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AbstractNode for AbstractTree {
|
||||||
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
|
for statement in &self.0 {
|
||||||
|
statement.define_types(context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
for statement in &self.0 {
|
||||||
|
statement.validate(context, manage_memory)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
self,
|
||||||
|
context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
let mut previous = None;
|
||||||
|
|
||||||
|
for statement in self.0 {
|
||||||
|
previous = statement.evaluate(context, manage_memory)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(previous)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
self.0.last().unwrap().expected_type(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait AbstractNode {
|
pub trait AbstractNode {
|
||||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError>;
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError>;
|
||||||
|
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
use std::{fmt::Display, fs::read_to_string, path::Path};
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
fs::read_to_string,
|
||||||
|
path::Path,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -12,43 +17,53 @@ use crate::{
|
|||||||
Type,
|
Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation};
|
use super::{AbstractNode, AbstractTree, Evaluation};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Use {
|
pub struct Use {
|
||||||
path: String,
|
path: String,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
abstract_tree: Arc<RwLock<Option<AbstractTree>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Use {
|
impl Use {
|
||||||
pub fn new(path: String) -> Self {
|
pub fn new(path: String) -> Self {
|
||||||
Self { path }
|
Self {
|
||||||
|
path,
|
||||||
|
abstract_tree: Arc::new(RwLock::new(None)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for Use {
|
impl AbstractNode for Use {
|
||||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
match self.path.as_str() {
|
let abstract_tree = match self.path.as_str() {
|
||||||
"std.io" => std_io_compiled().define_types(context),
|
"std.fs" => std_fs_compiled().clone(),
|
||||||
|
"std.json" => std_json_compiled().clone(),
|
||||||
|
"std.io" => std_io_compiled().clone(),
|
||||||
|
"std.thread" => std_thread_compiled().clone(),
|
||||||
_ => {
|
_ => {
|
||||||
if Path::new(&self.path).exists() {
|
if Path::new(&self.path).exists() {
|
||||||
Ok(())
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::CannotUsePath(self.path.clone()))
|
return Err(ValidationError::CannotUsePath(self.path.clone()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_tree.define_types(_context)?;
|
||||||
|
|
||||||
|
*self.abstract_tree.write()? = Some(abstract_tree);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
match self.path.as_str() {
|
if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() {
|
||||||
"std.io" => std_io_compiled().validate(context, manage_memory),
|
abstract_tree.validate(context, manage_memory)
|
||||||
_ => {
|
|
||||||
if Path::new(&self.path).exists() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::CannotUsePath(self.path.clone()))
|
Err(ValidationError::Uninitialized)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,39 +72,21 @@ impl AbstractNode for Use {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let abstact_tree = match self.path.as_str() {
|
if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() {
|
||||||
"std.fs" => std_fs_compiled().clone(),
|
abstract_tree.clone().evaluate(context, manage_memory)
|
||||||
"std.io" => std_io_compiled().clone(),
|
} else {
|
||||||
"std.json" => std_json_compiled().clone(),
|
Err(RuntimeError::ValidationFailure(
|
||||||
"std.thread" => std_thread_compiled().clone(),
|
ValidationError::Uninitialized,
|
||||||
path => {
|
))
|
||||||
let file_contents = read_to_string(path)?;
|
|
||||||
let tokens = lex(&file_contents).map_err(|errors| RuntimeError::Use(errors))?;
|
|
||||||
let abstract_tree = parser(false)
|
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
|
||||||
.into_result()
|
|
||||||
.map_err(|errors| {
|
|
||||||
RuntimeError::Use(
|
|
||||||
errors
|
|
||||||
.into_iter()
|
|
||||||
.map(|error| DustError::from(error))
|
|
||||||
.collect::<Vec<DustError>>(),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
abstract_tree
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
abstact_tree
|
|
||||||
.run(context, manage_memory)
|
|
||||||
.map_err(|errors| RuntimeError::Use(errors))?;
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
todo!()
|
if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() {
|
||||||
|
abstract_tree.expected_type(context)
|
||||||
|
} else {
|
||||||
|
Err(ValidationError::Uninitialized)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,3 +95,23 @@ impl Display for Use {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Use {}
|
||||||
|
|
||||||
|
impl PartialEq for Use {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Use {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Use {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -127,14 +127,16 @@ impl AbstractNode for ValueNode {
|
|||||||
let first_item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
let first_item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(first_item.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
first_item.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
for item in items {
|
for item in items {
|
||||||
let item_type = if let Some(r#type) = item.expected_type(context)? {
|
let item_type = if let Some(r#type) = item.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(item.position()));
|
return Err(ValidationError::ExpectedValueStatement(item.position()));
|
||||||
};
|
};
|
||||||
|
|
||||||
first_item_type.check(&item_type).map_err(|conflict| {
|
first_item_type.check(&item_type).map_err(|conflict| {
|
||||||
@ -178,7 +180,9 @@ impl AbstractNode for ValueNode {
|
|||||||
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
let expected_type = constructor.clone().construct(&context)?;
|
let expected_type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
@ -213,9 +217,13 @@ impl AbstractNode for ValueNode {
|
|||||||
),
|
),
|
||||||
r#type,
|
r#type,
|
||||||
),
|
),
|
||||||
(None, Some(_)) => return Err(ValidationError::ExpectedValue(body.position)),
|
(None, Some(_)) => {
|
||||||
|
return Err(ValidationError::ExpectedNonValueStatement(body.position))
|
||||||
|
}
|
||||||
(Some(constructor), None) => {
|
(Some(constructor), None) => {
|
||||||
return Err(ValidationError::ExpectedExpression(constructor.position()))
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
constructor.position(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
(None, None) => return Ok(()),
|
(None, None) => return Ok(()),
|
||||||
};
|
};
|
||||||
@ -252,7 +260,9 @@ impl AbstractNode for ValueNode {
|
|||||||
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
expected_type.check(&actual_type).map_err(|conflict| {
|
expected_type.check(&actual_type).map_err(|conflict| {
|
||||||
@ -292,7 +302,7 @@ impl AbstractNode for ValueNode {
|
|||||||
values.push(value);
|
values.push(value);
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +325,7 @@ impl AbstractNode for ValueNode {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -334,7 +344,7 @@ impl AbstractNode for ValueNode {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -387,7 +397,7 @@ impl AbstractNode for ValueNode {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::ExpectedValueStatement(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -422,7 +432,9 @@ impl AbstractNode for ValueNode {
|
|||||||
let item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
let item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(first_item.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
first_item.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Type::List {
|
Type::List {
|
||||||
@ -498,7 +510,9 @@ impl AbstractNode for ValueNode {
|
|||||||
let r#type = if let Some(r#type) = expression.expected_type(context)? {
|
let r#type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(expression.position()));
|
return Err(ValidationError::ExpectedValueStatement(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
types.push((
|
types.push((
|
||||||
|
@ -63,7 +63,7 @@ impl AbstractNode for While {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(expression_position),
|
ValidationError::ExpectedValueStatement(expression_position),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
abstract_tree::Type,
|
abstract_tree::Type,
|
||||||
error::{PoisonError, ValidationError},
|
error::{PoisonError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
|
standard_library::core_context,
|
||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
@ -34,6 +35,16 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_with_std_core(parent: Option<Context>) -> Result<Self, PoisonError> {
|
||||||
|
let new = Context::with_variables_from(core_context())?;
|
||||||
|
|
||||||
|
if let Some(context) = parent {
|
||||||
|
new.set_parent(context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(new)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_variables_from(other: &Context) -> Result<Self, PoisonError> {
|
pub fn with_variables_from(other: &Context) -> Result<Self, PoisonError> {
|
||||||
let variables = other.data.read()?.variables.clone();
|
let variables = other.data.read()?.variables.clone();
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ impl PartialEq for RuntimeError {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
|
/// A node needs to be initialized before it can be validated.
|
||||||
|
Uninitialized,
|
||||||
BuiltInFunctionFailure(&'static str),
|
BuiltInFunctionFailure(&'static str),
|
||||||
CannotAssignToNone(SourcePosition),
|
CannotAssignToNone(SourcePosition),
|
||||||
CannotIndex {
|
CannotIndex {
|
||||||
@ -138,12 +140,12 @@ pub enum ValidationError {
|
|||||||
actual: Type,
|
actual: Type,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
},
|
},
|
||||||
ExpectedValue(SourcePosition),
|
|
||||||
FullTypeNotKnown {
|
FullTypeNotKnown {
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
},
|
},
|
||||||
ExpectedExpression(SourcePosition),
|
ExpectedValueStatement(SourcePosition),
|
||||||
|
ExpectedNonValueStatement(SourcePosition),
|
||||||
RwLockPoison(PoisonError),
|
RwLockPoison(PoisonError),
|
||||||
TypeCheck {
|
TypeCheck {
|
||||||
/// The mismatch that caused the error.
|
/// The mismatch that caused the error.
|
||||||
|
@ -341,9 +341,13 @@ impl InterpreterError {
|
|||||||
.with_message(format!("This has type {}.", index_type.fg(type_color),)),
|
.with_message(format!("This has type {}.", index_type.fg(type_color),)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
ValidationError::ExpectedExpression(position) => builder.add_label(
|
ValidationError::ExpectedValueStatement(position) => builder.add_label(
|
||||||
Label::new((self.source_id.clone(), position.0..position.1))
|
Label::new((self.source_id.clone(), position.0..position.1))
|
||||||
.with_message("Expected a statement that ends in an expression."),
|
.with_message("Expected a statement that yields a value."),
|
||||||
|
),
|
||||||
|
ValidationError::ExpectedNonValueStatement(position) => builder.add_label(
|
||||||
|
Label::new((self.source_id.clone(), position.0..position.1))
|
||||||
|
.with_message("Expected a statement that does not yield a value."),
|
||||||
),
|
),
|
||||||
ValidationError::ExpectedFunction { actual, position } => builder.add_label(
|
ValidationError::ExpectedFunction { actual, position } => builder.add_label(
|
||||||
Label::new((self.source_id.clone(), position.0..position.1)).with_message(
|
Label::new((self.source_id.clone(), position.0..position.1)).with_message(
|
||||||
@ -353,7 +357,6 @@ impl InterpreterError {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ValidationError::ExpectedValue(_) => todo!(),
|
|
||||||
ValidationError::FieldNotFound {
|
ValidationError::FieldNotFound {
|
||||||
identifier,
|
identifier,
|
||||||
position,
|
position,
|
||||||
@ -418,6 +421,7 @@ impl InterpreterError {
|
|||||||
ValidationError::BuiltInFunctionFailure(reason) => builder
|
ValidationError::BuiltInFunctionFailure(reason) => builder
|
||||||
.add_label(Label::new((self.source_id.clone(), 0..0)).with_message(reason)),
|
.add_label(Label::new((self.source_id.clone(), 0..0)).with_message(reason)),
|
||||||
ValidationError::CannotUsePath(_) => todo!(),
|
ValidationError::CannotUsePath(_) => todo!(),
|
||||||
|
ValidationError::Uninitialized => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, OnceLock};
|
||||||
|
|
||||||
use crate::{abstract_tree::AbstractTree, lexer::lex, parser};
|
use crate::{
|
||||||
|
abstract_tree::{AbstractNode, AbstractTree},
|
||||||
|
context::Context,
|
||||||
|
lexer::lex,
|
||||||
|
parser,
|
||||||
|
};
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
pub fn std_full_compiled() -> [AbstractTree; 5] {
|
pub fn std_full_compiled() -> [AbstractTree; 5] {
|
||||||
@ -19,6 +24,27 @@ pub const STD_IO: &str = include_str!("../../std/io.ds");
|
|||||||
pub const STD_JSON: &str = include_str!("../../std/json.ds");
|
pub const STD_JSON: &str = include_str!("../../std/json.ds");
|
||||||
pub const STD_THREAD: &str = include_str!("../../std/thread.ds");
|
pub const STD_THREAD: &str = include_str!("../../std/thread.ds");
|
||||||
|
|
||||||
|
static CORE_CONTEXT: OnceLock<Context> = OnceLock::new();
|
||||||
|
|
||||||
|
pub fn core_context<'a>() -> &'a Context {
|
||||||
|
CORE_CONTEXT.get_or_init(|| {
|
||||||
|
let context = Context::new(None);
|
||||||
|
let std_core = std_core_compiled().clone();
|
||||||
|
|
||||||
|
std_core
|
||||||
|
.define_types(&context)
|
||||||
|
.expect("Failed to define types for std.core");
|
||||||
|
std_core
|
||||||
|
.validate(&context, true)
|
||||||
|
.expect("Failed to validate std.core");
|
||||||
|
std_core
|
||||||
|
.evaluate(&context, true)
|
||||||
|
.expect("Failed to evaluate std.core");
|
||||||
|
|
||||||
|
context
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
static CORE_SOURCE: OnceLock<(Arc<str>, Arc<str>)> = OnceLock::new();
|
static CORE_SOURCE: OnceLock<(Arc<str>, Arc<str>)> = OnceLock::new();
|
||||||
|
|
||||||
pub fn core_source<'a>() -> &'a (Arc<str>, Arc<str>) {
|
pub fn core_source<'a>() -> &'a (Arc<str>, Arc<str>) {
|
||||||
@ -42,11 +68,11 @@ static STD_CORE_COMPILED: OnceLock<AbstractTree> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_core_compiled<'a>() -> &'a AbstractTree {
|
pub fn std_core_compiled<'a>() -> &'a AbstractTree {
|
||||||
STD_CORE_COMPILED.get_or_init(|| {
|
STD_CORE_COMPILED.get_or_init(|| {
|
||||||
let tokens = lex(STD_CORE).expect("Failed to lex.");
|
let tokens = lex(STD_CORE).expect("Failed to lex");
|
||||||
let abstract_tree = parser(true)
|
let abstract_tree = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
.expect("Failed to parse.");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
abstract_tree
|
abstract_tree
|
||||||
})
|
})
|
||||||
@ -56,11 +82,11 @@ static STD_FS_COMPILED: OnceLock<AbstractTree> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_fs_compiled<'a>() -> &'a AbstractTree {
|
pub fn std_fs_compiled<'a>() -> &'a AbstractTree {
|
||||||
STD_FS_COMPILED.get_or_init(|| {
|
STD_FS_COMPILED.get_or_init(|| {
|
||||||
let tokens = lex(STD_FS).expect("Failed to lex.");
|
let tokens = lex(STD_FS).expect("Failed to lex");
|
||||||
let abstract_tree = parser(true)
|
let abstract_tree = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
.expect("Failed to parse.");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
abstract_tree
|
abstract_tree
|
||||||
})
|
})
|
||||||
@ -70,11 +96,11 @@ static STD_IO_COMPILED: OnceLock<AbstractTree> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_io_compiled<'a>() -> &'a AbstractTree {
|
pub fn std_io_compiled<'a>() -> &'a AbstractTree {
|
||||||
STD_IO_COMPILED.get_or_init(|| {
|
STD_IO_COMPILED.get_or_init(|| {
|
||||||
let tokens = lex(STD_IO).expect("Failed to lex.");
|
let tokens = lex(STD_IO).expect("Failed to lex");
|
||||||
let abstract_tree = parser(true)
|
let abstract_tree = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
.expect("Failed to parse.");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
abstract_tree
|
abstract_tree
|
||||||
})
|
})
|
||||||
@ -84,11 +110,11 @@ static STD_JSON_COMPILED: OnceLock<AbstractTree> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_json_compiled<'a>() -> &'a AbstractTree {
|
pub fn std_json_compiled<'a>() -> &'a AbstractTree {
|
||||||
STD_JSON_COMPILED.get_or_init(|| {
|
STD_JSON_COMPILED.get_or_init(|| {
|
||||||
let tokens = lex(STD_JSON).expect("Failed to lex.");
|
let tokens = lex(STD_JSON).expect("Failed to lex");
|
||||||
let abstract_tree = parser(true)
|
let abstract_tree = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
.expect("Failed to parse.");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
abstract_tree
|
abstract_tree
|
||||||
})
|
})
|
||||||
@ -98,11 +124,11 @@ static STD_THREAD_COMPILED: OnceLock<AbstractTree> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn std_thread_compiled<'a>() -> &'a AbstractTree {
|
pub fn std_thread_compiled<'a>() -> &'a AbstractTree {
|
||||||
STD_THREAD_COMPILED.get_or_init(|| {
|
STD_THREAD_COMPILED.get_or_init(|| {
|
||||||
let tokens = lex(STD_THREAD).expect("Failed to lex.");
|
let tokens = lex(STD_THREAD).expect("Failed to lex");
|
||||||
let abstract_tree = parser(true)
|
let abstract_tree = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
.expect("Failed to parse.");
|
.expect("Failed to parse");
|
||||||
|
|
||||||
abstract_tree
|
abstract_tree
|
||||||
})
|
})
|
||||||
|
@ -56,7 +56,7 @@ fn main() {
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let context = Context::new(None);
|
let context = Context::new_with_std_core(None).unwrap();
|
||||||
let interpreter = Interpreter::new(context.clone());
|
let interpreter = Interpreter::new(context.clone());
|
||||||
|
|
||||||
let (source_id, source): (Arc<str>, Arc<str>) = if let Some(path) = args.path {
|
let (source_id, source): (Arc<str>, Arc<str>) = if let Some(path) = args.path {
|
||||||
|
Loading…
Reference in New Issue
Block a user