Attempt to add JSON parsing

This commit is contained in:
Jeff 2024-06-04 14:47:15 -04:00
parent c8dfbda447
commit f625568ced
31 changed files with 296 additions and 38 deletions

14
Cargo.lock generated
View File

@ -356,6 +356,8 @@ dependencies = [
"log", "log",
"rand", "rand",
"rayon", "rayon",
"serde",
"serde_json",
] ]
[[package]] [[package]]
@ -1023,18 +1025,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1043,9 +1045,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.114" version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",

View File

@ -17,3 +17,5 @@ env_logger = "0.11.3"
log = "0.4.21" log = "0.4.21"
rand = "0.8.5" rand = "0.8.5"
rayon = "1.9.0" rayon = "1.9.0"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"

View File

@ -1,5 +1,7 @@
use std::borrow::Borrow; use std::borrow::Borrow;
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -9,7 +11,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Type, WithPosition}; use super::{AbstractNode, Action, Expression, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct As { pub struct As {
expression: Expression, expression: Expression,
r#type: WithPosition<Type>, r#type: WithPosition<Type>,

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
identifier::Identifier, identifier::Identifier,
@ -7,7 +9,7 @@ use crate::{
use super::{AbstractNode, Action, Statement, Type, WithPosition}; use super::{AbstractNode, Action, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Assignment { pub struct Assignment {
identifier: WithPosition<Identifier>, identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>, r#type: Option<WithPosition<Type>>,
@ -15,7 +17,7 @@ pub struct Assignment {
statement: Box<Statement>, statement: Box<Statement>,
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum AssignmentOperator { pub enum AssignmentOperator {
Assign, Assign,
AddAssign, AddAssign,

View File

@ -1,6 +1,7 @@
use std::sync::RwLock; use std::sync::RwLock;
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
@ -9,7 +10,7 @@ use crate::{
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AsyncBlock { pub struct AsyncBlock {
statements: Vec<Statement>, statements: Vec<Statement>,
} }

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -5,7 +7,7 @@ use crate::{
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Block { pub struct Block {
statements: Vec<Statement>, statements: Vec<Statement>,
} }

View File

@ -5,6 +5,8 @@ use std::{
time::Duration, time::Duration,
}; };
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
abstract_tree::{Action, Type}, abstract_tree::{Action, Type},
context::Context, context::Context,
@ -13,10 +15,12 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Expression}; use super::{AbstractNode, Expression, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInFunctionCall { pub enum BuiltInFunctionCall {
JsonParse(WithPosition<Type>, Expression),
Length(Expression),
ReadFile(Expression), ReadFile(Expression),
ReadLine, ReadLine,
Sleep(Expression), Sleep(Expression),
@ -26,6 +30,8 @@ pub enum BuiltInFunctionCall {
impl AbstractNode for BuiltInFunctionCall { impl AbstractNode for BuiltInFunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self { match self {
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.item.clone()),
BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String), BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
BuiltInFunctionCall::ReadLine => Ok(Type::String), BuiltInFunctionCall::ReadLine => Ok(Type::String),
BuiltInFunctionCall::Sleep(_) => Ok(Type::None), BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
@ -39,6 +45,12 @@ impl AbstractNode for BuiltInFunctionCall {
_manage_memory: bool, _manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
match self { match self {
BuiltInFunctionCall::JsonParse(_, expression) => {
expression.validate(_context, _manage_memory)
}
BuiltInFunctionCall::Length(expression) => {
expression.validate(_context, _manage_memory)
}
BuiltInFunctionCall::ReadFile(expression) => { BuiltInFunctionCall::ReadFile(expression) => {
expression.validate(_context, _manage_memory) expression.validate(_context, _manage_memory)
} }
@ -52,7 +64,7 @@ impl AbstractNode for BuiltInFunctionCall {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
match self { match self {
BuiltInFunctionCall::ReadFile(expression) => { BuiltInFunctionCall::JsonParse(r#type, expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().run(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Action::Return(value) = action {
value value
@ -62,6 +74,45 @@ impl AbstractNode for BuiltInFunctionCall {
)); ));
}; };
if let ValueInner::String(string) = value.inner().as_ref() {
let deserialized = serde_json::from_str(string)?;
Ok(Action::Return(deserialized))
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedString {
actual: value.r#type(context)?,
position: expression.position(),
},
))
}
}
BuiltInFunctionCall::Length(expression) => {
let action = expression.clone().run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position()),
));
};
let length = if let ValueInner::List(list) = value.inner().as_ref() {
list.len() as i64
} else {
0
};
Ok(Action::Return(Value::integer(length)))
}
BuiltInFunctionCall::ReadFile(expression) => {
let action = expression.clone().run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position()),
));
};
let file_contents = if let ValueInner::String(path) = value.inner().as_ref() { let file_contents = if let ValueInner::String(path) = value.inner().as_ref() {
read_to_string(path)? read_to_string(path)?
} else { } else {

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -9,7 +11,7 @@ use super::{
SourcePosition, Type, ValueNode, WithPosition, SourcePosition, Type, ValueNode, WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[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>>), BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -6,7 +8,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Type, WithPosition}; use super::{AbstractNode, Action, Expression, Type, WithPosition};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionCall { pub struct FunctionCall {
function: Box<Expression>, function: Box<Expression>,
type_arguments: Vec<WithPosition<Type>>, type_arguments: Vec<WithPosition<Type>>,

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -6,7 +8,7 @@ use crate::{
use super::{AbstractNode, Action, Block, Expression, Type, WithPosition}; use super::{AbstractNode, Action, Block, Expression, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct IfElse { pub struct IfElse {
if_expression: Expression, if_expression: Expression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -5,7 +7,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ListIndex { pub struct ListIndex {
left: Expression, left: Expression,
right: Expression, right: Expression,

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -7,7 +9,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Type}; use super::{AbstractNode, Action, Expression, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Logic { pub enum Logic {
Equal(Expression, Expression), Equal(Expression, Expression),
NotEqual(Expression, Expression), NotEqual(Expression, Expression),

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -5,7 +7,7 @@ use crate::{
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Loop { pub struct Loop {
statements: Vec<Statement>, statements: Vec<Statement>,
} }

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -6,7 +8,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MapIndex { pub struct MapIndex {
collection: Expression, collection: Expression,
index: Expression, index: Expression,

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -7,7 +9,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, SourcePosition, Type}; use super::{AbstractNode, Action, Expression, SourcePosition, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Math { pub enum Math {
Add(Expression, Expression), Add(Expression, Expression),
Subtract(Expression, Expression), Subtract(Expression, Expression),

View File

@ -20,6 +20,7 @@ pub mod r#while;
use std::{cmp::Ordering, ops::Index}; use std::{cmp::Ordering, ops::Index};
use chumsky::span::{SimpleSpan, Span}; use chumsky::span::{SimpleSpan, Span};
use serde::{Deserialize, Serialize};
pub use self::{ pub use self::{
assignment::{Assignment, AssignmentOperator}, assignment::{Assignment, AssignmentOperator},
@ -48,7 +49,7 @@ use crate::{
Value, Value,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct WithPosition<T> { pub struct WithPosition<T> {
pub item: T, pub item: T,
pub position: SourcePosition, pub position: SourcePosition,
@ -65,7 +66,7 @@ pub trait WithPos: Sized {
impl<T> WithPos for T {} impl<T> WithPos for T {}
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct SourcePosition(pub usize, pub usize); pub struct SourcePosition(pub usize, pub usize);
impl From<SimpleSpan> for SourcePosition { impl From<SimpleSpan> for SourcePosition {
@ -87,6 +88,7 @@ pub enum Action {
None, None,
} }
#[derive(Debug, Clone)]
pub struct AbstractTree(Vec<Statement>); pub struct AbstractTree(Vec<Statement>);
impl AbstractTree { impl AbstractTree {

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -8,7 +10,7 @@ use super::{
StructureDefinition, Type, While, WithPosition, StructureDefinition, Type, While, WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Statement { pub enum Statement {
Assignment(WithPosition<Assignment>), Assignment(WithPosition<Assignment>),
AsyncBlock(WithPosition<AsyncBlock>), AsyncBlock(WithPosition<AsyncBlock>),

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -6,7 +8,7 @@ use crate::{
use super::{AbstractNode, Action, Type, WithPosition}; use super::{AbstractNode, Action, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct StructureDefinition { pub struct StructureDefinition {
name: Identifier, name: Identifier,
fields: Vec<(Identifier, WithPosition<Type>)>, fields: Vec<(Identifier, WithPosition<Type>)>,

View File

@ -1,6 +1,7 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use clap::error::Result; use clap::error::Result;
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
@ -10,7 +11,7 @@ use crate::{
use super::{AbstractNode, Action, WithPosition}; use super::{AbstractNode, Action, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Type { pub enum Type {
Any, Any,
Argument(Identifier), Argument(Identifier),

View File

@ -1,5 +1,7 @@
use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -9,7 +11,7 @@ use crate::{
use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition}; use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition};
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValueNode { pub enum ValueNode {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -7,7 +9,7 @@ use crate::{
use super::{AbstractNode, Action, Expression, Statement, Type}; use super::{AbstractNode, Action, Expression, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct While { pub struct While {
expression: Expression, expression: Expression,
statements: Vec<Statement>, statements: Vec<Statement>,

View File

@ -55,6 +55,7 @@ pub enum RuntimeError {
Io(io::Error), Io(io::Error),
RwLockPoison(RwLockPoisonError), RwLockPoison(RwLockPoisonError),
ValidationFailure(ValidationError), ValidationFailure(ValidationError),
SerdeJson(serde_json::Error),
} }
impl From<RwLockPoisonError> for RuntimeError { impl From<RwLockPoisonError> for RuntimeError {
@ -81,6 +82,12 @@ impl From<io::Error> for RuntimeError {
} }
} }
impl From<serde_json::Error> for RuntimeError {
fn from(error: serde_json::Error) -> Self {
RuntimeError::SerdeJson(error)
}
}
impl PartialEq for RuntimeError { impl PartialEq for RuntimeError {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
match (self, other) { match (self, other) {
@ -106,6 +113,10 @@ pub enum ValidationError {
index_type: Type, index_type: Type,
index_position: SourcePosition, index_position: SourcePosition,
}, },
ExpectedString {
actual: Type,
position: SourcePosition,
},
ExpectedBoolean { ExpectedBoolean {
actual: Type, actual: Type,
position: SourcePosition, position: SourcePosition,

View File

@ -3,6 +3,8 @@ use std::{
sync::Arc, sync::Arc,
}; };
use serde::{de::Visitor, Deserialize, Serialize};
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(Arc<String>); pub struct Identifier(Arc<String>);
@ -21,3 +23,33 @@ impl Display for Identifier {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} }
} }
impl Serialize for Identifier {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.0.as_str())
}
}
impl<'de> Deserialize<'de> for Identifier {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Identifier(Arc::new(
deserializer.deserialize_string(StringVisitor)?,
)))
}
}
struct StringVisitor;
impl<'de> Visitor<'de> for StringVisitor {
type Value = String;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a UTF-8 string")
}
}

View File

@ -48,6 +48,8 @@ pub enum Keyword {
Fn, Fn,
Int, Int,
If, If,
JsonParse,
Length,
List, List,
Map, Map,
None, None,
@ -85,6 +87,8 @@ impl Display for Keyword {
Keyword::Loop => write!(f, "loop"), Keyword::Loop => write!(f, "loop"),
Keyword::While => write!(f, "while"), Keyword::While => write!(f, "while"),
Keyword::Type => write!(f, "type"), Keyword::Type => write!(f, "type"),
Keyword::JsonParse => write!(f, "JSON_PARSE"),
Keyword::Length => write!(f, "LENGTH"),
Keyword::ReadFile => write!(f, "READ_FILE"), Keyword::ReadFile => write!(f, "READ_FILE"),
Keyword::ReadLine => write!(f, "READ_LINE"), Keyword::ReadLine => write!(f, "READ_LINE"),
Keyword::Sleep => write!(f, "SLEEP"), Keyword::Sleep => write!(f, "SLEEP"),
@ -278,6 +282,8 @@ pub fn lexer<'src>() -> impl Parser<
"type" => Token::Keyword(Keyword::Type), "type" => Token::Keyword(Keyword::Type),
"loop" => Token::Keyword(Keyword::Loop), "loop" => Token::Keyword(Keyword::Loop),
"while" => Token::Keyword(Keyword::While), "while" => Token::Keyword(Keyword::While),
"JSON_PARSE" => Token::Keyword(Keyword::JsonParse),
"LENGTH" => Token::Keyword(Keyword::Length),
"READ_FILE" => Token::Keyword(Keyword::ReadFile), "READ_FILE" => Token::Keyword(Keyword::ReadFile),
"READ_LINE" => Token::Keyword(Keyword::ReadLine), "READ_LINE" => Token::Keyword(Keyword::ReadLine),
"SLEEP" => Token::Keyword(Keyword::Sleep), "SLEEP" => Token::Keyword(Keyword::Sleep),

View File

@ -17,7 +17,7 @@ use ariadne::{Color, Fmt, Label, Report, ReportKind};
use chumsky::prelude::*; use chumsky::prelude::*;
use context::Context; use context::Context;
use error::{Error, RuntimeError, TypeConflict, ValidationError}; use error::{Error, RuntimeError, TypeConflict, ValidationError};
use lexer::lex; use lexer::{lex, Token};
use parser::{parse, parser}; use parser::{parse, parser};
use rayon::prelude::*; use rayon::prelude::*;
pub use value::Value; pub use value::Value;
@ -51,15 +51,47 @@ impl<'a> Interpreter<'a> {
} }
} }
pub fn lex<'source>(
&mut self,
source_id: Arc<str>,
source: &'source str,
) -> Result<Vec<Token<'source>>, InterpreterError> {
let mut sources = self.sources.write().unwrap();
sources.clear();
sources.push((source_id.clone(), Arc::from(source)));
lex(source.as_ref())
.map(|tokens| tokens.into_iter().map(|(token, _)| token).collect())
.map_err(|errors| InterpreterError { source_id, errors })
}
pub fn parse<'source>(
&mut self,
source_id: Arc<str>,
source: &'source str,
) -> Result<AbstractTree, InterpreterError> {
let mut sources = self.sources.write().unwrap();
sources.clear();
sources.push((source_id.clone(), Arc::from(source)));
parse(&lex(source).map_err(|errors| InterpreterError {
source_id: source_id.clone(),
errors,
})?)
.map_err(|errors| InterpreterError { source_id, errors })
}
pub fn run( pub fn run(
&mut self, &mut self,
source_id: Arc<str>, source_id: Arc<str>,
source: Arc<str>, source: Arc<str>,
) -> Result<Option<Value>, InterpreterError> { ) -> Result<Option<Value>, InterpreterError> {
self.sources let mut sources = self.sources.write().unwrap();
.write()
.unwrap() sources.clear();
.push((source_id.clone(), source.clone())); sources.push((source_id.clone(), source.clone()));
let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError { let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError {
source_id: source_id.clone(), source_id: source_id.clone(),
@ -77,7 +109,11 @@ impl<'a> Interpreter<'a> {
} }
pub fn load_std(&mut self) -> Result<(), InterpreterError> { pub fn load_std(&mut self) -> Result<(), InterpreterError> {
let std_sources: [(Arc<str>, Arc<str>); 3] = [ let std_sources: [(Arc<str>, Arc<str>); 4] = [
(
Arc::from("std/core.ds"),
Arc::from(include_str!("../../std/core.ds")),
),
( (
Arc::from("std/fs.ds"), Arc::from("std/fs.ds"),
Arc::from(include_str!("../../std/fs.ds")), Arc::from(include_str!("../../std/fs.ds")),
@ -363,6 +399,7 @@ impl InterpreterError {
.with_message(format!("This has type {}.", actual.fg(type_color),)), .with_message(format!("This has type {}.", actual.fg(type_color),)),
) )
} }
ValidationError::ExpectedString { actual, position } => todo!(),
} }
} }
let report = builder.finish(); let report = builder.finish();

View File

@ -263,6 +263,14 @@ pub fn parser<'src>(
); );
let built_in_function_call = choice(( let built_in_function_call = choice((
just(Token::Keyword(Keyword::Length))
.ignore_then(expression.clone())
.map_with(|argument, state| {
Expression::BuiltInFunctionCall(
Box::new(BuiltInFunctionCall::Length(argument))
.with_position(state.span()),
)
}),
just(Token::Keyword(Keyword::ReadFile)) just(Token::Keyword(Keyword::ReadFile))
.ignore_then(expression.clone()) .ignore_then(expression.clone())
.map_with(|argument, state| { .map_with(|argument, state| {
@ -292,6 +300,15 @@ pub fn parser<'src>(
.with_position(state.span()), .with_position(state.span()),
) )
}), }),
just(Token::Keyword(Keyword::JsonParse))
.ignore_then(r#type.clone())
.then(expression.clone())
.map_with(|(r#type, argument), state| {
Expression::BuiltInFunctionCall(
Box::new(BuiltInFunctionCall::JsonParse(r#type, argument))
.with_position(state.span()),
)
}),
)) ))
.try_map_with(move |expression, state| { .try_map_with(move |expression, state| {
if allow_built_ins { if allow_built_ins {

View File

@ -6,6 +6,8 @@ use std::{
sync::Arc, sync::Arc,
}; };
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition}, abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
context::Context, context::Context,
@ -181,7 +183,25 @@ impl Ord for Value {
} }
} }
#[derive(Clone, Debug, PartialEq)] impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
todo!()
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
todo!()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValueInner { pub enum ValueInner {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),
@ -299,7 +319,7 @@ impl Ord for ValueInner {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Function { pub struct Function {
type_parameters: Vec<WithPosition<Type>>, type_parameters: Vec<WithPosition<Type>>,
parameters: Vec<(Identifier, WithPosition<Type>)>, parameters: Vec<(Identifier, WithPosition<Type>)>,

View File

@ -23,6 +23,14 @@ struct Args {
#[arg(short, long)] #[arg(short, long)]
command: Option<String>, command: Option<String>,
// Display lexer tokens of the input source.
#[arg(short, long)]
lex: bool,
// Display abstract tree of the input source.
#[arg(short, long)]
parse: bool,
#[arg(long)] #[arg(long)]
no_std: bool, no_std: bool,
@ -68,6 +76,36 @@ fn main() {
return; return;
}; };
if args.lex {
match interpreter.lex(source_id, source.as_ref()) {
Ok(tokens) => println!("{tokens:?}"),
Err(error) => {
for report in error.build_reports() {
report
.write_for_stdout(sources(interpreter.sources()), stderr())
.unwrap();
}
}
}
return;
}
if args.parse {
match interpreter.parse(source_id, source.as_ref()) {
Ok(abstract_tree) => println!("{abstract_tree:?}"),
Err(error) => {
for report in error.build_reports() {
report
.write_for_stdout(sources(interpreter.sources()), stderr())
.unwrap();
}
}
}
return;
}
let run_result = interpreter.run(source_id.clone(), source.clone()); let run_result = interpreter.run(source_id.clone(), source.clone());
match run_result { match run_result {

View File

@ -6,4 +6,4 @@
input = fs.read_file('examples/assets/data.json') input = fs.read_file('examples/assets/data.json')
data = json.parse(input) data = json.parse(input)
list.length(data) length(data)

3
std/core.ds Normal file
View File

@ -0,0 +1,3 @@
length = fn (input: list) int {
LENGTH input
}

5
std/json.ds Normal file
View File

@ -0,0 +1,5 @@
json = {
parse = fn (T)(input: str) T {
JSON_PARSE T input
}
}