From 7e152f9f519da9c4ba61891c31181c6a440f4256 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 1 Jul 2024 16:59:39 -0400 Subject: [PATCH] Continue standard library implementation --- dust-lang/src/abstract_tree/as.rs | 2 +- dust-lang/src/abstract_tree/function_call.rs | 25 ++-- dust-lang/src/abstract_tree/if_else.rs | 6 +- dust-lang/src/abstract_tree/list_index.rs | 12 +- dust-lang/src/abstract_tree/logic.rs | 16 +-- dust-lang/src/abstract_tree/map_index.rs | 6 +- dust-lang/src/abstract_tree/math.rs | 14 +-- dust-lang/src/abstract_tree/mod.rs | 56 +++++---- dust-lang/src/abstract_tree/use.rs | 115 +++++++++++-------- dust-lang/src/abstract_tree/value_node.rs | 38 ++++-- dust-lang/src/abstract_tree/while.rs | 2 +- dust-lang/src/context.rs | 11 ++ dust-lang/src/error.rs | 6 +- dust-lang/src/lib.rs | 10 +- dust-lang/src/standard_library.rs | 48 ++++++-- dust-shell/src/main.rs | 2 +- 16 files changed, 232 insertions(+), 137 deletions(-) diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 49aa278..99c47b4 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -56,7 +56,7 @@ impl AbstractNode for As { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), + ValidationError::ExpectedValueStatement(expression_position), )); }; let r#type = self.constructor.construct(&context)?; diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index f199a78..999c9bd 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -71,7 +71,7 @@ impl AbstractNode for FunctionCall { if let Some(r#type) = self.function_expression.expected_type(outer_context)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.function_expression.position(), )); }; @@ -102,13 +102,14 @@ impl AbstractNode for FunctionCall { for ((identifier, _), expression) in parameters.iter().zip(arguments.into_iter()) { - let r#type = if let Some(r#type) = - expression.expected_type(outer_context)? - { - r#type - } else { - return Err(ValidationError::ExpectedExpression(expression.position())); - }; + let r#type = + if let Some(r#type) = expression.expected_type(outer_context)? { + r#type + } else { + return Err(ValidationError::ExpectedValueStatement( + expression.position(), + )); + }; self.context.set_type(identifier.clone(), r#type)?; } @@ -157,7 +158,7 @@ impl AbstractNode for FunctionCall { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(function_position), + ValidationError::ExpectedValueStatement(function_position), )); }; @@ -186,7 +187,7 @@ impl AbstractNode for FunctionCall { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedValue(position), + ValidationError::ExpectedValueStatement(position), )); }; @@ -236,7 +237,7 @@ impl AbstractNode for FunctionCall { value } else { 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, ValidationError> { 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 { diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index fecf5b7..a75cad8 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -60,7 +60,7 @@ impl AbstractNode for IfElse { let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.if_expression.position(), )); }; @@ -123,7 +123,7 @@ impl AbstractNode for IfElse { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(if_position), + ValidationError::ExpectedValueStatement(if_position), )); }; @@ -140,7 +140,7 @@ impl AbstractNode for IfElse { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), + ValidationError::ExpectedValueStatement(expression_position), )); }; diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 1c41f6b..92e463a 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -37,14 +37,16 @@ impl AbstractNode for ListIndex { let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.collection.position(), )); }; let index_type = if let Some(r#type) = self.index.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression(self.index.position())); + return Err(ValidationError::ExpectedValueStatement( + self.index.position(), + )); }; match collection_type { @@ -82,7 +84,7 @@ impl AbstractNode for ListIndex { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(left_position), + ValidationError::ExpectedValueStatement(left_position), )); }; let right_position = self.index.position(); @@ -91,7 +93,7 @@ impl AbstractNode for ListIndex { value } else { 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.collection.position(), )); }; diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 81827b2..0935748 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -77,12 +77,12 @@ impl AbstractNode for Logic { let left_type = if let Some(r#type) = left.expected_type(context)? { r#type } 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(right.position())); + return Err(ValidationError::ExpectedValueStatement(right.position())); }; left_type @@ -102,12 +102,12 @@ impl AbstractNode for Logic { let left_type = if let Some(r#type) = left.expected_type(context)? { r#type } 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(right.position())); + return Err(ValidationError::ExpectedValueStatement(right.position())); }; 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(expression.position())); + return Err(ValidationError::ExpectedValueStatement( + expression.position(), + )); }; if let Type::Boolean = expression_type { @@ -161,7 +163,7 @@ impl AbstractNode for Logic { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), + ValidationError::ExpectedValueStatement(expression_position), )); }; @@ -175,7 +177,7 @@ impl AbstractNode for Logic { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), + ValidationError::ExpectedValueStatement(expression_position), )); }; diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index f9049be..a91645b 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -37,7 +37,7 @@ impl AbstractNode for MapIndex { let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.collection.position(), )); }; @@ -71,7 +71,7 @@ impl AbstractNode for MapIndex { value } else { 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression( + return Err(ValidationError::ExpectedValueStatement( self.collection.position(), )); }; diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index 30785bd..ca24503 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -52,12 +52,12 @@ impl AbstractNode for Math { let left_type = if let Some(r#type) = left.expected_type(context)? { r#type } 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(right.position())); + return Err(ValidationError::ExpectedValueStatement(right.position())); }; 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)? { r#type } 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(right.position())); + return Err(ValidationError::ExpectedValueStatement(right.position())); }; if let Type::Integer | Type::Float = left_type { @@ -116,7 +116,7 @@ impl AbstractNode for Math { value } else { 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)? { r#type } 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(right.position())); + return Err(ValidationError::ExpectedValueStatement(right.position())); }; if let Type::Float = left_type { diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 4e3545b..a424dfa 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -120,26 +120,6 @@ impl AbstractTree { 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( self, context: &Context, @@ -206,6 +186,42 @@ impl Index 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, 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, ValidationError> { + self.0.last().unwrap().expected_type(context) + } +} + pub trait AbstractNode { fn define_types(&self, context: &Context) -> Result<(), ValidationError>; diff --git a/dust-lang/src/abstract_tree/use.rs b/dust-lang/src/abstract_tree/use.rs index cd0ae89..ffba015 100644 --- a/dust-lang/src/abstract_tree/use.rs +++ b/dust-lang/src/abstract_tree/use.rs @@ -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 serde::{Deserialize, Serialize}; @@ -12,43 +17,53 @@ use crate::{ 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 { path: String, + + #[serde(skip)] + abstract_tree: Arc>>, } impl Use { pub fn new(path: String) -> Self { - Self { path } + Self { + path, + abstract_tree: Arc::new(RwLock::new(None)), + } } } impl AbstractNode for Use { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { - match self.path.as_str() { - "std.io" => std_io_compiled().define_types(context), + fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + let abstract_tree = match self.path.as_str() { + "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() { - Ok(()) + todo!() } 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> { - match self.path.as_str() { - "std.io" => std_io_compiled().validate(context, manage_memory), - _ => { - if Path::new(&self.path).exists() { - Ok(()) - } else { - Err(ValidationError::CannotUsePath(self.path.clone())) - } - } + if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() { + abstract_tree.validate(context, manage_memory) + } else { + Err(ValidationError::Uninitialized) } } @@ -57,39 +72,21 @@ impl AbstractNode for Use { context: &Context, manage_memory: bool, ) -> Result, RuntimeError> { - let abstact_tree = match self.path.as_str() { - "std.fs" => std_fs_compiled().clone(), - "std.io" => std_io_compiled().clone(), - "std.json" => std_json_compiled().clone(), - "std.thread" => std_thread_compiled().clone(), - 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::>(), - ) - })?; - - abstract_tree - } - }; - - abstact_tree - .run(context, manage_memory) - .map_err(|errors| RuntimeError::Use(errors))?; - - Ok(None) + if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() { + abstract_tree.clone().evaluate(context, manage_memory) + } else { + Err(RuntimeError::ValidationFailure( + ValidationError::Uninitialized, + )) + } } fn expected_type(&self, context: &Context) -> Result, 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!() } } + +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 { + todo!() + } +} + +impl Ord for Use { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + todo!() + } +} diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 0b8aa78..20301bc 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -127,14 +127,16 @@ impl AbstractNode for ValueNode { let first_item_type = if let Some(r#type) = first_item.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression(first_item.position())); + return Err(ValidationError::ExpectedValueStatement( + first_item.position(), + )); }; for item in items { let item_type = if let Some(r#type) = item.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression(item.position())); + return Err(ValidationError::ExpectedValueStatement(item.position())); }; 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(expression.position())); + return Err(ValidationError::ExpectedValueStatement( + expression.position(), + )); }; let expected_type = constructor.clone().construct(&context)?; @@ -213,9 +217,13 @@ impl AbstractNode for ValueNode { ), r#type, ), - (None, Some(_)) => return Err(ValidationError::ExpectedValue(body.position)), + (None, Some(_)) => { + return Err(ValidationError::ExpectedNonValueStatement(body.position)) + } (Some(constructor), None) => { - return Err(ValidationError::ExpectedExpression(constructor.position())) + return Err(ValidationError::ExpectedValueStatement( + constructor.position(), + )) } (None, None) => return Ok(()), }; @@ -252,7 +260,9 @@ impl AbstractNode for ValueNode { let actual_type = if let Some(r#type) = expression.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression(expression.position())); + return Err(ValidationError::ExpectedValueStatement( + expression.position(), + )); }; expected_type.check(&actual_type).map_err(|conflict| { @@ -292,7 +302,7 @@ impl AbstractNode for ValueNode { values.push(value); } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(position), + ValidationError::ExpectedValueStatement(position), )); } } @@ -315,7 +325,7 @@ impl AbstractNode for ValueNode { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(position), + ValidationError::ExpectedValueStatement(position), )); }; @@ -334,7 +344,7 @@ impl AbstractNode for ValueNode { value } else { return Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(position), + ValidationError::ExpectedValueStatement(position), )); }; @@ -387,7 +397,7 @@ impl AbstractNode for ValueNode { value } else { 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)? { r#type } else { - return Err(ValidationError::ExpectedExpression(first_item.position())); + return Err(ValidationError::ExpectedValueStatement( + first_item.position(), + )); }; Type::List { @@ -498,7 +510,9 @@ impl AbstractNode for ValueNode { let r#type = if let Some(r#type) = expression.expected_type(context)? { r#type } else { - return Err(ValidationError::ExpectedExpression(expression.position())); + return Err(ValidationError::ExpectedValueStatement( + expression.position(), + )); }; types.push(( diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index d14dfdb..d4d1cf3 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -63,7 +63,7 @@ impl AbstractNode for While { Ok(value) } else { Err(RuntimeError::ValidationFailure( - ValidationError::ExpectedExpression(expression_position), + ValidationError::ExpectedValueStatement(expression_position), )) } }; diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 348f6d5..0931271 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -7,6 +7,7 @@ use crate::{ abstract_tree::Type, error::{PoisonError, ValidationError}, identifier::Identifier, + standard_library::core_context, value::ValueInner, Value, }; @@ -34,6 +35,16 @@ impl Context { } } + pub fn new_with_std_core(parent: Option) -> Result { + 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 { let variables = other.data.read()?.variables.clone(); diff --git a/dust-lang/src/error.rs b/dust-lang/src/error.rs index 6b72c9e..3e82e06 100644 --- a/dust-lang/src/error.rs +++ b/dust-lang/src/error.rs @@ -104,6 +104,8 @@ impl PartialEq for RuntimeError { #[derive(Debug, PartialEq)] pub enum ValidationError { + /// A node needs to be initialized before it can be validated. + Uninitialized, BuiltInFunctionFailure(&'static str), CannotAssignToNone(SourcePosition), CannotIndex { @@ -138,12 +140,12 @@ pub enum ValidationError { actual: Type, position: SourcePosition, }, - ExpectedValue(SourcePosition), FullTypeNotKnown { identifier: Identifier, position: SourcePosition, }, - ExpectedExpression(SourcePosition), + ExpectedValueStatement(SourcePosition), + ExpectedNonValueStatement(SourcePosition), RwLockPoison(PoisonError), TypeCheck { /// The mismatch that caused the error. diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 8d00dda..364c569 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -341,9 +341,13 @@ impl InterpreterError { .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)) - .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( Label::new((self.source_id.clone(), position.0..position.1)).with_message( @@ -353,7 +357,6 @@ impl InterpreterError { ), ), ), - ValidationError::ExpectedValue(_) => todo!(), ValidationError::FieldNotFound { identifier, position, @@ -418,6 +421,7 @@ impl InterpreterError { ValidationError::BuiltInFunctionFailure(reason) => builder .add_label(Label::new((self.source_id.clone(), 0..0)).with_message(reason)), ValidationError::CannotUsePath(_) => todo!(), + ValidationError::Uninitialized => todo!(), } } diff --git a/dust-lang/src/standard_library.rs b/dust-lang/src/standard_library.rs index 569bb6f..495cd8d 100644 --- a/dust-lang/src/standard_library.rs +++ b/dust-lang/src/standard_library.rs @@ -1,6 +1,11 @@ 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::*; 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_THREAD: &str = include_str!("../../std/thread.ds"); +static CORE_CONTEXT: OnceLock = 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, Arc)> = OnceLock::new(); pub fn core_source<'a>() -> &'a (Arc, Arc) { @@ -42,11 +68,11 @@ static STD_CORE_COMPILED: OnceLock = OnceLock::new(); pub fn std_core_compiled<'a>() -> &'a AbstractTree { 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) .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .expect("Failed to parse."); + .expect("Failed to parse"); abstract_tree }) @@ -56,11 +82,11 @@ static STD_FS_COMPILED: OnceLock = OnceLock::new(); pub fn std_fs_compiled<'a>() -> &'a AbstractTree { 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) .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .expect("Failed to parse."); + .expect("Failed to parse"); abstract_tree }) @@ -70,11 +96,11 @@ static STD_IO_COMPILED: OnceLock = OnceLock::new(); pub fn std_io_compiled<'a>() -> &'a AbstractTree { 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) .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .expect("Failed to parse."); + .expect("Failed to parse"); abstract_tree }) @@ -84,11 +110,11 @@ static STD_JSON_COMPILED: OnceLock = OnceLock::new(); pub fn std_json_compiled<'a>() -> &'a AbstractTree { 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) .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .expect("Failed to parse."); + .expect("Failed to parse"); abstract_tree }) @@ -98,11 +124,11 @@ static STD_THREAD_COMPILED: OnceLock = OnceLock::new(); pub fn std_thread_compiled<'a>() -> &'a AbstractTree { 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) .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .expect("Failed to parse."); + .expect("Failed to parse"); abstract_tree }) diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index 6c90b35..cac54fd 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -56,7 +56,7 @@ fn main() { .init(); 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 (source_id, source): (Arc, Arc) = if let Some(path) = args.path {