1
0

Begin fixing built-in functions

This commit is contained in:
Jeff 2024-06-24 07:13:54 -04:00
parent f106d64367
commit 18859cda77
11 changed files with 187 additions and 260 deletions

View File

@ -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)))
} }
} }

View File

@ -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)
}
} }
} }
} }

View File

@ -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,

View File

@ -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,
} }
} }
} }

View File

@ -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,

View File

@ -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,

View File

@ -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))
)) ))
); );
} }

View File

@ -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,
} }
} }
} }

View File

@ -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)

View File

@ -1,3 +1,3 @@
length = fn (list: [any]) -> int { length = fn (list: [any]) -> int {
__LENGTH__ list __LENGTH__(list)
} }

View File

@ -1,5 +1,5 @@
fs = { fs = {
read_file = fn (path: str) -> str { read_file = fn (path: str) -> str {
__READ_FILE__ path __READ_FILE__(path)
} }
} }