This commit is contained in:
Jeff 2024-06-26 11:35:39 -04:00
parent a177f19f28
commit 49fe4555c6
6 changed files with 123 additions and 63 deletions

View File

@ -1,4 +1,10 @@
use std::{fs::read_to_string, io::stdin, thread::sleep, time::Duration}; use std::{
fmt::{self, Display, Formatter},
fs::read_to_string,
io::stdin,
thread::sleep,
time::Duration,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::from_str; use serde_json::from_str;
@ -51,6 +57,21 @@ impl BuiltInFunction {
} }
} }
impl Display for BuiltInFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let display = match self {
BuiltInFunction::Length => "__LENGTH__",
BuiltInFunction::ReadLine => "__READ_LINE__",
BuiltInFunction::ReadFile => "__READ_FILE__",
BuiltInFunction::Sleep => "__SLEEP__",
BuiltInFunction::WriteLine => "__WRITE_LINE__",
BuiltInFunction::JsonParse => "__JSON_PARSE__",
};
write!(f, "{display}")
}
}
trait FunctionLogic { trait FunctionLogic {
fn r#type() -> Type; fn r#type() -> Type;
fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError>; fn call(context: &Context, manage_memory: bool) -> Result<Option<Value>, RuntimeError>;

View File

@ -40,8 +40,6 @@ impl Expression {
impl AbstractNode for Expression { impl AbstractNode for Expression {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
log::trace!("Defining types for expression at {}", self.position());
match self { match self {
Expression::As(inner) => inner.node.define_types(_context), Expression::As(inner) => inner.node.define_types(_context),
Expression::FunctionCall(inner) => inner.node.define_types(_context), Expression::FunctionCall(inner) => inner.node.define_types(_context),
@ -55,8 +53,6 @@ impl AbstractNode for Expression {
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
log::trace!("Validating expression at {}", self.position());
match self { match self {
Expression::As(r#as) => r#as.node.validate(context, manage_memory), Expression::As(r#as) => r#as.node.validate(context, manage_memory),
Expression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {
@ -87,8 +83,6 @@ impl AbstractNode for Expression {
context: &Context, context: &Context,
manage_memory: bool, manage_memory: bool,
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
log::trace!("Evaluating expression at {}", self.position());
match self { match self {
Expression::As(r#as) => r#as.node.evaluate(context, manage_memory), Expression::As(r#as) => r#as.node.evaluate(context, manage_memory),
Expression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {

View File

@ -8,7 +8,7 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor, ValueNode, WithPosition}; use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCall { pub struct FunctionCall {
@ -143,16 +143,6 @@ impl AbstractNode for FunctionCall {
context: &Context, context: &Context,
manage_memory: bool, manage_memory: bool,
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
if let Expression::Value(WithPosition {
node: ValueNode::BuiltInFunction(function),
..
}) = *self.function_expression
{
return function
.call(context, manage_memory)
.map(|value_option| value_option.map(|value| Evaluation::Return(value)));
}
let function_position = self.function_expression.position(); let function_position = self.function_expression.position();
let evaluation = self.function_expression.evaluate(context, manage_memory)?; let evaluation = self.function_expression.evaluate(context, manage_memory)?;
let value = if let Some(Evaluation::Return(value)) = evaluation { let value = if let Some(Evaluation::Return(value)) = evaluation {
@ -162,17 +152,8 @@ impl AbstractNode for FunctionCall {
ValidationError::ExpectedExpression(function_position), ValidationError::ExpectedExpression(function_position),
)); ));
}; };
let function = if let ValueInner::Function(function) = value.inner().as_ref() {
function.clone()
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFunction {
actual: value.r#type(context)?,
position: function_position,
},
));
};
if let ValueInner::Function(function) = value.inner().as_ref() {
if let (Some(type_parameters), Some(type_arguments)) = if let (Some(type_parameters), Some(type_arguments)) =
(function.type_parameters(), self.type_arguments) (function.type_parameters(), self.type_arguments)
{ {
@ -188,7 +169,9 @@ impl AbstractNode for FunctionCall {
if let (Some(parameters), Some(arguments)) = if let (Some(parameters), Some(arguments)) =
(function.value_parameters(), self.value_arguments) (function.value_parameters(), self.value_arguments)
{ {
for ((identifier, _), expression) in parameters.into_iter().zip(arguments.into_iter()) { for ((identifier, _), expression) in
parameters.into_iter().zip(arguments.into_iter())
{
let position = expression.position(); let position = expression.position();
let evaluation = expression.evaluate(context, manage_memory)?; let evaluation = expression.evaluate(context, manage_memory)?;
let value = if let Some(Evaluation::Return(value)) = evaluation { let value = if let Some(Evaluation::Return(value)) = evaluation {
@ -203,7 +186,67 @@ impl AbstractNode for FunctionCall {
} }
} }
function.call(&self.context, manage_memory) return function.clone().call(&self.context, manage_memory);
}
if let ValueInner::BuiltInFunction(function) = value.inner().as_ref() {
let (type_parameters, value_parameters, _) = if let Type::Function {
type_parameters,
value_parameters,
return_type,
} = function.r#type()
{
(type_parameters, value_parameters, return_type)
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFunction {
actual: function.r#type(),
position: function_position,
},
));
};
if let (Some(type_parameters), Some(type_arguments)) =
(type_parameters, self.type_arguments)
{
for (identifier, constructor) in
type_parameters.into_iter().zip(type_arguments.into_iter())
{
let r#type = constructor.construct(context)?;
self.context.set_type(identifier.clone(), r#type)?;
}
}
if let (Some(parameters), Some(arguments)) = (value_parameters, self.value_arguments) {
for ((identifier, _), expression) in
parameters.into_iter().zip(arguments.into_iter())
{
let position = expression.position();
let evaluation = expression.evaluate(context, manage_memory)?;
let value = if let Some(Evaluation::Return(value)) = evaluation {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedValue(position),
));
};
self.context.set_value(identifier.clone(), value)?;
}
}
return function
.call(&self.context, manage_memory)
.map(|option| option.map(|value| Evaluation::Return(value)));
}
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFunction {
actual: value.r#type(context)?,
position: function_position,
},
));
} }
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> { fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {

View File

@ -235,10 +235,10 @@ impl Display for Type {
} }
Type::Float => write!(f, "float"), Type::Float => write!(f, "float"),
Type::Generic { concrete_type, .. } => { Type::Generic { concrete_type, .. } => {
if let Some(r#type) = concrete_type { match concrete_type.clone().map(|r#box| *r#box) {
write!(f, "implied to be {}", r#type) Some(Type::Generic { identifier, .. }) => write!(f, "{identifier}"),
} else { Some(concrete_type) => write!(f, "implied to be {concrete_type}"),
write!(f, "unknown") None => write!(f, "unknown"),
} }
} }
Type::Integer => write!(f, "int"), Type::Integer => write!(f, "int"),

View File

@ -169,7 +169,7 @@ impl Display for Value {
write!(f, "{{ ")?; write!(f, "{{ ")?;
for (index, (key, value)) in map.into_iter().enumerate() { for (index, (key, value)) in map.into_iter().enumerate() {
write!(f, "{key} = {value}")?; write!(f, "{key} = {value:?}")?;
if index != map.len() - 1 { if index != map.len() - 1 {
write!(f, ", ")?; write!(f, ", ")?;
@ -178,7 +178,7 @@ impl Display for Value {
write!(f, " }}") write!(f, " }}")
} }
ValueInner::Range(_) => todo!(), ValueInner::Range(range) => write!(f, "{}..{}", range.start, range.end),
ValueInner::String(string) => write!(f, "{string}"), ValueInner::String(string) => write!(f, "{string}"),
ValueInner::Function(Function { ValueInner::Function(Function {
type_parameters, type_parameters,
@ -187,14 +187,16 @@ impl Display for Value {
body, body,
.. ..
}) => { }) => {
write!(f, "fn ")?;
if let Some(type_parameters) = type_parameters { if let Some(type_parameters) = type_parameters {
write!(f, "(")?; write!(f, "(")?;
for (index, r#type) in type_parameters.into_iter().enumerate() { for (index, identifier) in type_parameters.into_iter().enumerate() {
if index == type_parameters.len() - 1 { if index == type_parameters.len() - 1 {
write!(f, "{}", r#type)?; write!(f, "{}", identifier)?;
} else { } else {
write!(f, "{} ", r#type)?; write!(f, "{} ", identifier)?;
} }
} }
@ -226,7 +228,7 @@ impl Display for Value {
write!(f, "}}") write!(f, "}}")
} }
ValueInner::BuiltInFunction(_) => todo!(), ValueInner::BuiltInFunction(built_in_function) => write!(f, "{built_in_function}"),
} }
} }
} }

View File

@ -1,8 +1,8 @@
// This function returns its argument. // This function returns its argument.
foo = fn |T| (x: T) -> T { x } foo = fn <T>(x: T) -> T { x }
// Use turbofish to supply type information. // Use turbofish to supply type information.
bar = foo::(str)::("hi") bar = foo::<str>("hi")
// Use type annotation // Use type annotation
baz: str = foo("hi") baz: str = foo("hi")
@ -10,7 +10,7 @@ baz: str = foo("hi")
// The `json.parse` function takes a string and returns the specified type // The `json.parse` function takes a string and returns the specified type
// Use turbofish // Use turbofish
x = json.parse::(int)::("1") x = json.parse::<int>("1")
// Use type annotation // Use type annotation
x: int = json.parse("1") x: int = json.parse("1")