1
0

Continue standard library implementation

This commit is contained in:
Jeff 2024-07-01 16:59:39 -04:00
parent 699576c4c7
commit 7e152f9f51
16 changed files with 232 additions and 137 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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