Clean up
This commit is contained in:
parent
a177f19f28
commit
49fe4555c6
@ -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>;
|
||||||
|
@ -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) => {
|
||||||
|
@ -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,48 +152,101 @@ 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 (Some(type_parameters), Some(type_arguments)) =
|
if let ValueInner::Function(function) = value.inner().as_ref() {
|
||||||
(function.type_parameters(), self.type_arguments)
|
if let (Some(type_parameters), Some(type_arguments)) =
|
||||||
{
|
(function.type_parameters(), self.type_arguments)
|
||||||
for (identifier, constructor) in
|
|
||||||
type_parameters.into_iter().zip(type_arguments.into_iter())
|
|
||||||
{
|
{
|
||||||
let r#type = constructor.construct(context)?;
|
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)?;
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (Some(parameters), Some(arguments)) =
|
||||||
|
(function.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.clone().call(&self.context, manage_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (Some(parameters), Some(arguments)) =
|
if let ValueInner::BuiltInFunction(function) = value.inner().as_ref() {
|
||||||
(function.value_parameters(), self.value_arguments)
|
let (type_parameters, value_parameters, _) = if let Type::Function {
|
||||||
{
|
type_parameters,
|
||||||
for ((identifier, _), expression) in parameters.into_iter().zip(arguments.into_iter()) {
|
value_parameters,
|
||||||
let position = expression.position();
|
return_type,
|
||||||
let evaluation = expression.evaluate(context, manage_memory)?;
|
} = function.r#type()
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
{
|
||||||
value
|
(type_parameters, value_parameters, return_type)
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedValue(position),
|
ValidationError::ExpectedFunction {
|
||||||
));
|
actual: function.r#type(),
|
||||||
};
|
position: function_position,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
self.context.set_value(identifier.clone(), value)?;
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function.call(&self.context, manage_memory)
|
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> {
|
||||||
|
@ -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"),
|
||||||
|
@ -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}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user