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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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