Attempt to add JSON parsing
This commit is contained in:
parent
c8dfbda447
commit
f625568ced
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -356,6 +356,8 @@ dependencies = [
|
||||
"log",
|
||||
"rand",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1023,18 +1025,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1043,9 +1045,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.114"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -17,3 +17,5 @@ env_logger = "0.11.3"
|
||||
log = "0.4.21"
|
||||
rand = "0.8.5"
|
||||
rayon = "1.9.0"
|
||||
serde = { version = "1.0.203", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -9,7 +11,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
expression: Expression,
|
||||
r#type: WithPosition<Type>,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
error::{RuntimeError, ValidationError},
|
||||
identifier::Identifier,
|
||||
@ -7,7 +9,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
identifier: WithPosition<Identifier>,
|
||||
r#type: Option<WithPosition<Type>>,
|
||||
@ -15,7 +17,7 @@ pub struct Assignment {
|
||||
statement: Box<Statement>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum AssignmentOperator {
|
||||
Assign,
|
||||
AddAssign,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::sync::RwLock;
|
||||
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
@ -9,7 +10,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
statements: Vec<Statement>,
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -5,7 +7,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
statements: Vec<Statement>,
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
abstract_tree::{Action, Type},
|
||||
context::Context,
|
||||
@ -13,10 +15,12 @@ use crate::{
|
||||
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 {
|
||||
JsonParse(WithPosition<Type>, Expression),
|
||||
Length(Expression),
|
||||
ReadFile(Expression),
|
||||
ReadLine,
|
||||
Sleep(Expression),
|
||||
@ -26,6 +30,8 @@ pub enum BuiltInFunctionCall {
|
||||
impl AbstractNode for BuiltInFunctionCall {
|
||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
||||
match self {
|
||||
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.item.clone()),
|
||||
BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
|
||||
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
|
||||
BuiltInFunctionCall::ReadLine => Ok(Type::String),
|
||||
BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
|
||||
@ -39,6 +45,12 @@ impl AbstractNode for BuiltInFunctionCall {
|
||||
_manage_memory: bool,
|
||||
) -> Result<(), ValidationError> {
|
||||
match self {
|
||||
BuiltInFunctionCall::JsonParse(_, expression) => {
|
||||
expression.validate(_context, _manage_memory)
|
||||
}
|
||||
BuiltInFunctionCall::Length(expression) => {
|
||||
expression.validate(_context, _manage_memory)
|
||||
}
|
||||
BuiltInFunctionCall::ReadFile(expression) => {
|
||||
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> {
|
||||
match self {
|
||||
BuiltInFunctionCall::ReadFile(expression) => {
|
||||
BuiltInFunctionCall::JsonParse(r#type, expression) => {
|
||||
let action = expression.clone().run(context, _manage_memory)?;
|
||||
let value = if let Action::Return(value) = action {
|
||||
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() {
|
||||
read_to_string(path)?
|
||||
} else {
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -9,7 +11,7 @@ use super::{
|
||||
SourcePosition, Type, ValueNode, WithPosition,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum Expression {
|
||||
As(WithPosition<Box<As>>),
|
||||
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -6,7 +8,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
function: Box<Expression>,
|
||||
type_arguments: Vec<WithPosition<Type>>,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -6,7 +8,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
if_expression: Expression,
|
||||
if_block: WithPosition<Block>,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -5,7 +7,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
left: Expression,
|
||||
right: Expression,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -7,7 +9,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
Equal(Expression, Expression),
|
||||
NotEqual(Expression, Expression),
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -5,7 +7,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
statements: Vec<Statement>,
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -6,7 +8,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
collection: Expression,
|
||||
index: Expression,
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -7,7 +9,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
Add(Expression, Expression),
|
||||
Subtract(Expression, Expression),
|
||||
|
@ -20,6 +20,7 @@ pub mod r#while;
|
||||
use std::{cmp::Ordering, ops::Index};
|
||||
|
||||
use chumsky::span::{SimpleSpan, Span};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub use self::{
|
||||
assignment::{Assignment, AssignmentOperator},
|
||||
@ -48,7 +49,7 @@ use crate::{
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct WithPosition<T> {
|
||||
pub item: T,
|
||||
pub position: SourcePosition,
|
||||
@ -65,7 +66,7 @@ pub trait WithPos: Sized {
|
||||
|
||||
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);
|
||||
|
||||
impl From<SimpleSpan> for SourcePosition {
|
||||
@ -87,6 +88,7 @@ pub enum Action {
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AbstractTree(Vec<Statement>);
|
||||
|
||||
impl AbstractTree {
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -8,7 +10,7 @@ use super::{
|
||||
StructureDefinition, Type, While, WithPosition,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum Statement {
|
||||
Assignment(WithPosition<Assignment>),
|
||||
AsyncBlock(WithPosition<AsyncBlock>),
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -6,7 +8,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
name: Identifier,
|
||||
fields: Vec<(Identifier, WithPosition<Type>)>,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use clap::error::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
@ -10,7 +11,7 @@ use crate::{
|
||||
|
||||
use super::{AbstractNode, Action, WithPosition};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum Type {
|
||||
Any,
|
||||
Argument(Identifier),
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -9,7 +11,7 @@ use crate::{
|
||||
|
||||
use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ValueNode {
|
||||
Boolean(bool),
|
||||
Float(f64),
|
||||
|
@ -1,3 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
@ -7,7 +9,7 @@ use crate::{
|
||||
|
||||
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 {
|
||||
expression: Expression,
|
||||
statements: Vec<Statement>,
|
||||
|
@ -55,6 +55,7 @@ pub enum RuntimeError {
|
||||
Io(io::Error),
|
||||
RwLockPoison(RwLockPoisonError),
|
||||
ValidationFailure(ValidationError),
|
||||
SerdeJson(serde_json::Error),
|
||||
}
|
||||
|
||||
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 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
@ -106,6 +113,10 @@ pub enum ValidationError {
|
||||
index_type: Type,
|
||||
index_position: SourcePosition,
|
||||
},
|
||||
ExpectedString {
|
||||
actual: Type,
|
||||
position: SourcePosition,
|
||||
},
|
||||
ExpectedBoolean {
|
||||
actual: Type,
|
||||
position: SourcePosition,
|
||||
|
@ -3,6 +3,8 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use serde::{de::Visitor, Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Identifier(Arc<String>);
|
||||
|
||||
@ -21,3 +23,33 @@ impl Display for Identifier {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ pub enum Keyword {
|
||||
Fn,
|
||||
Int,
|
||||
If,
|
||||
JsonParse,
|
||||
Length,
|
||||
List,
|
||||
Map,
|
||||
None,
|
||||
@ -85,6 +87,8 @@ impl Display for Keyword {
|
||||
Keyword::Loop => write!(f, "loop"),
|
||||
Keyword::While => write!(f, "while"),
|
||||
Keyword::Type => write!(f, "type"),
|
||||
Keyword::JsonParse => write!(f, "JSON_PARSE"),
|
||||
Keyword::Length => write!(f, "LENGTH"),
|
||||
Keyword::ReadFile => write!(f, "READ_FILE"),
|
||||
Keyword::ReadLine => write!(f, "READ_LINE"),
|
||||
Keyword::Sleep => write!(f, "SLEEP"),
|
||||
@ -278,6 +282,8 @@ pub fn lexer<'src>() -> impl Parser<
|
||||
"type" => Token::Keyword(Keyword::Type),
|
||||
"loop" => Token::Keyword(Keyword::Loop),
|
||||
"while" => Token::Keyword(Keyword::While),
|
||||
"JSON_PARSE" => Token::Keyword(Keyword::JsonParse),
|
||||
"LENGTH" => Token::Keyword(Keyword::Length),
|
||||
"READ_FILE" => Token::Keyword(Keyword::ReadFile),
|
||||
"READ_LINE" => Token::Keyword(Keyword::ReadLine),
|
||||
"SLEEP" => Token::Keyword(Keyword::Sleep),
|
||||
|
@ -17,7 +17,7 @@ use ariadne::{Color, Fmt, Label, Report, ReportKind};
|
||||
use chumsky::prelude::*;
|
||||
use context::Context;
|
||||
use error::{Error, RuntimeError, TypeConflict, ValidationError};
|
||||
use lexer::lex;
|
||||
use lexer::{lex, Token};
|
||||
use parser::{parse, parser};
|
||||
use rayon::prelude::*;
|
||||
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(
|
||||
&mut self,
|
||||
source_id: Arc<str>,
|
||||
source: Arc<str>,
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
self.sources
|
||||
.write()
|
||||
.unwrap()
|
||||
.push((source_id.clone(), source.clone()));
|
||||
let mut sources = self.sources.write().unwrap();
|
||||
|
||||
sources.clear();
|
||||
sources.push((source_id.clone(), source.clone()));
|
||||
|
||||
let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError {
|
||||
source_id: source_id.clone(),
|
||||
@ -77,7 +109,11 @@ impl<'a> Interpreter<'a> {
|
||||
}
|
||||
|
||||
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(include_str!("../../std/fs.ds")),
|
||||
@ -363,6 +399,7 @@ impl InterpreterError {
|
||||
.with_message(format!("This has type {}.", actual.fg(type_color),)),
|
||||
)
|
||||
}
|
||||
ValidationError::ExpectedString { actual, position } => todo!(),
|
||||
}
|
||||
}
|
||||
let report = builder.finish();
|
||||
|
@ -263,6 +263,14 @@ pub fn parser<'src>(
|
||||
);
|
||||
|
||||
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))
|
||||
.ignore_then(expression.clone())
|
||||
.map_with(|argument, state| {
|
||||
@ -292,6 +300,15 @@ pub fn parser<'src>(
|
||||
.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| {
|
||||
if allow_built_ins {
|
||||
|
@ -6,6 +6,8 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
|
||||
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 {
|
||||
Boolean(bool),
|
||||
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 {
|
||||
type_parameters: Vec<WithPosition<Type>>,
|
||||
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
||||
|
@ -23,6 +23,14 @@ struct Args {
|
||||
#[arg(short, long)]
|
||||
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)]
|
||||
no_std: bool,
|
||||
|
||||
@ -68,6 +76,36 @@ fn main() {
|
||||
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());
|
||||
|
||||
match run_result {
|
||||
|
@ -6,4 +6,4 @@
|
||||
input = fs.read_file('examples/assets/data.json')
|
||||
data = json.parse(input)
|
||||
|
||||
list.length(data)
|
||||
length(data)
|
||||
|
3
std/core.ds
Normal file
3
std/core.ds
Normal file
@ -0,0 +1,3 @@
|
||||
length = fn (input: list) int {
|
||||
LENGTH input
|
||||
}
|
5
std/json.ds
Normal file
5
std/json.ds
Normal file
@ -0,0 +1,5 @@
|
||||
json = {
|
||||
parse = fn (T)(input: str) T {
|
||||
JSON_PARSE T input
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user