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