Begin fixing built-in functions
This commit is contained in:
parent
f106d64367
commit
18859cda77
@ -14,242 +14,179 @@ use crate::{
|
|||||||
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum BuiltInFunctionCall {
|
pub enum BuiltInFunction {
|
||||||
Length(Length),
|
Length,
|
||||||
ReadFile(ReadFile),
|
ReadLine,
|
||||||
ReadLine(ReadLine),
|
ReadFile,
|
||||||
Sleep(Sleep),
|
Sleep,
|
||||||
WriteLine(WriteLine),
|
WriteLine,
|
||||||
JsonParse(JsonParse),
|
JsonParse,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for BuiltInFunctionCall {
|
impl BuiltInFunction {
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
pub fn r#type(&self) -> Type {
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evaluate(
|
|
||||||
self,
|
|
||||||
_context: &Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::Length(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::Length => Length::r#type(),
|
||||||
BuiltInFunctionCall::ReadFile(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::ReadLine => ReadLine::r#type(),
|
||||||
BuiltInFunctionCall::ReadLine(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::ReadFile => ReadFile::r#type(),
|
||||||
BuiltInFunctionCall::Sleep(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::Sleep => Sleep::r#type(),
|
||||||
BuiltInFunctionCall::WriteLine(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::WriteLine => WriteLine::r#type(),
|
||||||
BuiltInFunctionCall::JsonParse(inner) => inner.call(_context, _manage_memory),
|
BuiltInFunction::JsonParse => JsonParse::r#type(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
pub fn call(&self, context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::Length(inner) => inner.return_type(_context),
|
BuiltInFunction::Length => Length::call(context, manage_memory),
|
||||||
BuiltInFunctionCall::ReadFile(inner) => inner.return_type(_context),
|
BuiltInFunction::ReadLine => ReadLine::call(context, manage_memory),
|
||||||
BuiltInFunctionCall::ReadLine(inner) => inner.return_type(_context),
|
BuiltInFunction::ReadFile => ReadFile::call(context, manage_memory),
|
||||||
BuiltInFunctionCall::Sleep(inner) => inner.return_type(_context),
|
BuiltInFunction::Sleep => Sleep::call(context, manage_memory),
|
||||||
BuiltInFunctionCall::WriteLine(inner) => inner.return_type(_context),
|
BuiltInFunction::WriteLine => WriteLine::call(context, manage_memory),
|
||||||
BuiltInFunctionCall::JsonParse(inner) => inner.return_type(_context),
|
BuiltInFunction::JsonParse => JsonParse::call(context, manage_memory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FunctionLogic {
|
trait FunctionLogic {
|
||||||
fn return_type(&self, context: &Context) -> Result<Option<Type>, ValidationError>;
|
fn r#type() -> Type;
|
||||||
fn call(
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError>;
|
||||||
self,
|
|
||||||
context: &Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Length(Box<Expression>);
|
struct Length;
|
||||||
|
|
||||||
impl Length {
|
|
||||||
pub fn new(expression: Expression) -> Self {
|
|
||||||
Length(Box::new(expression))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionLogic for Length {
|
impl FunctionLogic for Length {
|
||||||
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
fn r#type() -> Type {
|
||||||
Ok(Some(Type::Integer))
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: Some(vec![(
|
||||||
|
Identifier::new("list"),
|
||||||
|
Type::ListOf(Box::new(Type::Any)),
|
||||||
|
)]),
|
||||||
|
return_type: Some(Box::new(Type::Integer)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
self,
|
let value = if let Some(value) = context.get_value(&Identifier::new("input"))? {
|
||||||
context: &Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
let position = self.0.position();
|
|
||||||
let evaluation = self.0.evaluate(context, manage_memory)?;
|
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::BuiltInFunctionFailure("input does not exist"),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let list = if let ValueInner::List(list) = value.inner().as_ref() {
|
let list = if let ValueInner::List(list) = value.inner().as_ref() {
|
||||||
list
|
list
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedList {
|
ValidationError::BuiltInFunctionFailure("list is not a list"),
|
||||||
actual: value.r#type(context)?,
|
|
||||||
position,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::integer(list.len() as i64))))
|
Ok(Value::integer(list.len() as i64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct ReadFile(Box<Expression>);
|
struct ReadFile;
|
||||||
|
|
||||||
impl ReadFile {
|
|
||||||
pub fn new(expression: Expression) -> Self {
|
|
||||||
ReadFile(Box::new(expression))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionLogic for ReadFile {
|
impl FunctionLogic for ReadFile {
|
||||||
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
fn r#type() -> Type {
|
||||||
Ok(Some(Type::String))
|
Type::Function {
|
||||||
}
|
type_parameters: None,
|
||||||
|
value_parameters: None,
|
||||||
fn call(self, context: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
return_type: None,
|
||||||
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(
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
ValidationError::BuiltInFunctionFailure(self.0.position()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
||||||
pub struct ReadLine;
|
|
||||||
|
|
||||||
impl FunctionLogic for ReadLine {
|
|
||||||
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
|
||||||
Ok(Some(Type::String))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
let mut user_input = String::new();
|
|
||||||
|
|
||||||
stdin().read_line(&mut user_input)?;
|
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::string(
|
|
||||||
user_input.trim_end_matches('\n'),
|
|
||||||
))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
||||||
pub struct Sleep(Box<Expression>);
|
|
||||||
|
|
||||||
impl Sleep {
|
|
||||||
pub fn new(expression: Expression) -> Self {
|
|
||||||
Sleep(Box::new(expression))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionLogic for Sleep {
|
|
||||||
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct WriteLine(Box<Expression>);
|
struct ReadLine;
|
||||||
|
|
||||||
impl WriteLine {
|
impl FunctionLogic for ReadLine {
|
||||||
pub fn new(expression: Expression) -> Self {
|
fn r#type() -> Type {
|
||||||
WriteLine(Box::new(expression))
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: None,
|
||||||
|
return_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionLogic for WriteLine {
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
fn return_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
todo!()
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(
|
|
||||||
self,
|
|
||||||
context: &Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
let position = self.0.position();
|
|
||||||
let evaluation = self.0.evaluate(context, manage_memory)?;
|
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedExpression(position),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("{value}");
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct JsonParse(TypeConstructor, Box<Expression>);
|
struct Sleep;
|
||||||
|
|
||||||
impl JsonParse {
|
impl FunctionLogic for Sleep {
|
||||||
pub fn new(constructor: TypeConstructor, expression: Expression) -> Self {
|
fn r#type() -> Type {
|
||||||
JsonParse(constructor, Box::new(expression))
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: None,
|
||||||
|
return_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
struct WriteLine;
|
||||||
|
|
||||||
|
impl FunctionLogic for WriteLine {
|
||||||
|
fn r#type() -> Type {
|
||||||
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: None,
|
||||||
|
return_type: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
struct JsonParse;
|
||||||
|
|
||||||
impl FunctionLogic for JsonParse {
|
impl FunctionLogic for JsonParse {
|
||||||
fn return_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn r#type() -> Type {
|
||||||
self.0.construct(context).map(|r#type| Some(r#type))
|
Type::Function {
|
||||||
|
type_parameters: None,
|
||||||
|
value_parameters: None,
|
||||||
|
return_type: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(
|
fn call(context: &Context, manage_memory: bool) -> Result<Value, RuntimeError> {
|
||||||
self,
|
let target_type = if let Some(r#type) = context.get_type(&Identifier::new("T"))? {
|
||||||
context: &Context,
|
r#type
|
||||||
manage_memory: bool,
|
} else {
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
return Err(RuntimeError::ValidationFailure(
|
||||||
let target_type = self.0.construct(context)?;
|
ValidationError::BuiltInFunctionFailure("T does not exist"),
|
||||||
let position = self.1.position();
|
));
|
||||||
let evaluation = self.1.evaluate(context, manage_memory)?;
|
};
|
||||||
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
let value = if let Some(value) = context.get_value(&Identifier::new("input"))? {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedExpression(position),
|
ValidationError::BuiltInFunctionFailure("input does not exist"),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let input = if let ValueInner::String(string) = value.inner().as_ref() {
|
let input = if let ValueInner::String(string) = value.inner().as_ref() {
|
||||||
string
|
string
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedString {
|
ValidationError::BuiltInFunctionFailure("input is not a string"),
|
||||||
actual: value.r#type(context)?,
|
|
||||||
position,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -279,8 +216,6 @@ impl FunctionLogic for JsonParse {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = parse_value(&input, target_type)?;
|
parse_value(&input, target_type)
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(value)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AbstractNode, As, BuiltInFunctionCall, Evaluation, FunctionCall, ListIndex, Logic, MapIndex,
|
AbstractNode, As, Evaluation, FunctionCall, ListIndex, Logic, MapIndex, Math, SourcePosition,
|
||||||
Math, SourcePosition, Type, ValueNode, WithPosition,
|
Type, ValueNode, WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[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>>),
|
||||||
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 +34,6 @@ 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::BuiltIn(inner) => inner.position,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +44,6 @@ impl AbstractNode for Expression {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
Expression::As(inner) => inner.node.define_types(_context),
|
Expression::As(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),
|
||||||
@ -62,9 +59,6 @@ impl AbstractNode for Expression {
|
|||||||
|
|
||||||
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::BuiltIn(built_in_function_call) => {
|
|
||||||
built_in_function_call.node.validate(context, manage_memory)
|
|
||||||
}
|
|
||||||
Expression::FunctionCall(function_call) => {
|
Expression::FunctionCall(function_call) => {
|
||||||
function_call.node.validate(context, manage_memory)
|
function_call.node.validate(context, manage_memory)
|
||||||
}
|
}
|
||||||
@ -123,9 +117,6 @@ 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::BuiltIn(built_in_function_call) => {
|
|
||||||
built_in_function_call.node.evaluate(context, manage_memory)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +141,6 @@ 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::BuiltIn(built_in_function_call) => {
|
|
||||||
built_in_function_call.node.expected_type(_context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ pub use self::{
|
|||||||
assignment::{Assignment, AssignmentOperator},
|
assignment::{Assignment, AssignmentOperator},
|
||||||
async_block::AsyncBlock,
|
async_block::AsyncBlock,
|
||||||
block::Block,
|
block::Block,
|
||||||
built_in_function::BuiltInFunctionCall,
|
built_in_function::BuiltInFunction,
|
||||||
enum_declaration::{EnumDeclaration, EnumVariant},
|
enum_declaration::{EnumDeclaration, EnumVariant},
|
||||||
expression::Expression,
|
expression::Expression,
|
||||||
function_call::FunctionCall,
|
function_call::FunctionCall,
|
||||||
|
@ -10,12 +10,14 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AbstractNode, Block, Evaluation, Expression, Type, TypeConstructor, WithPos, WithPosition,
|
AbstractNode, Block, BuiltInFunction, Evaluation, Expression, Type, TypeConstructor, WithPos,
|
||||||
|
WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ValueNode {
|
pub enum ValueNode {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
BuiltInFunction(BuiltInFunction),
|
||||||
EnumInstance {
|
EnumInstance {
|
||||||
type_name: WithPosition<Identifier>,
|
type_name: WithPosition<Identifier>,
|
||||||
variant: WithPosition<Identifier>,
|
variant: WithPosition<Identifier>,
|
||||||
@ -239,7 +241,7 @@ impl AbstractNode for ValueNode {
|
|||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let value = match self {
|
let value = match self {
|
||||||
ValueNode::Boolean(boolean) => Value::boolean(boolean),
|
ValueNode::Boolean(boolean) => Value::boolean(boolean),
|
||||||
@ -253,7 +255,7 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
let position = expression.position();
|
let position = expression.position();
|
||||||
let evaluation = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, manage_memory)?;
|
||||||
|
|
||||||
if let Some(Evaluation::Return(value)) = evaluation {
|
if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
values.push(value);
|
values.push(value);
|
||||||
@ -277,7 +279,7 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
for expression in expression_list {
|
for expression in expression_list {
|
||||||
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 {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -296,7 +298,7 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
for (identifier, _type, expression) in property_list {
|
for (identifier, _type, expression) in property_list {
|
||||||
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 {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -355,7 +357,7 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
for (identifier, expression) in expressions {
|
for (identifier, expression) in expressions {
|
||||||
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 {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -369,6 +371,9 @@ impl AbstractNode for ValueNode {
|
|||||||
|
|
||||||
Value::structure(name, fields)
|
Value::structure(name, fields)
|
||||||
}
|
}
|
||||||
|
ValueNode::BuiltInFunction(built_in_function) => {
|
||||||
|
built_in_function.call(context, manage_memory)?
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(value)))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
@ -488,6 +493,7 @@ impl AbstractNode for ValueNode {
|
|||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ValueNode::BuiltInFunction(built_in_function) => built_in_function.r#type(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(r#type))
|
Ok(Some(r#type))
|
||||||
@ -612,6 +618,8 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Structure { .. }, _) => Ordering::Greater,
|
(Structure { .. }, _) => Ordering::Greater,
|
||||||
|
(BuiltInFunction(left), BuiltInFunction(right)) => left.cmp(right),
|
||||||
|
(BuiltInFunction(_), _) => Ordering::Greater,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl PartialEq for RuntimeError {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
BuiltInFunctionFailure(SourcePosition),
|
BuiltInFunctionFailure(&'static str),
|
||||||
CannotAssignToNone(SourcePosition),
|
CannotAssignToNone(SourcePosition),
|
||||||
CannotIndex {
|
CannotIndex {
|
||||||
r#type: Type,
|
r#type: Type,
|
||||||
|
@ -13,9 +13,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
built_in_function::{
|
built_in_function::BuiltInFunction,
|
||||||
BuiltInFunctionCall, JsonParse, Length, ReadFile, ReadLine, Sleep, WriteLine,
|
|
||||||
},
|
|
||||||
enum_declaration::EnumVariant,
|
enum_declaration::EnumVariant,
|
||||||
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
||||||
};
|
};
|
||||||
@ -375,57 +373,47 @@ pub fn parser<'src>(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let _built_in_function = |keyword| {
|
let underscored = |keyword| {
|
||||||
just(Token::Keyword(keyword)).delimited_by(
|
just(Token::Keyword(keyword)).delimited_by(
|
||||||
just(Token::Symbol(Symbol::DoubleUnderscore)),
|
just(Token::Symbol(Symbol::DoubleUnderscore)),
|
||||||
just(Token::Symbol(Symbol::DoubleUnderscore)),
|
just(Token::Symbol(Symbol::DoubleUnderscore)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let built_in_function_call = choice((
|
let built_in_function = choice((
|
||||||
_built_in_function(Keyword::Length)
|
underscored(Keyword::Length).map_with(|_, state| {
|
||||||
.ignore_then(expression.clone())
|
Expression::Value(
|
||||||
.map_with(|argument, state| {
|
ValueNode::BuiltInFunction(BuiltInFunction::Length)
|
||||||
Expression::BuiltIn(
|
|
||||||
BuiltInFunctionCall::Length(Length::new(argument))
|
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::ReadFile)
|
underscored(Keyword::ReadLine).map_with(|_, state| {
|
||||||
.ignore_then(expression.clone())
|
Expression::Value(
|
||||||
.map_with(|argument, state| {
|
ValueNode::BuiltInFunction(BuiltInFunction::ReadLine)
|
||||||
Expression::BuiltIn(
|
|
||||||
BuiltInFunctionCall::ReadFile(ReadFile::new(argument))
|
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::ReadLine).map_with(|_, state| {
|
underscored(Keyword::ReadFile).map_with(|_, state| {
|
||||||
Expression::BuiltIn(
|
Expression::Value(
|
||||||
BuiltInFunctionCall::ReadLine(ReadLine).with_position(state.span()),
|
ValueNode::BuiltInFunction(BuiltInFunction::ReadFile)
|
||||||
)
|
|
||||||
}),
|
|
||||||
_built_in_function(Keyword::Sleep)
|
|
||||||
.ignore_then(expression.clone())
|
|
||||||
.map_with(|argument, state| {
|
|
||||||
Expression::BuiltIn(
|
|
||||||
BuiltInFunctionCall::Sleep(Sleep::new(argument))
|
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::WriteLine)
|
underscored(Keyword::Sleep).map_with(|_, state| {
|
||||||
.ignore_then(expression.clone())
|
Expression::Value(
|
||||||
.map_with(|argument, state| {
|
ValueNode::BuiltInFunction(BuiltInFunction::Sleep)
|
||||||
Expression::BuiltIn(
|
|
||||||
BuiltInFunctionCall::WriteLine(WriteLine::new(argument))
|
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_built_in_function(Keyword::JsonParse)
|
underscored(Keyword::WriteLine).map_with(|_, state| {
|
||||||
.ignore_then(type_constructor.clone())
|
Expression::Value(
|
||||||
.then(expression.clone())
|
ValueNode::BuiltInFunction(BuiltInFunction::WriteLine)
|
||||||
.map_with(|(constructor, argument), state| {
|
.with_position(state.span()),
|
||||||
Expression::BuiltIn(
|
)
|
||||||
BuiltInFunctionCall::JsonParse(JsonParse::new(constructor, argument))
|
}),
|
||||||
|
underscored(Keyword::JsonParse).map_with(|_, state| {
|
||||||
|
Expression::Value(
|
||||||
|
ValueNode::BuiltInFunction(BuiltInFunction::JsonParse)
|
||||||
.with_position(state.span()),
|
.with_position(state.span()),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@ -456,6 +444,7 @@ pub fn parser<'src>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let atom = choice((
|
let atom = choice((
|
||||||
|
built_in_function.clone(),
|
||||||
enum_instance.clone(),
|
enum_instance.clone(),
|
||||||
range.clone(),
|
range.clone(),
|
||||||
function.clone(),
|
function.clone(),
|
||||||
@ -646,8 +635,8 @@ pub fn parser<'src>(
|
|||||||
));
|
));
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
built_in_function_call,
|
|
||||||
logic_math_indexes_as_and_function_calls,
|
logic_math_indexes_as_and_function_calls,
|
||||||
|
built_in_function,
|
||||||
enum_instance,
|
enum_instance,
|
||||||
range,
|
range,
|
||||||
function,
|
function,
|
||||||
|
@ -270,15 +270,15 @@ fn built_in_function() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statements[0],
|
statements[0],
|
||||||
Statement::Expression(Expression::BuiltIn(
|
Statement::Expression(Expression::Value(
|
||||||
BuiltInFunctionCall::ReadLine(ReadLine).with_position((0, 13))
|
ValueNode::BuiltInFunction(BuiltInFunction::ReadLine).with_position((0, 13))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn built_in_function_with_arg() {
|
fn built_in_function_with_arg() {
|
||||||
let tokens = lex("__WRITE_LINE__ 'hiya'").unwrap();
|
let tokens = lex("__WRITE_LINE__('hiya')").unwrap();
|
||||||
let statements = parser(true)
|
let statements = parser(true)
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
@ -292,11 +292,17 @@ fn built_in_function_with_arg() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statements[0],
|
statements[0],
|
||||||
Statement::Expression(Expression::BuiltIn(
|
Statement::Expression(Expression::FunctionCall(
|
||||||
BuiltInFunctionCall::WriteLine(WriteLine::new(Expression::Value(
|
FunctionCall::new(
|
||||||
|
Expression::Value(
|
||||||
|
ValueNode::BuiltInFunction(BuiltInFunction::WriteLine).with_position((0, 14))
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
Some(vec![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, 22))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use serde::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
abstract_tree::{AbstractNode, Block, BuiltInFunction, Evaluation, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{PoisonError, RuntimeError, ValidationError},
|
error::{PoisonError, RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
@ -214,6 +214,7 @@ impl Display for Value {
|
|||||||
|
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
|
ValueInner::BuiltInFunction(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,6 +306,7 @@ impl Serialize for Value {
|
|||||||
|
|
||||||
struct_ser.end()
|
struct_ser.end()
|
||||||
}
|
}
|
||||||
|
ValueInner::BuiltInFunction(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,6 +556,7 @@ impl<'de> Deserialize<'de> for Value {
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueInner {
|
pub enum ValueInner {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
BuiltInFunction(BuiltInFunction),
|
||||||
EnumInstance {
|
EnumInstance {
|
||||||
type_name: Identifier,
|
type_name: Identifier,
|
||||||
variant: Identifier,
|
variant: Identifier,
|
||||||
@ -628,6 +631,7 @@ impl ValueInner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ValueInner::BuiltInFunction(_) => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(r#type)
|
Ok(r#type)
|
||||||
@ -717,6 +721,8 @@ impl Ord for ValueInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Structure { .. }, _) => Ordering::Greater,
|
(Structure { .. }, _) => Ordering::Greater,
|
||||||
|
(BuiltInFunction(left), BuiltInFunction(right)) => left.cmp(right),
|
||||||
|
(BuiltInFunction(_), _) => Ordering::Greater,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
/*
|
|
||||||
This is is simple program to get the length of a json array.
|
|
||||||
|
|
||||||
Use `cargo run --package dust-shell examples/json_length.ds`
|
|
||||||
*/
|
|
||||||
input = fs.read_file('examples/assets/data.json')
|
input = fs.read_file('examples/assets/data.json')
|
||||||
data = json.parse(input)
|
data = json.parse(input)
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
length = fn (list: [any]) -> int {
|
length = fn (list: [any]) -> int {
|
||||||
__LENGTH__ list
|
__LENGTH__(list)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user