From 2e9a523058e6c227e6d21f34eab2e202ce4bb198 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 24 Jun 2024 08:17:06 -0400 Subject: [PATCH] Continue fixing built-in functions --- .../src/abstract_tree/built_in_function.rs | 33 +++++++++++-------- dust-lang/src/abstract_tree/function_call.rs | 10 +++++- dust-lang/src/abstract_tree/value_node.rs | 6 +++- dust-lang/src/lib.rs | 16 ++++----- std/io.ds | 4 +-- std/json.ds | 2 +- std/thread.ds | 2 +- 7 files changed, 46 insertions(+), 27 deletions(-) diff --git a/dust-lang/src/abstract_tree/built_in_function.rs b/dust-lang/src/abstract_tree/built_in_function.rs index 473d667..d6d6a37 100644 --- a/dust-lang/src/abstract_tree/built_in_function.rs +++ b/dust-lang/src/abstract_tree/built_in_function.rs @@ -35,7 +35,11 @@ impl BuiltInFunction { } } - pub fn call(&self, context: &Context, manage_memory: bool) -> Result { + pub fn call( + &self, + context: &Context, + manage_memory: bool, + ) -> Result, RuntimeError> { match self { BuiltInFunction::Length => Length::call(context, manage_memory), BuiltInFunction::ReadLine => ReadLine::call(context, manage_memory), @@ -49,7 +53,7 @@ impl BuiltInFunction { trait FunctionLogic { fn r#type() -> Type; - fn call(context: &Context, manage_memory: bool) -> Result; + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError>; } #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -67,7 +71,7 @@ impl FunctionLogic for Length { } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { let value = if let Some(value) = context.get_value(&Identifier::new("input"))? { value } else { @@ -83,7 +87,7 @@ impl FunctionLogic for Length { )); }; - Ok(Value::integer(list.len() as i64)) + Ok(Some(Value::integer(list.len() as i64))) } } @@ -95,11 +99,11 @@ impl FunctionLogic for ReadFile { Type::Function { type_parameters: None, value_parameters: None, - return_type: None, + return_type: Some(Box::new(Type::String)), } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { todo!() } } @@ -112,11 +116,11 @@ impl FunctionLogic for ReadLine { Type::Function { type_parameters: None, value_parameters: None, - return_type: None, + return_type: Some(Box::new(Type::String)), } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { todo!() } } @@ -133,7 +137,7 @@ impl FunctionLogic for Sleep { } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { todo!() } } @@ -150,7 +154,7 @@ impl FunctionLogic for WriteLine { } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { todo!() } } @@ -163,11 +167,14 @@ impl FunctionLogic for JsonParse { Type::Function { type_parameters: None, value_parameters: None, - return_type: None, + return_type: Some(Box::new(Type::Generic { + identifier: Identifier::new("T"), + concrete_type: None, + })), } } - fn call(context: &Context, manage_memory: bool) -> Result { + fn call(context: &Context, manage_memory: bool) -> Result, RuntimeError> { let target_type = if let Some(r#type) = context.get_type(&Identifier::new("T"))? { r#type } else { @@ -216,6 +223,6 @@ impl FunctionLogic for JsonParse { Ok(value) } - parse_value(&input, target_type) + parse_value(&input, target_type).map(|value| Some(value)) } } diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 34e0a3a..5d91caf 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -6,7 +6,7 @@ use crate::{ value::ValueInner, }; -use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor}; +use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor, ValueNode, WithPosition}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct FunctionCall { @@ -47,6 +47,14 @@ impl AbstractNode for FunctionCall { } fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { + if let Expression::Value(WithPosition { + node: ValueNode::BuiltInFunction(_), + .. + }) = self.function_expression.as_ref() + { + return Ok(()); + } + self.function_expression.validate(context, manage_memory)?; if let Some(value_arguments) = &self.value_arguments { diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 2dcd73d..1a93570 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -173,6 +173,8 @@ impl AbstractNode for ValueNode { { body.node.validate(&context_template, _manage_memory)?; + println!("beep"); + let ((expected_return, expected_position), actual_return) = match (return_type, body.node.expected_type(&context_template)?) { (Some(constructor), Some(r#type)) => ( @@ -372,7 +374,9 @@ impl AbstractNode for ValueNode { Value::structure(name, fields) } ValueNode::BuiltInFunction(built_in_function) => { - built_in_function.call(context, manage_memory)? + return built_in_function + .call(context, manage_memory) + .map(|value_option| value_option.map(|value| Evaluation::Return(value))); } }; diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 1f33f65..d431b85 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -109,12 +109,10 @@ impl Interpreter { } pub fn load_std(&self) -> Result<(), InterpreterError> { - let std_core_source: (Arc, Arc) = { - ( - Arc::from("std/core.ds"), - Arc::from(include_str!("../../std/core.ds")), - ) - }; + let std_core_source: (Arc, Arc) = ( + Arc::from("std/core.ds"), + Arc::from(include_str!("../../std/core.ds")), + ); let std_sources: [(Arc, Arc); 4] = [ ( Arc::from("std/fs.ds"), @@ -172,7 +170,6 @@ impl Interpreter { ) -> Result, InterpreterError> { let mut sources = self.sources.write().unwrap(); - sources.clear(); sources.push((source_id.clone(), source.clone())); let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError { @@ -431,7 +428,10 @@ impl InterpreterError { .with_message(format!("This has type {}.", index_type.fg(type_color),)), ]) } - ValidationError::ExpectedExpression(_) => todo!(), + ValidationError::ExpectedExpression(position) => builder.add_label( + Label::new((self.source_id.clone(), position.0..position.1)) + .with_message("Expected a statement that ends in an expression."), + ), ValidationError::ExpectedFunction { .. } => todo!(), ValidationError::ExpectedValue(_) => todo!(), ValidationError::FieldNotFound { diff --git a/std/io.ds b/std/io.ds index 004dd37..5300897 100644 --- a/std/io.ds +++ b/std/io.ds @@ -1,9 +1,9 @@ io = { read_line = fn () -> str { - __READ_LINE__ + __READ_LINE__() } write_line = fn (output: any) { - __WRITE_LINE__ output + __WRITE_LINE__(output) } } diff --git a/std/json.ds b/std/json.ds index 69c18b0..9c51554 100644 --- a/std/json.ds +++ b/std/json.ds @@ -1,5 +1,5 @@ json = { parse = fn |T| (input: str) -> T { - __JSON_PARSE__ T input + __JSON_PARSE__::(T)::(input) } } diff --git a/std/thread.ds b/std/thread.ds index 699e609..a692227 100644 --- a/std/thread.ds +++ b/std/thread.ds @@ -1,5 +1,5 @@ thread = { sleep = fn (milliseconds: int) { - __SLEEP__ milliseconds + __SLEEP__(milliseconds) } }