Finish built-in function refactoring
This commit is contained in:
parent
34cea3518d
commit
572d5a9d18
@ -1,41 +1,155 @@
|
|||||||
use std::{
|
use std::{
|
||||||
array,
|
array,
|
||||||
fs::read_to_string,
|
fs::read_to_string,
|
||||||
io::{stdin, stdout, Write},
|
io::{self, stdin},
|
||||||
slice,
|
|
||||||
sync::OnceLock,
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use rayon::iter::IntoParallelIterator;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::from_str;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
value::{Function, ValueInner},
|
value::ValueInner,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||||
AbstractNode, Block, Evaluation, Expression, Statement, Type, TypeConstructor, WithPos,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub enum BuiltInExpression {
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
Length(BuiltInFunctionCall<Length>),
|
pub enum BuiltInFunctionCall {
|
||||||
|
Length(BuiltInContextBinding<Length>),
|
||||||
|
ReadFile(BuiltInContextBinding<ReadFile>),
|
||||||
|
ReadLine(BuiltInContextBinding<ReadLine>),
|
||||||
|
Sleep(BuiltInContextBinding<Sleep>),
|
||||||
|
WriteLine(BuiltInContextBinding<WriteLine>),
|
||||||
|
JsonParse(BuiltInContextBinding<JsonParse>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BuiltInFunctionCall<F> {
|
impl BuiltInFunctionCall {
|
||||||
|
pub fn length(argument: Expression) -> Self {
|
||||||
|
BuiltInFunctionCall::Length(BuiltInContextBinding::new(Length(Box::new(argument))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_file(argument: Expression) -> Self {
|
||||||
|
BuiltInFunctionCall::ReadFile(BuiltInContextBinding::new(ReadFile(Box::new(argument))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_line() -> Self {
|
||||||
|
BuiltInFunctionCall::ReadLine(BuiltInContextBinding::new(ReadLine))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sleep(argument: Expression) -> Self {
|
||||||
|
BuiltInFunctionCall::Sleep(BuiltInContextBinding::new(Sleep(Box::new(argument))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_line(argument: Expression) -> Self {
|
||||||
|
BuiltInFunctionCall::WriteLine(BuiltInContextBinding::new(WriteLine(Box::new(argument))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn json_parse(r#type: TypeConstructor, argument: Expression) -> Self {
|
||||||
|
BuiltInFunctionCall::JsonParse(BuiltInContextBinding::new(JsonParse(
|
||||||
|
r#type,
|
||||||
|
Box::new(argument),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractNode for BuiltInFunctionCall {
|
||||||
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
BuiltInFunctionCall::Length(inner) => inner.define_types(_context),
|
||||||
|
BuiltInFunctionCall::ReadFile(inner) => inner.define_types(_context),
|
||||||
|
BuiltInFunctionCall::ReadLine(inner) => inner.define_types(_context),
|
||||||
|
BuiltInFunctionCall::Sleep(inner) => inner.define_types(_context),
|
||||||
|
BuiltInFunctionCall::WriteLine(inner) => inner.define_types(_context),
|
||||||
|
BuiltInFunctionCall::JsonParse(inner) => inner.define_types(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
BuiltInFunctionCall::Length(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::ReadFile(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::ReadLine(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::Sleep(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::WriteLine(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::JsonParse(inner) => inner.validate(_context, _manage_memory),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
self,
|
||||||
|
_context: &Context,
|
||||||
|
_manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
match self {
|
||||||
|
BuiltInFunctionCall::Length(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::ReadFile(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::ReadLine(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::Sleep(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::WriteLine(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
BuiltInFunctionCall::JsonParse(inner) => inner.evaluate(_context, _manage_memory),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
match self {
|
||||||
|
BuiltInFunctionCall::Length(inner) => inner.expected_type(_context),
|
||||||
|
BuiltInFunctionCall::ReadFile(inner) => inner.expected_type(_context),
|
||||||
|
BuiltInFunctionCall::ReadLine(inner) => inner.expected_type(_context),
|
||||||
|
BuiltInFunctionCall::Sleep(inner) => inner.expected_type(_context),
|
||||||
|
BuiltInFunctionCall::WriteLine(inner) => inner.expected_type(_context),
|
||||||
|
BuiltInFunctionCall::JsonParse(inner) => inner.expected_type(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BuiltInContextBinding<F> {
|
||||||
function: F,
|
function: F,
|
||||||
|
#[serde(skip)]
|
||||||
context: Context,
|
context: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FunctionLogic {
|
impl<F> BuiltInContextBinding<F> {
|
||||||
fn type_parameters() -> Option<impl IntoIterator<Item = (Identifier, Type)>>;
|
pub fn new(function: F) -> Self {
|
||||||
fn value_parameters() -> impl IntoIterator<Item = Identifier>;
|
Self {
|
||||||
fn return_type() -> Type;
|
function,
|
||||||
|
context: Context::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Eq> Eq for BuiltInContextBinding<F> {}
|
||||||
|
|
||||||
|
impl<F: PartialEq> PartialEq for BuiltInContextBinding<F> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.function == other.function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Ord> PartialOrd for BuiltInContextBinding<F> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.function.cmp(&other.function))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Ord> Ord for BuiltInContextBinding<F> {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
self.function.cmp(&other.function)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait FunctionLogic {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
);
|
||||||
|
fn return_type(&self, context: &Context) -> Result<Option<Type>, ValidationError>;
|
||||||
fn call(
|
fn call(
|
||||||
self,
|
self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@ -43,14 +157,29 @@ pub trait FunctionLogic {
|
|||||||
) -> Result<Option<Evaluation>, RuntimeError>;
|
) -> Result<Option<Evaluation>, RuntimeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: FunctionLogic> AbstractNode for BuiltInFunctionCall<F> {
|
impl<F> AbstractNode for BuiltInContextBinding<F>
|
||||||
|
where
|
||||||
|
F: FunctionLogic + Clone,
|
||||||
|
{
|
||||||
fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
|
||||||
if let Some(type_arguments) = F::type_parameters() {
|
let (type_arguments, value_arguments) = self.function.clone().arguments();
|
||||||
for (identifier, r#type) in type_arguments {
|
|
||||||
|
if let Some(type_arguments) = type_arguments {
|
||||||
|
for (identifier, constructor) in type_arguments {
|
||||||
|
let r#type = constructor.construct(&self.context)?;
|
||||||
|
|
||||||
self.context.set_type(identifier, r#type)?;
|
self.context.set_type(identifier, r#type)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(value_arguments) = value_arguments {
|
||||||
|
for (identifier, expression) in value_arguments {
|
||||||
|
if let Some(r#type) = expression.expected_type(&self.context)? {
|
||||||
|
self.context.set_type(identifier, r#type)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,26 +195,29 @@ impl<F: FunctionLogic> AbstractNode for BuiltInFunctionCall<F> {
|
|||||||
self.function.call(&self.context, manage_memory)
|
self.function.call(&self.context, manage_memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
Ok(Some(F::return_type()))
|
self.function.return_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Length {
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
argument: Expression,
|
pub struct Length(Box<Expression>);
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionLogic for Length {
|
impl FunctionLogic for Length {
|
||||||
fn type_parameters() -> Option<impl IntoIterator<Item = (Identifier, Type)>> {
|
fn arguments(
|
||||||
None::<array::IntoIter<(Identifier, Type), 0>>
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
None::<array::IntoIter<(Identifier, TypeConstructor), 0>>,
|
||||||
|
Some([(Identifier::new("list"), *self.0)].into_iter()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value_parameters() -> impl IntoIterator<Item = Identifier> {
|
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
[(Identifier::new("list"))].into_iter()
|
Ok(Some(Type::Integer))
|
||||||
}
|
|
||||||
|
|
||||||
fn return_type() -> Type {
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(
|
||||||
@ -93,8 +225,8 @@ impl FunctionLogic for Length {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let position = self.argument.position();
|
let position = self.0.position();
|
||||||
let evaluation = self.argument.evaluate(context, manage_memory)?;
|
let evaluation = self.0.evaluate(context, manage_memory)?;
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -116,3 +248,183 @@ impl FunctionLogic for Length {
|
|||||||
Ok(Some(Evaluation::Return(Value::integer(list.len() as i64))))
|
Ok(Some(Evaluation::Return(Value::integer(list.len() as i64))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct ReadFile(Box<Expression>);
|
||||||
|
|
||||||
|
impl FunctionLogic for ReadFile {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
None::<array::IntoIter<(Identifier, TypeConstructor), 0>>,
|
||||||
|
Some([(Identifier::new("path"), *self.0)].into_iter()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(Some(Type::String))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(self, context: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
if let Ok(Some(value)) = context.get_value(&Identifier::new("path")) {
|
||||||
|
if let ValueInner::String(path) = value.inner().as_ref() {
|
||||||
|
let file_content = read_to_string(path)?;
|
||||||
|
|
||||||
|
return Ok(Some(Evaluation::Return(Value::string(file_content))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure(self.0.position()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct ReadLine;
|
||||||
|
|
||||||
|
impl FunctionLogic for ReadLine {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
None::<array::IntoIter<(Identifier, TypeConstructor), 0>>,
|
||||||
|
None::<array::IntoIter<(Identifier, Expression), 0>>,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(Some(Type::String))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
let user_input = io::read_to_string(stdin())?;
|
||||||
|
|
||||||
|
Ok(Some(Evaluation::Return(Value::string(user_input))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct Sleep(Box<Expression>);
|
||||||
|
|
||||||
|
impl FunctionLogic for Sleep {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
None::<array::IntoIter<(Identifier, TypeConstructor), 0>>,
|
||||||
|
Some([(Identifier::new("milliseconds"), *self.0)].into_iter()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct WriteLine(Box<Expression>);
|
||||||
|
|
||||||
|
impl FunctionLogic for WriteLine {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
None::<array::IntoIter<(Identifier, TypeConstructor), 0>>,
|
||||||
|
Some([(Identifier::new("message"), *self.0)].into_iter()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(self, context: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
let message = context.get_value(&Identifier::new("message"))?;
|
||||||
|
|
||||||
|
if let Some(message) = message {
|
||||||
|
println!("{message}");
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure(self.0.position()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct JsonParse(TypeConstructor, Box<Expression>);
|
||||||
|
|
||||||
|
impl FunctionLogic for JsonParse {
|
||||||
|
fn arguments(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, TypeConstructor)>>,
|
||||||
|
Option<impl IntoIterator<Item = (Identifier, Expression)>>,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
Some([(Identifier::new("T"), self.0)].into_iter()),
|
||||||
|
Some([(Identifier::new("input"), *self.1)].into_iter()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
self.0.construct(context).map(|r#type| Some(r#type))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(self, context: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
let target_type = context.get_type(&Identifier::new("T"))?;
|
||||||
|
let input = context.get_value(&Identifier::new("input"))?;
|
||||||
|
|
||||||
|
if let (Some(r#type), Some(value)) = (target_type, input) {
|
||||||
|
let input_string = if let ValueInner::String(string) = value.inner().as_ref() {
|
||||||
|
string
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure(self.0.position()),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_value = match r#type {
|
||||||
|
Type::Any => from_str::<Value>(input_string)?,
|
||||||
|
Type::Boolean => Value::boolean(from_str::<bool>(input_string)?),
|
||||||
|
Type::Enum { .. } => todo!(),
|
||||||
|
Type::Float => Value::float(from_str::<f64>(input_string)?),
|
||||||
|
Type::Function { .. } => todo!(),
|
||||||
|
Type::Generic { .. } => todo!(),
|
||||||
|
Type::Integer => Value::integer(from_str::<i64>(input_string)?),
|
||||||
|
Type::List { .. } => todo!(),
|
||||||
|
Type::ListOf(_) => todo!(),
|
||||||
|
Type::Map => todo!(),
|
||||||
|
Type::Range => todo!(),
|
||||||
|
Type::String => Value::string(from_str::<String>(input_string)?),
|
||||||
|
Type::Structure { .. } => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(Some(Evaluation::Return(parsed_value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::BuiltInFunctionFailure(self.0.position()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ use super::{
|
|||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
As(WithPosition<Box<As>>),
|
As(WithPosition<Box<As>>),
|
||||||
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
|
BuiltIn(WithPosition<BuiltInFunctionCall>),
|
||||||
FunctionCall(WithPosition<FunctionCall>),
|
FunctionCall(WithPosition<FunctionCall>),
|
||||||
Identifier(WithPosition<Identifier>),
|
Identifier(WithPosition<Identifier>),
|
||||||
MapIndex(WithPosition<Box<MapIndex>>),
|
MapIndex(WithPosition<Box<MapIndex>>),
|
||||||
@ -35,7 +35,7 @@ impl Expression {
|
|||||||
Expression::Logic(inner) => inner.position,
|
Expression::Logic(inner) => inner.position,
|
||||||
Expression::Math(inner) => inner.position,
|
Expression::Math(inner) => inner.position,
|
||||||
Expression::Value(inner) => inner.position,
|
Expression::Value(inner) => inner.position,
|
||||||
Expression::BuiltInFunctionCall(inner) => inner.position,
|
Expression::BuiltIn(inner) => inner.position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ impl AbstractNode for Expression {
|
|||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Expression::As(inner) => inner.node.define_types(_context),
|
Expression::As(inner) => inner.node.define_types(_context),
|
||||||
Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context),
|
Expression::BuiltIn(inner) => inner.node.define_types(_context),
|
||||||
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
||||||
Expression::Identifier(_) => Ok(()),
|
Expression::Identifier(_) => Ok(()),
|
||||||
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
||||||
@ -58,7 +58,7 @@ impl AbstractNode for Expression {
|
|||||||
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
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::BuiltInFunctionCall(built_in_function_call) => {
|
Expression::BuiltIn(built_in_function_call) => {
|
||||||
built_in_function_call.node.validate(context, manage_memory)
|
built_in_function_call.node.validate(context, manage_memory)
|
||||||
}
|
}
|
||||||
Expression::FunctionCall(function_call) => {
|
Expression::FunctionCall(function_call) => {
|
||||||
@ -117,7 +117,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::Logic(logic) => logic.node.evaluate(context, manage_memory),
|
Expression::Logic(logic) => logic.node.evaluate(context, manage_memory),
|
||||||
Expression::Math(math) => math.node.evaluate(context, manage_memory),
|
Expression::Math(math) => math.node.evaluate(context, manage_memory),
|
||||||
Expression::Value(value_node) => value_node.node.evaluate(context, manage_memory),
|
Expression::Value(value_node) => value_node.node.evaluate(context, manage_memory),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
Expression::BuiltIn(built_in_function_call) => {
|
||||||
built_in_function_call.node.evaluate(context, manage_memory)
|
built_in_function_call.node.evaluate(context, manage_memory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::Logic(logic) => logic.node.expected_type(_context),
|
Expression::Logic(logic) => logic.node.expected_type(_context),
|
||||||
Expression::Math(math) => math.node.expected_type(_context),
|
Expression::Math(math) => math.node.expected_type(_context),
|
||||||
Expression::Value(value_node) => value_node.node.expected_type(_context),
|
Expression::Value(value_node) => value_node.node.expected_type(_context),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
Expression::BuiltIn(built_in_function_call) => {
|
||||||
built_in_function_call.node.expected_type(_context)
|
built_in_function_call.node.expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub use self::{
|
|||||||
assignment::{Assignment, AssignmentOperator},
|
assignment::{Assignment, AssignmentOperator},
|
||||||
async_block::AsyncBlock,
|
async_block::AsyncBlock,
|
||||||
block::Block,
|
block::Block,
|
||||||
built_in_function::FunctionLogic,
|
built_in_function::BuiltInFunctionCall,
|
||||||
enum_declaration::{EnumDeclaration, EnumVariant},
|
enum_declaration::{EnumDeclaration, EnumVariant},
|
||||||
expression::Expression,
|
expression::Expression,
|
||||||
function_call::FunctionCall,
|
function_call::FunctionCall,
|
||||||
|
@ -103,6 +103,7 @@ impl PartialEq for RuntimeError {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
|
BuiltInFunctionFailure(SourcePosition),
|
||||||
CannotAssignToNone(SourcePosition),
|
CannotAssignToNone(SourcePosition),
|
||||||
CannotIndex {
|
CannotIndex {
|
||||||
r#type: Type,
|
r#type: Type,
|
||||||
|
@ -470,6 +470,8 @@ impl InterpreterError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValidationError::EnumVariantNotFound { .. } => todo!(),
|
ValidationError::EnumVariantNotFound { .. } => todo!(),
|
||||||
|
ValidationError::ExpectedList { .. } => todo!(),
|
||||||
|
ValidationError::BuiltInFunctionFailure(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
|
built_in_function::BuiltInFunctionCall,
|
||||||
enum_declaration::EnumVariant,
|
enum_declaration::EnumVariant,
|
||||||
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
||||||
};
|
};
|
||||||
@ -339,46 +340,42 @@ pub fn parser<'src>(
|
|||||||
_built_in_function(Keyword::Length)
|
_built_in_function(Keyword::Length)
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.map_with(|argument, state| {
|
.map_with(|argument, state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::Length(argument))
|
BuiltInFunctionCall::length(argument).with_position(state.span()),
|
||||||
.with_position(state.span()),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::ReadFile)
|
_built_in_function(Keyword::ReadFile)
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.map_with(|argument, state| {
|
.map_with(|argument, state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::ReadFile(argument))
|
BuiltInFunctionCall::read_file(argument).with_position(state.span()),
|
||||||
.with_position(state.span()),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::ReadLine).map_with(|_, state| {
|
_built_in_function(Keyword::ReadLine).map_with(|_, state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::ReadLine).with_position(state.span()),
|
BuiltInFunctionCall::read_line().with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::Sleep)
|
_built_in_function(Keyword::Sleep)
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.map_with(|argument, state| {
|
.map_with(|argument, state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::Sleep(argument))
|
BuiltInFunctionCall::sleep(argument).with_position(state.span()),
|
||||||
.with_position(state.span()),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::WriteLine)
|
_built_in_function(Keyword::WriteLine)
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.map_with(|argument, state| {
|
.map_with(|argument, state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::WriteLine(argument))
|
BuiltInFunctionCall::write_line(argument).with_position(state.span()),
|
||||||
.with_position(state.span()),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::JsonParse)
|
_built_in_function(Keyword::JsonParse)
|
||||||
.ignore_then(type_constructor.clone())
|
.ignore_then(type_constructor.clone())
|
||||||
.then(expression.clone())
|
.then(expression.clone())
|
||||||
.map_with(|(constructor, argument), state| {
|
.map_with(|(constructor, argument), state| {
|
||||||
Expression::BuiltInFunctionCall(
|
Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::JsonParse(constructor, argument))
|
BuiltInFunctionCall::json_parse(constructor, argument)
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
@ -240,8 +240,8 @@ fn built_in_function() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statements[0],
|
statements[0],
|
||||||
Statement::Expression(Expression::BuiltInFunctionCall(
|
Statement::Expression(Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 13))
|
BuiltInFunctionCall::read_line().with_position((0, 13))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -262,10 +262,10 @@ fn built_in_function_with_arg() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statements[0],
|
statements[0],
|
||||||
Statement::Expression(Expression::BuiltInFunctionCall(
|
Statement::Expression(Expression::BuiltIn(
|
||||||
Box::new(BuiltInFunctionCall::WriteLine(Expression::Value(
|
BuiltInFunctionCall::write_line(Expression::Value(
|
||||||
ValueNode::String("hiya".to_string()).with_position((15, 21))
|
ValueNode::String("hiya".to_string()).with_position((15, 21))
|
||||||
)))
|
))
|
||||||
.with_position((0, 21))
|
.with_position((0, 21))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -787,18 +787,39 @@ impl Eq for Function {}
|
|||||||
|
|
||||||
impl PartialEq for Function {
|
impl PartialEq for Function {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
todo!()
|
self.type_parameters == other.type_parameters
|
||||||
|
&& self.value_parameters == other.value_parameters
|
||||||
|
&& self.return_type == other.return_type
|
||||||
|
&& self.body == other.body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Function {
|
impl PartialOrd for Function {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
todo!()
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Function {
|
impl Ord for Function {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
todo!()
|
let type_params_cmp = self.type_parameters.cmp(&other.type_parameters);
|
||||||
|
|
||||||
|
if type_params_cmp.is_eq() {
|
||||||
|
let value_params_cmp = self.value_parameters.cmp(&other.value_parameters);
|
||||||
|
|
||||||
|
if value_params_cmp.is_eq() {
|
||||||
|
let return_cmp = self.return_type.cmp(&other.return_type);
|
||||||
|
|
||||||
|
if return_cmp.is_eq() {
|
||||||
|
self.body.cmp(&other.body)
|
||||||
|
} else {
|
||||||
|
return_cmp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value_params_cmp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type_params_cmp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user