Continue fixing built-in functions

This commit is contained in:
Jeff 2024-06-24 08:17:06 -04:00
parent 18859cda77
commit 2e9a523058
7 changed files with 46 additions and 27 deletions

View File

@ -35,7 +35,11 @@ impl BuiltInFunction {
} }
} }
pub fn call(&self, context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> { pub fn call(
&self,
context: &Context,
manage_memory: bool,
) -> Result<Option<Value>, RuntimeError> {
match self { match self {
BuiltInFunction::Length => Length::call(context, manage_memory), BuiltInFunction::Length => Length::call(context, manage_memory),
BuiltInFunction::ReadLine => ReadLine::call(context, manage_memory), BuiltInFunction::ReadLine => ReadLine::call(context, manage_memory),
@ -49,7 +53,7 @@ impl BuiltInFunction {
trait FunctionLogic { trait FunctionLogic {
fn r#type() -> Type; fn r#type() -> Type;
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError>; fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError>;
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[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<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
let value = if let Some(value) = context.get_value(&Identifier::new("input"))? { let value = if let Some(value) = context.get_value(&Identifier::new("input"))? {
value value
} else { } 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::Function {
type_parameters: None, type_parameters: None,
value_parameters: None, value_parameters: None,
return_type: None, return_type: Some(Box::new(Type::String)),
} }
} }
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
todo!() todo!()
} }
} }
@ -112,11 +116,11 @@ impl FunctionLogic for ReadLine {
Type::Function { Type::Function {
type_parameters: None, type_parameters: None,
value_parameters: None, value_parameters: None,
return_type: None, return_type: Some(Box::new(Type::String)),
} }
} }
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
todo!() todo!()
} }
} }
@ -133,7 +137,7 @@ impl FunctionLogic for Sleep {
} }
} }
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
todo!() todo!()
} }
} }
@ -150,7 +154,7 @@ impl FunctionLogic for WriteLine {
} }
} }
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
todo!() todo!()
} }
} }
@ -163,11 +167,14 @@ impl FunctionLogic for JsonParse {
Type::Function { Type::Function {
type_parameters: None, type_parameters: None,
value_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<Value, RuntimeError> { fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError> {
let target_type = if let Some(r#type) = context.get_type(&Identifier::new("T"))? { let target_type = if let Some(r#type) = context.get_type(&Identifier::new("T"))? {
r#type r#type
} else { } else {
@ -216,6 +223,6 @@ impl FunctionLogic for JsonParse {
Ok(value) Ok(value)
} }
parse_value(&input, target_type) parse_value(&input, target_type).map(|value| Some(value))
} }
} }

View File

@ -6,7 +6,7 @@ use crate::{
value::ValueInner, 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)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionCall { pub struct FunctionCall {
@ -47,6 +47,14 @@ impl AbstractNode for FunctionCall {
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { 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)?; self.function_expression.validate(context, manage_memory)?;
if let Some(value_arguments) = &self.value_arguments { if let Some(value_arguments) = &self.value_arguments {

View File

@ -173,6 +173,8 @@ impl AbstractNode for ValueNode {
{ {
body.node.validate(&context_template, _manage_memory)?; body.node.validate(&context_template, _manage_memory)?;
println!("beep");
let ((expected_return, expected_position), actual_return) = let ((expected_return, expected_position), actual_return) =
match (return_type, body.node.expected_type(&context_template)?) { match (return_type, body.node.expected_type(&context_template)?) {
(Some(constructor), Some(r#type)) => ( (Some(constructor), Some(r#type)) => (
@ -372,7 +374,9 @@ impl AbstractNode for ValueNode {
Value::structure(name, fields) Value::structure(name, fields)
} }
ValueNode::BuiltInFunction(built_in_function) => { 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)));
} }
}; };

View File

@ -109,12 +109,10 @@ impl Interpreter {
} }
pub fn load_std(&self) -> Result<(), InterpreterError> { pub fn load_std(&self) -> Result<(), InterpreterError> {
let std_core_source: (Arc<str>, Arc<str>) = { let std_core_source: (Arc<str>, Arc<str>) = (
( Arc::from("std/core.ds"),
Arc::from("std/core.ds"), Arc::from(include_str!("../../std/core.ds")),
Arc::from(include_str!("../../std/core.ds")), );
)
};
let std_sources: [(Arc<str>, Arc<str>); 4] = [ let std_sources: [(Arc<str>, Arc<str>); 4] = [
( (
Arc::from("std/fs.ds"), Arc::from("std/fs.ds"),
@ -172,7 +170,6 @@ impl Interpreter {
) -> Result<Option<Value>, InterpreterError> { ) -> Result<Option<Value>, InterpreterError> {
let mut sources = self.sources.write().unwrap(); let mut sources = self.sources.write().unwrap();
sources.clear();
sources.push((source_id.clone(), source.clone())); sources.push((source_id.clone(), source.clone()));
let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError { 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),)), .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::ExpectedFunction { .. } => todo!(),
ValidationError::ExpectedValue(_) => todo!(), ValidationError::ExpectedValue(_) => todo!(),
ValidationError::FieldNotFound { ValidationError::FieldNotFound {

View File

@ -1,9 +1,9 @@
io = { io = {
read_line = fn () -> str { read_line = fn () -> str {
__READ_LINE__ __READ_LINE__()
} }
write_line = fn (output: any) { write_line = fn (output: any) {
__WRITE_LINE__ output __WRITE_LINE__(output)
} }
} }

View File

@ -1,5 +1,5 @@
json = { json = {
parse = fn |T| (input: str) -> T { parse = fn |T| (input: str) -> T {
__JSON_PARSE__ T input __JSON_PARSE__::(T)::(input)
} }
} }

View File

@ -1,5 +1,5 @@
thread = { thread = {
sleep = fn (milliseconds: int) { sleep = fn (milliseconds: int) {
__SLEEP__ milliseconds __SLEEP__(milliseconds)
} }
} }