Compare commits

...

7 Commits

Author SHA1 Message Date
99ba7b78ab Add lots of type checking 2024-01-04 22:30:06 -05:00
2a7988f9a6 Implement structures 2024-01-04 21:12:45 -05:00
84cb17e75c Implement structures 2024-01-04 20:54:22 -05:00
de98c58587 Implement structures 2024-01-04 19:07:31 -05:00
2a18f9fb7c Implement structure value, type and syntax 2024-01-04 18:32:40 -05:00
614bb6f23e Change language syntax for "map" to "struct" 2024-01-04 12:11:27 -05:00
531227ba2d Begin custom type implementation 2024-01-03 20:11:09 -05:00
46 changed files with 16810 additions and 15664 deletions

View File

@ -1,22 +1,22 @@
cards = {
Cards = struct {
rooms = ['Library' 'Kitchen' 'Conservatory']
suspects = ['White' 'Green' 'Scarlett']
weapons = ['Rope' 'Lead_Pipe' 'Knife']
}
is_ready_to_solve = (cards <map>) <bool> {
is_ready_to_solve = (cards <Cards>) <bool> {
(length(cards:suspects) == 1)
&& (length(cards:rooms) == 1)
&& (length(cards:weapons) == 1)
}
remove_card = (cards <map>, opponent_card <str>) <none> {
remove_card = (cards <Cards>, opponent_card <str>) <none> {
cards:rooms -= opponent_card
cards:suspects -= opponent_card
cards:weapons -= opponent_card
}
make_guess = (cards <map>, current_room <str>) <none> {
make_guess = (cards <Cards>, current_room <str>) <none> {
if is_ready_to_solve(cards) {
output(
'I accuse '
@ -40,11 +40,13 @@ make_guess = (cards <map>, current_room <str>) <none> {
}
}
take_turn = (cards <map>, opponent_card <str>, current_room <str>) <none> {
take_turn = (cards <Cards>, opponent_card <str>, current_room <str>) <none> {
remove_card(cards opponent_card)
make_guess(cards current_room)
}
cards = new Cards
take_turn(cards 'Rope' 'Kitchen')
take_turn(cards 'Library' 'Kitchen')
take_turn(cards 'Conservatory' 'Kitchen')

View File

@ -1,9 +1,14 @@
data = json:parse(fs:read('examples/assets/jq_data.json'))
new_data = []
MyData = struct {
message <str>
name <str>
}
data_list = []
for commit_data in data {
new_data += {
new_data += new MyData {
message = commit_data:commit:message
name = commit_data:commit:committer:name
}

View File

@ -1,11 +1,11 @@
dictionary = {
Info = struct {
dust = "awesome"
answer = 42
}
output(
'Dust is '
+ dictionary:dust
+ Info:dust
+ '! The answer is '
+ dictionary:answer
+ Info:answer
)

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, Type, TypeDefinition, Value};
use crate::{
AbstractTree, Error, Identifier, Result, Statement, Structure, Type, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment {
@ -19,7 +21,7 @@ pub enum AssignmentOperator {
}
impl AbstractTree for Assignment {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "assignment", node)?;
let child_count = node.child_count();
@ -74,7 +76,7 @@ impl AbstractTree for Assignment {
})
}
fn check_type(&self, context: &Map) -> Result<()> {
fn check_type(&self, context: &Structure) -> Result<()> {
let statement_type = self.statement.expected_type(context)?;
if let Some(type_definition) = &self.type_definition {
@ -110,7 +112,7 @@ impl AbstractTree for Assignment {
Ok(())
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let key = self.identifier.inner();
let value = self.statement.run(source, context)?;
@ -143,7 +145,7 @@ impl AbstractTree for Assignment {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(Type::None)
}
}

View File

@ -4,7 +4,7 @@ use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Statement, Type, Value};
use crate::{AbstractTree, Error, Result, Statement, Structure, Type, Value};
/// Abstract representation of a block.
///
@ -21,7 +21,7 @@ pub struct Block {
}
impl AbstractTree for Block {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "block", node)?;
let first_child = node.child(0).unwrap();
@ -50,7 +50,7 @@ impl AbstractTree for Block {
})
}
fn check_type(&self, _context: &Map) -> Result<()> {
fn check_type(&self, _context: &Structure) -> Result<()> {
for statement in &self.statements {
if let Statement::Return(inner_statement) = statement {
return inner_statement.check_type(_context);
@ -62,7 +62,7 @@ impl AbstractTree for Block {
Ok(())
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
if self.is_async {
let statements = &self.statements;
let final_result = RwLock::new(Ok(Value::none()));
@ -111,7 +111,7 @@ impl AbstractTree for Block {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
if let Some(statement) = self.statements.iter().find(|statement| {
if let Statement::Return(_) = statement {
true

View File

@ -1,11 +1,12 @@
use std::{env::args, sync::OnceLock};
use enum_iterator::{all, Sequence};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, Identifier,
List, Map, Result, Type, TypeDefinition, Value,
List, Result, Structure, Type, Value,
};
static ARGS: OnceLock<Value> = OnceLock::new();
@ -14,7 +15,11 @@ static JSON: OnceLock<Value> = OnceLock::new();
static RANDOM: OnceLock<Value> = OnceLock::new();
static STRING: OnceLock<Value> = OnceLock::new();
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub fn built_in_values() -> impl Iterator<Item = BuiltInValue> {
all()
}
#[derive(Sequence, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInValue {
Args,
AssertEqual,
@ -27,121 +32,127 @@ pub enum BuiltInValue {
}
impl BuiltInValue {
pub fn name(&self) -> &'static str {
match self {
BuiltInValue::Args => "args",
BuiltInValue::AssertEqual => "assert_equal",
BuiltInValue::Fs => "fs",
BuiltInValue::Json => "json",
BuiltInValue::Length => "length",
BuiltInValue::Output => "output",
BuiltInValue::Random => "random",
BuiltInValue::String => "string",
}
}
pub fn get(self) -> Value {
match self {
BuiltInValue::Args => ARGS
.get_or_init(|| {
let args = args().map(|arg| Value::string(arg.to_string())).collect();
Value::List(List::with_items(args))
})
.clone(),
BuiltInValue::AssertEqual => {
Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
}
BuiltInValue::Fs => FS
.get_or_init(|| {
let fs_context = Structure::default();
fs_context
.set(
"read".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)),
None,
)
.unwrap();
Value::Structure(fs_context)
})
.clone(),
BuiltInValue::Json => JSON
.get_or_init(|| {
let json_context = Structure::default();
json_context
.set(
"parse".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
None,
)
.unwrap();
Value::Structure(json_context)
})
.clone(),
BuiltInValue::Length => Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::Output => Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
BuiltInValue::Random => RANDOM
.get_or_init(|| {
let random_context = Structure::default();
{
let mut variables = random_context.variables_mut().unwrap();
for built_in_function in [
BuiltInFunction::RandomBoolean,
BuiltInFunction::RandomFloat,
BuiltInFunction::RandomFrom,
BuiltInFunction::RandomInteger,
] {
let key = built_in_function.name().to_string();
let value = Value::Function(Function::BuiltIn(built_in_function));
let r#type = built_in_function.r#type();
variables.insert(key, (value, r#type));
}
}
Value::Structure(random_context)
})
.clone(),
BuiltInValue::String => STRING
.get_or_init(|| {
let string_context = Structure::default();
{
let mut variables = string_context.variables_mut().unwrap();
for string_function in string_functions() {
let key = string_function.name().to_string();
let value = Value::Function(Function::BuiltIn(
BuiltInFunction::String(string_function),
));
let r#type = string_function.r#type();
variables.insert(key, (value, r#type));
}
}
Value::Structure(string_context)
})
.clone(),
}
}
fn r#type(&self) -> Type {
match self {
BuiltInValue::Args => Type::list(Type::String),
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
BuiltInValue::Fs => Type::Map(Vec::new()),
BuiltInValue::Json => Type::Map(Vec::new()),
BuiltInValue::Fs => Type::Structure(Identifier::from(self.name())),
BuiltInValue::Json => Type::Structure(Identifier::from(self.name())),
BuiltInValue::Length => BuiltInFunction::Length.r#type(),
BuiltInValue::Output => BuiltInFunction::Output.r#type(),
BuiltInValue::Random => Type::Map(vec![
(
Identifier::new("boolean".to_string()),
TypeDefinition::new(BuiltInFunction::RandomBoolean.r#type()),
),
(
Identifier::new("float".to_string()),
TypeDefinition::new(BuiltInFunction::RandomFloat.r#type()),
),
(
Identifier::new("from".to_string()),
TypeDefinition::new(BuiltInFunction::RandomFrom.r#type()),
),
(
Identifier::new("integer".to_string()),
TypeDefinition::new(BuiltInFunction::RandomInteger.r#type()),
),
]),
BuiltInValue::String => Type::Map(Vec::new()),
}
}
fn get(&self) -> &Value {
match self {
BuiltInValue::Args => ARGS.get_or_init(|| {
let args = args().map(|arg| Value::string(arg.to_string())).collect();
Value::List(List::with_items(args))
}),
BuiltInValue::AssertEqual => {
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
}
BuiltInValue::Fs => FS.get_or_init(|| {
let fs_context = Map::new();
fs_context
.set(
"read".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::FsRead)),
None,
)
.unwrap();
Value::Map(fs_context)
}),
BuiltInValue::Json => JSON.get_or_init(|| {
let json_context = Map::new();
json_context
.set(
"parse".to_string(),
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
None,
)
.unwrap();
Value::Map(json_context)
}),
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
BuiltInValue::Random => RANDOM.get_or_init(|| {
let random_context = Map::new();
{
let mut variables = random_context.variables_mut().unwrap();
for built_in_function in [
BuiltInFunction::RandomBoolean,
BuiltInFunction::RandomFloat,
BuiltInFunction::RandomFrom,
BuiltInFunction::RandomInteger,
] {
let key = built_in_function.name().to_string();
let value = Value::Function(Function::BuiltIn(built_in_function));
let r#type = built_in_function.r#type();
variables.insert(key, (value, r#type));
}
}
Value::Map(random_context)
}),
BuiltInValue::String => STRING.get_or_init(|| {
let string_context = Map::new();
{
let mut variables = string_context.variables_mut().unwrap();
for string_function in string_functions() {
let key = string_function.name().to_string();
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function,
)));
let r#type = string_function.r#type();
variables.insert(key, (value, r#type));
}
}
Value::Map(string_context)
}),
BuiltInValue::Random => Type::Structure(Identifier::from(self.name())),
BuiltInValue::String => Type::Structure(Identifier::from(self.name())),
}
}
}
impl AbstractTree for BuiltInValue {
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> {
fn from_syntax_node(_source: &str, node: Node, _context: &Structure) -> Result<Self> {
let built_in_value = match node.kind() {
"args" => BuiltInValue::Args,
"assert_equal" => BuiltInValue::AssertEqual,
@ -157,11 +168,15 @@ impl AbstractTree for BuiltInValue {
Ok(built_in_value)
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
fn run(&self, _source: &str, _context: &Structure) -> Result<Value> {
Ok(self.get().clone())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn check_type(&self, _context: &Structure) -> Result<()> {
Ok(())
}
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(self.r#type())
}
}

View File

@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Type, Value, Yield,
value_node::ValueNode, AbstractTree, Error, Identifier, Index, Result, Structure, Type, Value,
Yield,
};
use super::{function_call::FunctionCall, logic::Logic, math::Math};
@ -24,7 +25,7 @@ pub enum Expression {
}
impl AbstractTree for Expression {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "expression", node)?;
let child = if node.child(0).unwrap().is_named() {
@ -65,7 +66,7 @@ impl AbstractTree for Expression {
Ok(expression)
}
fn check_type(&self, _context: &Map) -> Result<()> {
fn check_type(&self, _context: &Structure) -> Result<()> {
match self {
Expression::Value(value_node) => value_node.check_type(_context),
Expression::Identifier(identifier) => identifier.check_type(_context),
@ -77,7 +78,7 @@ impl AbstractTree for Expression {
}
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
match self {
Expression::Value(value_node) => value_node.run(source, context),
Expression::Identifier(identifier) => identifier.run(source, context),
@ -89,7 +90,7 @@ impl AbstractTree for Expression {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
match self {
Expression::Value(value_node) => value_node.expected_type(context),
Expression::Identifier(identifier) => identifier.expected_type(context),

View File

@ -2,7 +2,7 @@ use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value};
use crate::{AbstractTree, Block, Error, Expression, Identifier, Result, Structure, Type, Value};
/// Abstract representation of a for loop statement.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -11,10 +11,11 @@ pub struct For {
item_id: Identifier,
collection: Expression,
block: Block,
context: Structure,
}
impl AbstractTree for For {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "for", node)?;
let for_node = node.child(0).unwrap();
@ -45,36 +46,49 @@ impl AbstractTree for For {
item_id: identifier,
collection: expression,
block: item,
context: Structure::clone_from(context)?,
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
let expression_run = self.collection.run(source, context)?;
let values = expression_run.as_list()?.items();
fn check_type(&self, context: &Structure) -> Result<()> {
self.collection.check_type(context)?;
let key = self.item_id.inner();
let collection_type = self.collection.expected_type(context)?;
Type::list(Type::Any).check(&collection_type)?;
if let Type::List(item_type) = self.collection.expected_type(context)? {
self.context
.set(key.to_string(), Value::none(), Some(*item_type))?;
}
self.block.check_type(&self.context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let expression_run = self.collection.run(source, context)?;
let key = self.item_id.inner();
let values = expression_run.as_list()?.items();
if self.is_async {
values.par_iter().try_for_each(|value| {
let iter_context = Map::clone_from(context)?;
self.context.set(key.clone(), value.clone(), None)?;
iter_context.set(key.clone(), value.clone(), None)?;
self.block.run(source, &iter_context).map(|_value| ())
self.block.run(source, &self.context).map(|_value| ())
})?;
} else {
let loop_context = Map::clone_from(context)?;
for value in values.iter() {
loop_context.set(key.clone(), value.clone(), None)?;
self.context.set(key.clone(), value.clone(), None)?;
self.block.run(source, &loop_context)?;
self.block.run(source, &self.context)?;
}
}
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(Type::None)
}
}

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, FunctionExpression, Map, Result, Type, Value};
use crate::{AbstractTree, Error, Expression, FunctionExpression, Result, Structure, Type, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall {
@ -19,7 +19,7 @@ impl FunctionCall {
}
impl AbstractTree for FunctionCall {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "function_call", node)?;
let function_node = node.child(0).unwrap();
@ -44,20 +44,38 @@ impl AbstractTree for FunctionCall {
})
}
fn check_type(&self, context: &Map) -> Result<()> {
let function_expression_type = self.function_expression.expected_type(context)?;
fn check_type(&self, context: &Structure) -> Result<()> {
self.function_expression.check_type(context)?;
let variables = context.variables()?;
let function_type = match &self.function_expression {
FunctionExpression::Identifier(identifier) => {
let get_type = variables.get(identifier.inner());
if let Some((_, r#type)) = get_type {
r#type.clone()
} else {
return Err(Error::FunctionIdentifierNotFound(
identifier.inner().clone(),
));
}
}
function_expression => function_expression.expected_type(context)?,
};
let parameter_types = if let Type::Function {
parameter_types, ..
} = &function_expression_type
} = &function_type
{
parameter_types
} else {
return Err(Error::ExpectedFunctionType {
actual: function_expression_type,
return Err(Error::ExpectedFunctionExpression {
actual: self.function_expression.clone(),
});
};
for (index, expression) in self.arguments.iter().enumerate() {
expression.check_type(context)?;
if let Some(r#type) = parameter_types.get(index) {
r#type.check(&expression.expected_type(context)?)?;
}
@ -65,7 +83,7 @@ impl AbstractTree for FunctionCall {
if self.arguments.len() != parameter_types.len() {
return Err(Error::ExpectedFunctionArgumentAmount {
source: "TODO".to_string(),
source: "TODO".to_string(), // TODO
expected: parameter_types.len(),
actual: self.arguments.len(),
});
@ -74,7 +92,7 @@ impl AbstractTree for FunctionCall {
Ok(())
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let (name, value) = match &self.function_expression {
FunctionExpression::Identifier(identifier) => {
let key = identifier.inner();
@ -118,33 +136,15 @@ impl AbstractTree for FunctionCall {
.call(name, &arguments, source, context)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
match &self.function_expression {
FunctionExpression::Identifier(identifier) => {
let identifier_type = identifier.expected_type(context)?;
fn expected_type(&self, context: &Structure) -> Result<Type> {
let function_type = self.function_expression.expected_type(context)?;
if let Type::Function {
parameter_types: _,
return_type,
} = &identifier_type
{
Ok(*return_type.clone())
} else {
Ok(identifier_type)
}
}
FunctionExpression::FunctionCall(function_call) => function_call.expected_type(context),
FunctionExpression::Value(value_node) => {
let value_type = value_node.expected_type(context)?;
if let Type::Function { return_type, .. } = value_type {
Ok(*return_type)
} else {
Ok(value_type)
}
}
FunctionExpression::Index(index) => index.expected_type(context),
FunctionExpression::Yield(r#yield) => r#yield.expected_type(context),
if let Type::Function { return_type, .. } = function_type {
Ok(*return_type)
} else {
Err(Error::ExpectedFunctionExpression {
actual: self.function_expression.clone(),
})
}
}
}

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, Value, ValueNode,
Yield,
AbstractTree, Error, FunctionCall, Identifier, Index, Result, Structure, Type, Value,
ValueNode, Yield,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -16,7 +16,7 @@ pub enum FunctionExpression {
}
impl AbstractTree for FunctionExpression {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "function_expression", node)?;
let first_child = node.child(0).unwrap();
@ -54,7 +54,17 @@ impl AbstractTree for FunctionExpression {
Ok(function_expression)
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
match self {
FunctionExpression::Identifier(identifier) => identifier.check_type(_context),
FunctionExpression::FunctionCall(function_call) => function_call.check_type(_context),
FunctionExpression::Value(value_node) => value_node.check_type(_context),
FunctionExpression::Index(index) => index.check_type(_context),
FunctionExpression::Yield(r#yield) => r#yield.check_type(_context),
}
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
match self {
FunctionExpression::Identifier(identifier) => identifier.run(source, context),
FunctionExpression::FunctionCall(function_call) => function_call.run(source, context),
@ -64,7 +74,7 @@ impl AbstractTree for FunctionExpression {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
match self {
FunctionExpression::Identifier(identifier) => identifier.expected_type(context),
FunctionExpression::FunctionCall(function_call) => function_call.expected_type(context),

View File

@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Block, Error, Function, Identifier, Map, Result, Type, TypeDefinition, Value,
AbstractTree, Block, Error, Function, Identifier, Result, Structure, Type, TypeDefinition,
Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
@ -48,10 +49,10 @@ impl FunctionNode {
name: Option<String>,
arguments: &[Value],
source: &str,
outer_context: &Map,
outer_context: &Structure,
) -> Result<Value> {
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
let function_context = Map::clone_from(outer_context)?;
let function_context = Structure::clone_from(outer_context)?;
for (identifier, value) in parameter_argument_pairs {
let key = identifier.inner().clone();
@ -74,7 +75,7 @@ impl FunctionNode {
}
impl AbstractTree for FunctionNode {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "function", node)?;
let child_count = node.child_count();
@ -97,7 +98,7 @@ impl AbstractTree for FunctionNode {
}
}
let function_context = Map::clone_from(context)?;
let function_context = Structure::clone_from(context)?;
for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
function_context.set(
@ -118,18 +119,18 @@ impl AbstractTree for FunctionNode {
Ok(FunctionNode::new(parameters, body, r#type))
}
fn check_type(&self, context: &Map) -> Result<()> {
fn check_type(&self, context: &Structure) -> Result<()> {
self.return_type()
.check(&self.body.expected_type(context)?)?;
Ok(())
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
fn run(&self, _source: &str, _context: &Structure) -> Result<Value> {
Ok(Value::Function(Function::ContextDefined(self.clone())))
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(self.r#type().clone())
}
}

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Type, Value};
use crate::{AbstractTree, Error, Result, Structure, Type, Value};
/// A string by which a variable is known to a context.
///
@ -25,7 +25,7 @@ impl Identifier {
}
impl AbstractTree for Identifier {
fn from_syntax_node(source: &str, node: Node, _context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, _context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "identifier", node)?;
let text = &source[node.byte_range()];
@ -35,7 +35,7 @@ impl AbstractTree for Identifier {
Ok(Identifier(text.to_string()))
}
fn run(&self, _source: &str, context: &Map) -> Result<Value> {
fn run(&self, _source: &str, context: &Structure) -> Result<Value> {
if let Some((value, _)) = context.variables()?.get(&self.0) {
if !value.is_none() {
return Ok(value.clone());
@ -45,11 +45,27 @@ impl AbstractTree for Identifier {
Err(Error::VariableIdentifierNotFound(self.0.clone()))
}
fn expected_type(&self, context: &Map) -> Result<Type> {
if let Some((_value, r#type)) = context.variables()?.get(&self.0) {
fn check_type(&self, _context: &Structure) -> Result<()> {
Ok(())
}
fn expected_type(&self, context: &Structure) -> Result<Type> {
if let Some((_, r#type)) = context.variables()?.get(&self.0) {
Ok(r#type.clone())
} else {
Ok(Type::None)
Err(Error::VariableIdentifierNotFound(self.0.clone()))
}
}
}
impl From<String> for Identifier {
fn from(string: String) -> Self {
Identifier(string)
}
}
impl From<&str> for Identifier {
fn from(str: &str) -> Self {
Identifier(str.to_string())
}
}

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Expression, Map, Result, Type, Value};
use crate::{AbstractTree, Block, Expression, Result, Structure, Type, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse {
@ -13,7 +13,7 @@ pub struct IfElse {
}
impl AbstractTree for IfElse {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
let if_expression_node = node.child(0).unwrap().child(1).unwrap();
let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?;
@ -55,7 +55,26 @@ impl AbstractTree for IfElse {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.if_expression.check_type(_context)?;
self.if_block.check_type(_context)?;
for expression in &self.else_if_expressions {
expression.check_type(_context)?;
}
for block in &self.else_if_blocks {
block.check_type(_context)?;
}
if let Some(block) = &self.else_block {
block.check_type(_context)?;
}
Ok(())
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
if if_boolean {
@ -81,7 +100,7 @@ impl AbstractTree for IfElse {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.if_block.expected_type(context)
}
}

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, IndexExpression, List, Map, Result, Type, Value};
use crate::{
built_in_values, AbstractTree, Error, IndexExpression, List, Result, Structure, Type, Value,
};
/// Abstract representation of an index expression.
///
@ -14,7 +16,7 @@ pub struct Index {
}
impl AbstractTree for Index {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "index", node)?;
let collection_node = node.child(0).unwrap();
@ -41,7 +43,7 @@ impl AbstractTree for Index {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let collection = self.collection.run(source, context)?;
match collection {
@ -59,11 +61,12 @@ impl AbstractTree for Index {
Ok(item)
}
Value::Map(map) => {
Value::Structure(structure) => {
let value = if let IndexExpression::Identifier(identifier) = &self.index {
let key = identifier.inner();
map.variables()?
structure
.variables()?
.get(key)
.map(|(value, _)| value.clone())
.unwrap_or_default()
@ -71,7 +74,8 @@ impl AbstractTree for Index {
let value = self.index.run(source, context)?;
let key = value.as_string()?;
map.variables()?
structure
.variables()?
.get(key.as_str())
.map(|(value, _)| value.clone())
.unwrap_or_default()
@ -89,21 +93,81 @@ impl AbstractTree for Index {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn check_type(&self, context: &Structure) -> Result<()> {
let collection_type = self.collection.expected_type(context)?;
match collection_type {
Type::List(_) | Type::String | Type::Structure(_) | Type::StructureDefinition(_) => {
Ok(())
}
_ => Err(Error::TypeCheck {
expected: Type::Collection,
actual: collection_type,
}),
}
}
fn expected_type(&self, context: &Structure) -> Result<Type> {
match self.collection.expected_type(context)? {
Type::List(item_type) => Ok(*item_type.clone()),
Type::Map(identifier_types) => {
if let IndexExpression::Identifier(index_identifier) = &self.index {
for (identifier, r#type) in identifier_types {
if &identifier == index_identifier {
return Ok(r#type.take_inner());
Type::StructureDefinition(instantiator) => match &self.index {
IndexExpression::Value(_) => todo!(),
IndexExpression::Identifier(identifier) => {
if let Some((statement_option, type_option)) =
instantiator.get(identifier.inner())
{
if let Some(type_definition) = type_option {
Ok(type_definition.inner().clone())
} else if let Some(statement) = statement_option {
statement.expected_type(context)
} else {
Ok(Type::None)
}
} else {
Err(Error::VariableIdentifierNotFound(
identifier.inner().clone(),
))
}
}
IndexExpression::Index(_) => todo!(),
IndexExpression::FunctionCall(_) => todo!(),
},
Type::Structure(definition_identifier) => {
let key = definition_identifier.inner();
let variables = context.variables()?;
let get_structure = variables.get(key);
let value = if let Some((value, _)) = get_structure {
value.clone()
} else {
let find_built_in_value =
built_in_values().find(|built_in_value| built_in_value.name() == key);
Ok(Type::None)
if let Some(built_in_value) = find_built_in_value {
built_in_value.get()
} else {
return Err(Error::VariableIdentifierNotFound(key.to_string()));
}
};
let structure = value.as_structure()?;
match &self.index {
IndexExpression::Identifier(identifier) => {
let inner_variables = structure.variables()?;
let get_type = inner_variables.get(identifier.inner());
if let Some((_, r#type)) = get_type {
Ok(r#type.clone())
} else {
Err(Error::VariableIdentifierNotFound(
identifier.inner().clone(),
))
}
}
IndexExpression::Value(_) => todo!(),
IndexExpression::Index(_) => todo!(),
IndexExpression::FunctionCall(_) => todo!(),
}
}
Type::None => Ok(Type::None),
r#type => Ok(r#type),
}
}

View File

@ -1,7 +1,9 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Index, IndexExpression, Map, Result, Statement, Type, Value};
use crate::{
AbstractTree, Error, Index, IndexExpression, Result, Statement, Structure, Type, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct IndexAssignment {
@ -18,7 +20,7 @@ pub enum AssignmentOperator {
}
impl AbstractTree for IndexAssignment {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "index_assignment", node)?;
let index_node = node.child(0).unwrap();
@ -49,9 +51,14 @@ impl AbstractTree for IndexAssignment {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.index.check_type(_context)?;
self.statement.check_type(_context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let index_collection = self.index.collection.run(source, context)?;
let index_context = index_collection.as_map().unwrap_or(context);
let index_context = index_collection.as_structure().unwrap_or(context);
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier.inner()
} else {
@ -91,7 +98,7 @@ impl AbstractTree for IndexAssignment {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(Type::None)
}
}

View File

@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::{
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type,
Value,
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Result, Structure,
Type, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -14,7 +14,11 @@ pub enum IndexExpression {
}
impl AbstractTree for IndexExpression {
fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &Map) -> Result<Self> {
fn from_syntax_node(
source: &str,
node: tree_sitter::Node,
context: &Structure,
) -> Result<Self> {
Error::expect_syntax_node(source, "index_expression", node)?;
let first_child = node.child(0).unwrap();
@ -48,7 +52,16 @@ impl AbstractTree for IndexExpression {
Ok(abstract_node)
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
match self {
IndexExpression::Value(value_node) => value_node.check_type(_context),
IndexExpression::Identifier(identifier) => identifier.check_type(_context),
IndexExpression::Index(index) => index.check_type(_context),
IndexExpression::FunctionCall(function_call) => function_call.check_type(_context),
}
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
match self {
IndexExpression::Value(value_node) => value_node.run(source, context),
IndexExpression::Identifier(identifier) => identifier.run(source, context),
@ -57,7 +70,7 @@ impl AbstractTree for IndexExpression {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
match self {
IndexExpression::Value(value_node) => value_node.expected_type(context),
IndexExpression::Identifier(identifier) => identifier.expected_type(context),

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value};
use crate::{AbstractTree, Error, Expression, Result, Structure, Type, Value};
/// Abstract representation of a logic expression.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -12,7 +12,7 @@ pub struct Logic {
}
impl AbstractTree for Logic {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "logic", node)?;
let first_node = node.child(0).unwrap();
@ -59,7 +59,12 @@ impl AbstractTree for Logic {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.left.check_type(_context)?;
self.right.check_type(_context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?;
let result = match self.operator {
@ -88,7 +93,7 @@ impl AbstractTree for Logic {
Ok(Value::Boolean(result))
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(Type::Boolean)
}
}

View File

@ -6,7 +6,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Map, Result, Statement, Type, Value};
use crate::{AbstractTree, Error, Expression, Result, Statement, Structure, Type, Value};
/// Abstract representation of a match statement.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -17,7 +17,7 @@ pub struct Match {
}
impl AbstractTree for Match {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "match", node)?;
let matcher_node = node.child(1).unwrap();
@ -58,7 +58,22 @@ impl AbstractTree for Match {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.matcher.check_type(_context)?;
for (expression, statement) in &self.options {
expression.check_type(_context)?;
statement.check_type(_context)?;
}
if let Some(statement) = &self.fallback {
statement.check_type(_context)?;
}
Ok(())
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let matcher_value = self.matcher.run(source, context)?;
for (expression, statement) in &self.options {
@ -76,7 +91,7 @@ impl AbstractTree for Match {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
let (_, first_statement) = self.options.first().unwrap();
first_statement.expected_type(context)

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value};
use crate::{AbstractTree, Error, Expression, Result, Structure, Type, Value};
/// Abstract representation of a math operation.
///
@ -15,7 +15,7 @@ pub struct Math {
}
impl AbstractTree for Math {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "math", node)?;
let left_node = node.child(0).unwrap();
@ -48,7 +48,12 @@ impl AbstractTree for Math {
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.left.check_type(_context)?;
self.right.check_type(_context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?;
let value = match self.operator {
@ -62,7 +67,7 @@ impl AbstractTree for Math {
Ok(value)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.left.expected_type(context)
}
}

View File

@ -23,6 +23,7 @@ pub mod logic;
pub mod r#match;
pub mod math;
pub mod statement;
pub mod structure_instantiator;
pub mod type_definition;
pub mod value_node;
pub mod r#while;
@ -32,19 +33,20 @@ pub use {
assignment::*, block::*, built_in_value::*, expression::*, function_call::*,
function_expression::*, function_node::*, identifier::*, if_else::*, index::*,
index_assignment::IndexAssignment, index_expression::*, logic::*, math::*, r#for::*,
r#match::*, r#while::*, r#yield::*, statement::*, type_definition::*, value_node::*,
r#match::*, r#while::*, r#yield::*, statement::*, structure_instantiator::*,
type_definition::*, value_node::*,
};
use tree_sitter::Node;
use crate::{Error, Map, Result, Value};
use crate::{Error, Result, Structure, Value};
pub struct Root {
statements: Vec<Statement>,
}
impl AbstractTree for Root {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "root", node)?;
let statement_count = node.child_count();
@ -60,7 +62,7 @@ impl AbstractTree for Root {
Ok(Root { statements })
}
fn check_type(&self, _context: &Map) -> Result<()> {
fn check_type(&self, _context: &Structure) -> Result<()> {
for statement in &self.statements {
if let Statement::Return(inner_statement) = statement {
return inner_statement.check_type(_context);
@ -72,7 +74,7 @@ impl AbstractTree for Root {
Ok(())
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let mut value = Value::none();
for statement in &self.statements {
@ -86,7 +88,7 @@ impl AbstractTree for Root {
Ok(value)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.statements.last().unwrap().expected_type(context)
}
}
@ -103,15 +105,13 @@ pub trait AbstractTree: Sized {
///
/// If necessary, the source code can be accessed directly by getting the
/// node's byte range.
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self>;
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self>;
/// Verify the type integrity of the node.
fn check_type(&self, _context: &Map) -> Result<()> {
Ok(())
}
fn check_type(&self, _context: &Structure) -> Result<()>;
/// Execute dust code by traversing the tree.
fn run(&self, source: &str, context: &Map) -> Result<Value>;
fn run(&self, source: &str, context: &Structure) -> Result<Value>;
fn expected_type(&self, context: &Map) -> Result<Type>;
fn expected_type(&self, context: &Structure) -> Result<Type>;
}

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match,
Result, Type, Value, While,
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Match,
Result, Structure, Type, Value, While,
};
/// Abstract representation of a statement.
@ -21,7 +21,7 @@ pub enum Statement {
}
impl AbstractTree for Statement {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "statement", node)?;
let child = node.child(0).unwrap();
@ -66,7 +66,7 @@ impl AbstractTree for Statement {
}
}
fn check_type(&self, _context: &Map) -> Result<()> {
fn check_type(&self, _context: &Structure) -> Result<()> {
match self {
Statement::Assignment(assignment) => assignment.check_type(_context),
Statement::Expression(expression) => expression.check_type(_context),
@ -80,7 +80,7 @@ impl AbstractTree for Statement {
}
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
match self {
Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Expression(expression) => expression.run(source, context),
@ -94,7 +94,7 @@ impl AbstractTree for Statement {
}
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
match self {
Statement::Assignment(assignment) => assignment.expected_type(context),
Statement::Expression(expression) => expression.expected_type(context),

View File

@ -0,0 +1,130 @@
use std::collections::{btree_map, BTreeMap};
use serde::{Deserialize, Serialize};
use crate::{
AbstractTree, Error, Identifier, Result, Statement, Structure, Type, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructureInstantiator(BTreeMap<String, (Option<Statement>, Option<TypeDefinition>)>);
impl StructureInstantiator {
pub fn new() -> Self {
StructureInstantiator(BTreeMap::new())
}
pub fn get(&self, key: &str) -> Option<&(Option<Statement>, Option<TypeDefinition>)> {
self.0.get(key)
}
pub fn set(
&mut self,
key: String,
statement: Option<Statement>,
type_definition: Option<TypeDefinition>,
) {
self.0.insert(key, (statement, type_definition));
}
pub fn iter(&self) -> btree_map::Iter<'_, String, (Option<Statement>, Option<TypeDefinition>)> {
self.0.iter()
}
}
impl AbstractTree for StructureInstantiator {
fn from_syntax_node(
source: &str,
node: tree_sitter::Node,
context: &Structure,
) -> crate::Result<Self> {
Error::expect_syntax_node(source, "structure_instantiator", node)?;
let child_count = node.child_count();
let mut instantiator = StructureInstantiator::new();
let mut current_key = "".to_string();
let mut current_type = None;
for index in 1..child_count - 1 {
let child_syntax_node = node.child(index).unwrap();
if child_syntax_node.kind() == "identifier" {
if let Some(type_definition) = current_type {
instantiator.set(current_key, None, Some(type_definition));
current_type = None;
}
current_key =
Identifier::from_syntax_node(source, child_syntax_node, context)?.take_inner();
}
if child_syntax_node.kind() == "type_definition" {
current_type = Some(TypeDefinition::from_syntax_node(
source,
child_syntax_node,
context,
)?);
}
if child_syntax_node.kind() == "statement" {
let statement = Statement::from_syntax_node(source, child_syntax_node, context)?;
instantiator.set(current_key.clone(), Some(statement), current_type.clone());
current_type = None;
}
}
Ok(instantiator)
}
fn check_type(&self, context: &Structure) -> Result<()> {
for (_key, (statement_option, type_definition_option)) in &self.0 {
let statement_type = if let Some(statement) = statement_option {
statement.check_type(context)?;
Some(statement.expected_type(context)?)
} else {
None
};
if let (Some(statement_type), Some(type_definition)) =
(statement_type, type_definition_option)
{
type_definition.inner().check(&statement_type)?;
}
}
Ok(())
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let mut variables = BTreeMap::new();
for (key, (statement_option, type_definition_option)) in &self.0 {
let (value, r#type) = match (statement_option, type_definition_option) {
(Some(statement), Some(type_definition)) => {
let value = statement.run(source, context)?;
(value, type_definition.inner().clone())
}
(Some(statement), None) => {
let value = statement.run(source, context)?;
let r#type = value.r#type();
(value, r#type)
}
(None, Some(r#type)) => (Value::none(), r#type.inner().clone()),
(None, None) => (Value::none(), Type::None),
};
variables.insert(key.clone(), (value, r#type));
}
Ok(Value::Structure(Structure::new(variables, self.clone())))
}
fn expected_type(&self, _context: &Structure) -> Result<Type> {
todo!()
}
}

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Identifier, Map, Result, Value};
use crate::{AbstractTree, Error, Identifier, Result, Structure, StructureInstantiator, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct TypeDefinition {
@ -25,7 +25,7 @@ impl TypeDefinition {
}
impl AbstractTree for TypeDefinition {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "type_definition", node)?;
let type_node = node.child(1).unwrap();
@ -34,11 +34,15 @@ impl AbstractTree for TypeDefinition {
Ok(TypeDefinition { r#type })
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
Ok(())
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
self.r#type.run(source, context)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.r#type.expected_type(context)
}
}
@ -61,10 +65,11 @@ pub enum Type {
},
Integer,
List(Box<Type>),
Map(Vec<(Identifier, TypeDefinition)>),
None,
Number,
String,
Structure(Identifier),
StructureDefinition(StructureInstantiator),
Option(Box<Type>),
}
@ -92,8 +97,8 @@ impl Type {
| (Type::Collection, Type::Collection)
| (Type::Collection, Type::List(_))
| (Type::List(_), Type::Collection)
| (Type::Collection, Type::Map(_))
| (Type::Map(_), Type::Collection)
| (Type::Collection, Type::Structure(_))
| (Type::Structure(_), Type::Collection)
| (Type::Collection, Type::String)
| (Type::String, Type::Collection)
| (Type::Float, Type::Float)
@ -105,7 +110,7 @@ impl Type {
| (Type::Float, Type::Number)
| (Type::None, Type::None)
| (Type::String, Type::String) => Ok(()),
(Type::Map(left), Type::Map(right)) => {
(Type::Structure(left), Type::Structure(right)) => {
if left == right {
Ok(())
} else {
@ -181,7 +186,7 @@ impl Type {
}
impl AbstractTree for Type {
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> {
fn from_syntax_node(_source: &str, node: Node, _context: &Structure) -> Result<Self> {
Error::expect_syntax_node(_source, "type", node)?;
let type_node = node.child(0).unwrap();
@ -228,32 +233,8 @@ impl AbstractTree for Type {
"num" => Type::Number,
"none" => Type::None,
"str" => Type::String,
"{" => {
let child_count = node.child_count();
let mut identifier_types = Vec::new();
let mut identifier = None;
for index in 1..child_count - 1 {
let child = node.child(index).unwrap();
match child.kind() {
"identifier" => {
identifier =
Some(Identifier::from_syntax_node(_source, child, _context)?);
}
"type_definition" => {
if let Some(identifier) = &identifier {
let type_definition =
TypeDefinition::from_syntax_node(_source, child, _context)?;
identifier_types.push((identifier.clone(), type_definition));
}
}
_ => {}
}
}
Type::Map(identifier_types)
"identifier" => {
Type::Structure(Identifier::from_syntax_node(_source, type_node, _context)?)
}
"option" => {
let inner_type_node = node.child(2).unwrap();
@ -274,11 +255,15 @@ impl AbstractTree for Type {
Ok(r#type)
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
Ok(())
}
fn run(&self, _source: &str, _context: &Structure) -> Result<Value> {
Ok(Value::none())
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
Ok(Type::None)
}
}
@ -309,15 +294,8 @@ impl Display for Type {
}
Type::Integer => write!(f, "int"),
Type::List(item_type) => write!(f, "[{item_type}]"),
Type::Map(identifier_types) => {
write!(f, "{{")?;
for (identifier, r#type) in identifier_types {
write!(f, "{} {}", identifier.inner(), r#type)?;
}
write!(f, "}}")
}
Type::Structure(identifier) => write!(f, "{}", identifier.inner()),
Type::StructureDefinition(_) => todo!(),
Type::Number => write!(f, "num"),
Type::None => write!(f, "none"),
Type::String => write!(f, "str"),

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result,
Statement, Type, TypeDefinition, Value,
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Result, Structure,
StructureInstantiator, Type, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -17,12 +17,16 @@ pub enum ValueNode {
String(String),
List(Vec<Expression>),
Option(Option<Box<Expression>>),
Map(BTreeMap<String, (Statement, Option<Type>)>),
Structure {
definition_name: Identifier,
instantiator: StructureInstantiator,
},
StructureDefinition(StructureInstantiator),
BuiltInValue(BuiltInValue),
}
impl AbstractTree for ValueNode {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "value", node)?;
let child = node.child(0).unwrap();
@ -51,41 +55,32 @@ impl AbstractTree for ValueNode {
ValueNode::List(expressions)
}
"map" => {
let mut child_nodes = BTreeMap::new();
let mut current_key = "".to_string();
let mut current_type = None;
"structure" => {
let identifier_node = child.child(1).unwrap();
let identifier = Identifier::from_syntax_node(source, identifier_node, context)?;
for index in 0..child.child_count() - 1 {
let child_syntax_node = child.child(index).unwrap();
let instantiator_node = child.child(2);
if child_syntax_node.kind() == "identifier" {
current_key =
Identifier::from_syntax_node(source, child_syntax_node, context)?
.take_inner();
current_type = None;
}
if child_syntax_node.kind() == "type_definition" {
current_type = Some(
TypeDefinition::from_syntax_node(source, child_syntax_node, context)?
.take_inner(),
);
}
if child_syntax_node.kind() == "statement" {
let statement =
Statement::from_syntax_node(source, child_syntax_node, context)?;
if let Some(type_definition) = &current_type {
type_definition.check(&statement.expected_type(context)?)?;
}
child_nodes.insert(current_key.clone(), (statement, current_type.clone()));
if let Some(node) = instantiator_node {
let instantiator =
StructureInstantiator::from_syntax_node(source, node, context)?;
ValueNode::Structure {
definition_name: identifier,
instantiator,
}
} else {
todo!()
}
}
"structure_definition" => {
let instantiator_node = child.child(1).unwrap();
ValueNode::Map(child_nodes)
ValueNode::StructureDefinition(StructureInstantiator::from_syntax_node(
source,
instantiator_node,
context,
)?)
}
"option" => {
let first_grandchild = child.child(0).unwrap();
@ -122,7 +117,26 @@ impl AbstractTree for ValueNode {
Ok(value_node)
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, context: &Structure) -> Result<()> {
match self {
ValueNode::StructureDefinition(instantiator) => {
for (_, (statement_option, type_definition_option)) in instantiator.iter() {
if let (Some(statement), Some(type_definition)) =
(statement_option, type_definition_option)
{
type_definition
.inner()
.check(&statement.expected_type(context)?)?;
}
}
}
_ => {}
}
Ok(())
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
let value = match self {
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
@ -149,26 +163,51 @@ impl AbstractTree for ValueNode {
Value::Option(option_value)
}
ValueNode::Map(key_statement_pairs) => {
let map = Map::new();
ValueNode::Structure {
definition_name,
instantiator,
} => {
let variables = context.variables()?;
let definition = if let Some((value, _)) = variables.get(definition_name.inner()) {
value.as_structure()?.instantiator()
} else {
return Err(Error::VariableIdentifierNotFound(
definition_name.inner().clone(),
));
};
let structure = Structure::new(BTreeMap::new(), definition.clone());
for (key, (statement_option, type_definition_option)) in
definition.iter().chain(instantiator.iter())
{
for (key, (statement, r#type)) in key_statement_pairs {
let value = statement.run(source, context)?;
let value = if let Some(statement) = statement_option {
statement.run(source, context)?
} else {
Value::none()
};
map.set(key.clone(), value, r#type.clone())?;
if let Some(type_definition) = &type_definition_option {
structure.set(
key.to_string(),
value,
Some(type_definition.inner().clone()),
)?;
} else {
structure.set(key.to_string(), value, None)?;
}
}
Value::Map(map)
Value::Structure(structure)
}
ValueNode::StructureDefinition(instantiator) => instantiator.run(source, context)?,
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
};
Ok(value)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,
ValueNode::Float(_) => Type::Float,
@ -203,17 +242,11 @@ impl AbstractTree for ValueNode {
Type::None
}
}
ValueNode::Map(statements) => {
let mut identifier_types = Vec::new();
for (key, (statement, _)) in statements {
identifier_types.push((
Identifier::new(key.clone()),
TypeDefinition::new(statement.expected_type(context)?),
));
}
Type::Map(identifier_types)
ValueNode::Structure {
definition_name, ..
} => Type::Structure(definition_name.clone()),
ValueNode::StructureDefinition(instantiator) => {
Type::StructureDefinition(instantiator.clone())
}
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
};

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Expression, Map, Result, Type, Value};
use crate::{AbstractTree, Block, Error, Expression, Result, Structure, Type, Value};
/// Abstract representation of a while loop.
///
@ -13,7 +13,7 @@ pub struct While {
}
impl AbstractTree for While {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> crate::Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> crate::Result<Self> {
Error::expect_syntax_node(source, "while", node)?;
let expression_node = node.child(1).unwrap();
@ -25,7 +25,12 @@ impl AbstractTree for While {
Ok(While { expression, block })
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.expression.check_type(_context)?;
self.block.check_type(_context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
while self.expression.run(source, context)?.as_boolean()? {
self.block.run(source, context)?;
}
@ -33,7 +38,7 @@ impl AbstractTree for While {
Ok(Value::none())
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.block.expected_type(context)
}
}

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Map,
Result, Type, Value,
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Result,
Structure, Type, Value,
};
/// Abstract representation of a yield expression.
@ -15,7 +15,7 @@ pub struct Yield {
}
impl AbstractTree for Yield {
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
fn from_syntax_node(source: &str, node: Node, context: &Structure) -> Result<Self> {
Error::expect_syntax_node(source, "yield", node)?;
let input_node = node.child(0).unwrap();
@ -44,11 +44,15 @@ impl AbstractTree for Yield {
Ok(Yield { call })
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
fn check_type(&self, _context: &Structure) -> Result<()> {
self.call.check_type(_context)
}
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
self.call.run(source, context)
}
fn expected_type(&self, context: &Map) -> Result<Type> {
fn expected_type(&self, context: &Structure) -> Result<Type> {
self.call.expected_type(context)
}
}

View File

@ -1,227 +0,0 @@
use std::{fs::read_to_string, path::PathBuf};
use dust_lang::{Interpreter, Map, Result, Value};
use egui::{Align, Color32, Layout, RichText, ScrollArea};
use egui_extras::{Column, TableBuilder};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
pub struct App {
path: String,
source: String,
context: Map,
#[serde(skip)]
interpreter: Interpreter,
output: Result<Value>,
error: Option<String>,
}
impl App {
pub fn new(cc: &eframe::CreationContext<'_>, path: PathBuf) -> Self {
fn create_app(path: PathBuf) -> App {
let context = Map::new();
let mut interpreter = Interpreter::new(context.clone());
let read_source = read_to_string(&path);
let source = if let Ok(source) = read_source {
source
} else {
String::new()
};
let output = interpreter.run(&source);
App {
path: path.to_string_lossy().to_string(),
source,
context,
interpreter,
output,
error: None,
}
}
cc.egui_ctx.set_zoom_factor(1.2);
if path.is_file() {
create_app(path)
} else {
if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY)
.unwrap_or_else(|| create_app(path));
} else {
create_app(path)
}
}
}
}
impl eframe::App for App {
/// Called by the frame work to save state before shutdown.
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self);
}
/// Called each time the UI needs repainting, which may be many times per second.
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
ui.add_space(16.0);
egui::widgets::global_dark_light_mode_buttons(ui);
ui.with_layout(Layout::right_to_left(Align::Max), |ui| {
egui::warn_if_debug_build(ui);
ui.hyperlink_to("source code", "https://git.jeffa.io/jeff/dust");
});
});
});
egui::CentralPanel::default().show(ctx, |ui| {
ui.columns(2, |columns| {
ScrollArea::vertical()
.id_source("source")
.show(&mut columns[0], |ui| {
if let Some(error) = &self.error {
ui.label(RichText::new(error).color(Color32::LIGHT_RED));
}
ui.text_edit_singleline(&mut self.path);
ui.code_editor(&mut self.source);
if ui.button("read").clicked() {
match read_to_string(&self.path) {
Ok(source) => {
self.source = source;
self.error = None;
}
Err(error) => self.error = Some(error.to_string()),
}
}
if ui.button("run").clicked() {
self.output = self.interpreter.run(&self.source);
}
});
ScrollArea::vertical()
.id_source("output")
.show(&mut columns[1], |ui| match &self.output {
Ok(value) => display_value(value, ui),
Err(error) => {
ui.label(RichText::new(error.to_string()).color(Color32::LIGHT_RED));
display_value(&Value::Map(self.context.clone()), ui);
match &self.output {
Ok(value) => {
display_value(value, ui);
}
Err(error) => {
ui.label(error.to_string());
}
}
}
});
});
});
}
}
fn display_value(value: &Value, ui: &mut egui::Ui) {
match value {
Value::List(list) => {
let table = TableBuilder::new(ui)
.striped(true)
.resizable(true)
.column(Column::auto())
.column(Column::auto());
table
.header(20.0, |mut header| {
header.col(|ui| {
ui.strong("index");
});
})
.body(|mut body| {
for (index, value) in list.items().iter().enumerate() {
body.row(20.0, |mut row| {
row.col(|ui| {
ui.label(index.to_string());
});
row.col(|ui| {
display_value(value, ui);
});
});
}
});
}
Value::Map(map) => {
let table = TableBuilder::new(ui)
.striped(true)
.resizable(true)
.column(Column::auto())
.column(Column::auto());
table
.header(20.0, |mut header| {
header.col(|ui| {
ui.strong("key");
});
})
.body(|mut body| {
for (key, (value, _)) in map.variables().unwrap().iter() {
body.row(20.0, |mut row| {
row.col(|ui| {
ui.label(key);
});
row.col(|ui| {
display_value(value, ui);
});
});
}
});
}
Value::Function(function) => {
ui.label(function.to_string());
}
Value::String(string) => {
ui.label(RichText::new(string.read().unwrap().as_str()).color(Color32::GREEN));
}
Value::Float(float) => {
ui.label(float.to_string());
}
Value::Integer(integer) => {
ui.label(RichText::new(integer.to_string()).color(Color32::BLUE));
}
Value::Boolean(boolean) => {
ui.label(RichText::new(boolean.to_string()).color(Color32::RED));
}
Value::Option(option) => match option {
Some(value) => {
let table = TableBuilder::new(ui)
.striped(true)
.resizable(true)
.column(Column::auto());
table
.header(20.0, |mut header| {
header.col(|ui| {
ui.strong("some");
});
})
.body(|mut body| {
body.row(20.0, |mut row| {
row.col(|ui| {
display_value(value, ui);
});
});
});
}
None => {
ui.label("none");
}
},
}
}

View File

@ -1,35 +0,0 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::path::PathBuf;
use clap::Parser;
mod app;
#[derive(Parser)]
struct Args {
// Path to the file to read.
path: Option<PathBuf>,
}
fn main() -> eframe::Result<()> {
env_logger::init();
let path = if let Some(path) = Args::parse().path {
path
} else {
PathBuf::new()
};
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_inner_size([400.0, 300.0])
.with_min_inner_size([300.0, 220.0]),
..Default::default()
};
eframe::run_native(
"Dust GUI",
native_options,
Box::new(|cc| Box::new(app::App::new(cc, path))),
)
}

View File

@ -5,7 +5,7 @@ use std::fs::read_to_string;
use rand::{random, thread_rng, Rng};
use serde::{Deserialize, Serialize};
use crate::{Error, Map, Result, Type, Value};
use crate::{Error, Result, Structure, Type, Value};
pub use string::{string_functions, StringFunction};
@ -54,7 +54,12 @@ impl BuiltInFunction {
}
}
pub fn call(&self, arguments: &[Value], _source: &str, _outer_context: &Map) -> Result<Value> {
pub fn call(
&self,
arguments: &[Value],
_source: &str,
_outer_context: &Structure,
) -> Result<Value> {
match self {
BuiltInFunction::AssertEqual => {
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
@ -86,7 +91,7 @@ impl BuiltInFunction {
let value = arguments.first().unwrap();
let length = if let Ok(list) = value.as_list() {
list.items().len()
} else if let Ok(map) = value.as_map() {
} else if let Ok(map) = value.as_structure() {
map.variables()?.len()
} else if let Ok(str) = value.as_string() {
str.chars().count()

View File

@ -1,7 +1,7 @@
use enum_iterator::{all, Sequence};
use serde::{Deserialize, Serialize};
use crate::{Error, List, Map, Result, Type, Value};
use crate::{Error, List, Result, Structure, Type, Value};
pub fn string_functions() -> impl Iterator<Item = StringFunction> {
all()
@ -168,7 +168,12 @@ impl StringFunction {
}
}
pub fn call(&self, arguments: &[Value], _source: &str, _outer_context: &Map) -> Result<Value> {
pub fn call(
&self,
arguments: &[Value],
_source: &str,
_outer_context: &Structure,
) -> Result<Value> {
let value = match self {
StringFunction::AsBytes => {
Error::expect_argument_amount(self.name(), 1, arguments.len())?;

View File

@ -1,12 +1,10 @@
//! Error and Result types.
//!
//! To deal with errors from dependencies, either create a new error variant
//! or use the ToolFailure variant if the error can only occur inside a tool.
//! To deal with errors from dependencies, create a new Error variant.
use serde::{Deserialize, Serialize};
use tree_sitter::{LanguageError, Node, Point};
use crate::{value::Value, Type};
use crate::{value::Value, FunctionExpression, IndexExpression, Type};
use std::{
fmt::{self, Formatter},
@ -56,6 +54,10 @@ pub enum Error {
actual: usize,
},
ExpectedIndexIdentifier {
actual: IndexExpression,
},
/// An operator was called with the wrong amount of arguments.
ExpectedOperatorArgumentAmount {
expected: usize,
@ -83,8 +85,8 @@ pub enum Error {
actual: usize,
},
ExpectedFunctionType {
actual: Type,
ExpectedFunctionExpression {
actual: FunctionExpression,
},
ExpectedString {
@ -152,6 +154,14 @@ pub enum Error {
actual: Value,
},
ExpectedDefaultValue {
variable_name: String,
},
ExpectedStructureDefinition {
actual: Type,
},
/// A `VariableIdentifier` operation did not find its value in the context.
VariableIdentifierNotFound(String),
@ -434,11 +444,18 @@ impl fmt::Display for Error {
f,
"Parsing was cancelled either manually or because it took too long."
),
ExpectedFunctionType { actual } => write!(f, "Expected a function but got {actual}."),
ExpectedFunctionExpression { actual } => {
write!(f, "Expected a function expression but got {actual:?}.")
}
ExpectedStructureDefinition { actual } => {
write!(f, "Expected a structure definition but got {actual:?}")
}
ExpectedDefaultValue { variable_name } => write!(f, "No default value was found for the structure field \"{variable_name}\", a value must be provided."),
ExpectedIndexIdentifier { actual } => write!(f, "Expected an identifier but for {actual:?}."),
}
}
}
fn get_position(position: &Point) -> String {
format!("column {}, row {}", position.row + 1, position.column)
format!("row {}, column {}", position.row + 1, position.column)
}

View File

@ -4,7 +4,7 @@
//! functions or by constructing your own Evaluator.
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
use crate::{language, AbstractTree, Error, Result, Root, Structure, Value};
/// Interpret the given source code.
///
@ -18,7 +18,7 @@ use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
/// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6)));
/// ```
pub fn interpret(source: &str) -> Result<Value> {
interpret_with_context(source, Map::new())
interpret_with_context(source, Structure::default())
}
/// Interpret the given source code with the given context.
@ -40,7 +40,7 @@ pub fn interpret(source: &str) -> Result<Value> {
/// Ok(Value::Integer(10))
/// );
/// ```
pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> {
pub fn interpret_with_context(source: &str, context: Structure) -> Result<Value> {
let mut interpreter = Interpreter::new(context);
let value = interpreter.run(source)?;
@ -50,13 +50,13 @@ pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> {
/// A source code interpreter for the Dust language.
pub struct Interpreter {
parser: Parser,
context: Map,
context: Structure,
syntax_tree: Option<TSTree>,
abstract_tree: Option<Root>,
}
impl Interpreter {
pub fn new(context: Map) -> Self {
pub fn new(context: Structure) -> Self {
let mut parser = Parser::new();
parser
@ -133,6 +133,6 @@ impl Interpreter {
impl Default for Interpreter {
fn default() -> Self {
Interpreter::new(Map::new())
Interpreter::new(Structure::default())
}
}

View File

@ -8,7 +8,7 @@ pub use crate::{
built_in_functions::BuiltInFunction,
error::*,
interpret::*,
value::{function::Function, list::List, map::Map, Value},
value::{function::Function, list::List, structure::Structure, Value},
};
mod abstract_tree;

View File

@ -12,7 +12,7 @@ use tree_sitter::Parser as TSParser;
use std::{borrow::Cow, fs::read_to_string};
use dust_lang::{language, Interpreter, Map, Value};
use dust_lang::{language, Interpreter, Structure, Value};
/// Command-line arguments to be parsed.
#[derive(Parser, Debug)]
@ -53,7 +53,7 @@ fn main() {
"".to_string()
};
let context = Map::new();
let context = Structure::default();
if let Some(input) = args.input {
context
@ -168,7 +168,7 @@ impl Highlighter for DustReadline {
}
fn run_cli_shell() {
let context = Map::new();
let context = Structure::default();
let mut interpreter = Interpreter::new(context);
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
let mut input = String::new();

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, BuiltInFunction, FunctionNode, Map, Result, Type, Value};
use crate::{AbstractTree, BuiltInFunction, FunctionNode, Result, Structure, Type, Value};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum Function {
@ -28,7 +28,7 @@ impl Function {
name: Option<String>,
arguments: &[Value],
source: &str,
outer_context: &Map,
outer_context: &Structure,
) -> Result<Value> {
match self {
Function::BuiltIn(built_in_function) => {
@ -51,24 +51,24 @@ impl Function {
}
impl AbstractTree for Function {
fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result<Self> {
fn from_syntax_node(_source: &str, _node: Node, _context: &Structure) -> Result<Self> {
let inner_function = FunctionNode::from_syntax_node(_source, _node, _context)?;
Ok(Function::ContextDefined(inner_function))
}
fn check_type(&self, _context: &Map) -> Result<()> {
fn check_type(&self, _context: &Structure) -> Result<()> {
match self {
Function::BuiltIn(_) => Ok(()),
Function::ContextDefined(defined_function) => defined_function.check_type(_context),
}
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
fn run(&self, _source: &str, _context: &Structure) -> Result<Value> {
Ok(Value::Function(self.clone()))
}
fn expected_type(&self, _context: &Map) -> Result<Type> {
fn expected_type(&self, _context: &Structure) -> Result<Type> {
match self {
Function::BuiltIn(built_in) => Ok(built_in.r#type()),
Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()),

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values.
use crate::{
error::{Error, Result},
Function, Identifier, List, Map, Type, TypeDefinition,
Function, List, Structure, Type,
};
use serde::{
@ -21,7 +21,7 @@ use std::{
pub mod function;
pub mod list;
pub mod map;
pub mod structure;
/// Dust value representation.
///
@ -31,7 +31,7 @@ pub mod map;
#[derive(Debug, Clone)]
pub enum Value {
List(List),
Map(Map),
Structure(Structure),
Function(Function),
String(Arc<RwLock<String>>),
Float(f64),
@ -74,17 +74,8 @@ impl Value {
Type::List(Box::new(Type::Any))
}
}
Value::Map(map) => {
let mut identifier_types = Vec::new();
for (key, (value, _)) in map.variables().unwrap().iter() {
identifier_types.push((
Identifier::new(key.clone()),
TypeDefinition::new(value.r#type()),
));
}
Type::Map(identifier_types)
Value::Structure(structure) => {
Type::StructureDefinition(structure.instantiator().clone())
}
Value::Function(function) => function.r#type().clone(),
Value::String(_) => Type::String,
@ -148,11 +139,11 @@ impl Value {
}
pub fn is_map(&self) -> bool {
matches!(self, Value::Map(_))
matches!(self, Value::Structure(_))
}
pub fn is_function(&self) -> bool {
matches!(self, Value::Map(_))
matches!(self, Value::Structure(_))
}
/// Borrows the value stored in `self` as `&str`, or returns `Err` if `self` is not a `Value::String`.
@ -238,9 +229,9 @@ impl Value {
}
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::Map`.
pub fn as_map(&self) -> Result<&Map> {
pub fn as_structure(&self) -> Result<&Structure> {
match self {
Value::Map(map) => Ok(map),
Value::Structure(map) => Ok(map),
value => Err(Error::ExpectedMap {
actual: value.clone(),
}),
@ -441,7 +432,7 @@ impl PartialEq for Value {
left.read().unwrap().as_str() == right.read().unwrap().as_str()
}
(Value::List(left), Value::List(right)) => left == right,
(Value::Map(left), Value::Map(right)) => left == right,
(Value::Structure(left), Value::Structure(right)) => left == right,
(Value::Function(left), Value::Function(right)) => left == right,
(Value::Option(left), Value::Option(right)) => left == right,
_ => false,
@ -480,8 +471,8 @@ impl Ord for Value {
(Value::Boolean(_), _) => Ordering::Greater,
(Value::List(left), Value::List(right)) => left.cmp(right),
(Value::List(_), _) => Ordering::Greater,
(Value::Map(left), Value::Map(right)) => left.cmp(right),
(Value::Map(_), _) => Ordering::Greater,
(Value::Structure(left), Value::Structure(right)) => left.cmp(right),
(Value::Structure(_), _) => Ordering::Greater,
(Value::Function(left), Value::Function(right)) => left.cmp(right),
(Value::Function(_), _) => Ordering::Greater,
(Value::Option(left), Value::Option(right)) => left.cmp(right),
@ -511,7 +502,7 @@ impl Serialize for Value {
list.end()
}
Value::Option(inner) => inner.serialize(serializer),
Value::Map(inner) => inner.serialize(serializer),
Value::Structure(inner) => inner.serialize(serializer),
Value::Function(inner) => inner.serialize(serializer),
}
}
@ -532,7 +523,7 @@ impl Display for Value {
}
}
Value::List(list) => write!(f, "{list}"),
Value::Map(map) => write!(f, "{map}"),
Value::Structure(map) => write!(f, "{map}"),
Value::Function(function) => write!(f, "{function}"),
}
}
@ -852,13 +843,13 @@ impl<'de> Visitor<'de> for ValueVisitor {
where
M: MapAccess<'de>,
{
let map = Map::new();
let map = Structure::default();
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.set(key, value, None).unwrap();
}
Ok(Value::Map(map))
Ok(Value::Structure(map))
}
fn visit_enum<A>(self, data: A) -> std::result::Result<Self::Value, A::Error>

View File

@ -11,25 +11,33 @@ use std::{
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use crate::{value::Value, Result, Type};
use crate::{value::Value, Result, StructureInstantiator, Type};
/// A collection dust variables comprised of key-value pairs.
///
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
/// to one another.
#[derive(Clone, Debug)]
pub struct Map {
pub struct Structure {
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>,
instantiator: StructureInstantiator,
}
impl Map {
/// Creates a new instace.
pub fn new() -> Self {
Map {
variables: Arc::new(RwLock::new(BTreeMap::new())),
impl Structure {
pub fn new(
variables: BTreeMap<String, (Value, Type)>,
instantiator: StructureInstantiator,
) -> Self {
Structure {
variables: Arc::new(RwLock::new(variables)),
instantiator,
}
}
pub fn instantiator(&self) -> &StructureInstantiator {
&self.instantiator
}
pub fn clone_from(other: &Self) -> Result<Self> {
let mut new_map = BTreeMap::new();
@ -37,8 +45,9 @@ impl Map {
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
}
Ok(Map {
Ok(Structure {
variables: Arc::new(RwLock::new(new_map)),
instantiator: other.instantiator.clone(),
})
}
@ -80,15 +89,18 @@ impl Map {
}
}
impl Default for Map {
impl Default for Structure {
fn default() -> Self {
Self::new()
Structure {
variables: Arc::new(RwLock::new(BTreeMap::new())),
instantiator: StructureInstantiator::new(),
}
}
}
impl Eq for Map {}
impl Eq for Structure {}
impl PartialEq for Map {
impl PartialEq for Structure {
fn eq(&self, other: &Self) -> bool {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
@ -97,7 +109,7 @@ impl PartialEq for Map {
}
}
impl Ord for Map {
impl Ord for Structure {
fn cmp(&self, other: &Self) -> Ordering {
let left = self.variables.read().unwrap().clone().into_iter();
let right = other.variables.read().unwrap().clone().into_iter();
@ -106,13 +118,13 @@ impl Ord for Map {
}
}
impl PartialOrd for Map {
impl PartialOrd for Structure {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Display for Map {
impl Display for Structure {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "{{")?;
@ -125,7 +137,7 @@ impl Display for Map {
}
}
impl Serialize for Map {
impl Serialize for Structure {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
@ -142,7 +154,7 @@ impl Serialize for Map {
}
struct MapVisitor {
marker: PhantomData<fn() -> Map>,
marker: PhantomData<fn() -> Structure>,
}
impl MapVisitor {
@ -154,17 +166,17 @@ impl MapVisitor {
}
impl<'de> Visitor<'de> for MapVisitor {
type Value = Map;
type Value = Structure;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("Any valid whale data.")
}
fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error>
fn visit_map<M>(self, mut access: M) -> std::result::Result<Structure, M::Error>
where
M: MapAccess<'de>,
{
let map = Map::new();
let map = Structure::default();
{
while let Some((key, value)) = access.next_entry::<String, Value>()? {
@ -176,7 +188,7 @@ impl<'de> Visitor<'de> for MapVisitor {
}
}
impl<'de> Deserialize<'de> for Map {
impl<'de> Deserialize<'de> for Structure {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,

View File

@ -139,37 +139,45 @@ mod value {
}
#[test]
fn map() {
let map = Map::new();
fn structure() {
let structure = Structure::default();
map.set("x".to_string(), Value::Integer(1), None).unwrap();
map.set("foo".to_string(), Value::string("bar".to_string()), None)
structure
.set("x".to_string(), Value::Integer(1), None)
.unwrap();
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
}
#[test]
fn map_types() {
let map = Map::new();
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
structure
.set("foo".to_string(), Value::string("bar".to_string()), None)
.unwrap();
map.set(
"foo".to_string(),
Value::string("bar".to_string()),
Some(Type::String),
)
.unwrap();
assert_eq!(
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
Ok(Value::Map(map))
interpret("{ x = 1, foo = 'bar' }"),
Ok(Value::Structure(structure))
);
}
#[test]
fn map_type_errors() {
fn structure_types() {
let structure = Structure::default();
structure
.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
.unwrap();
structure
.set(
"foo".to_string(),
Value::string("bar".to_string()),
Some(Type::String),
)
.unwrap();
assert_eq!(
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
Ok(Value::Structure(structure))
);
}
#[test]
fn structure_type_errors() {
assert!(interpret("{ foo <bool> = 'bar' }")
.unwrap_err()
.is_type_check_error(&Error::TypeCheck {
@ -341,7 +349,7 @@ mod index {
}
#[test]
fn map_index() {
fn structure_index() {
let test = interpret("x = {y = {z = 2}} x:y:z").unwrap();
assert_eq!(Value::Integer(2), test);

View File

@ -151,10 +151,7 @@ Complex Function Call
foobar(
"hi"
42
{
x = 1
y = 2
}
new Baz
)
--------------------------------------------------------------------------------
@ -173,17 +170,8 @@ foobar(
(integer)))
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer))))
(identifier)
(statement
(expression
(value
(integer)))))))))))
(structure
(identifier))))))))
================================================================================
Callback Function Call

View File

@ -114,3 +114,64 @@ x:(y()):0
(index_expression
(value
(integer)))))))
================================================================================
Structure Definition Index
================================================================================
struct {
bar = 1
}:bar
--------------------------------------------------------------------------------
(root
(statement
(expression
(index
(index_expression
(value
(structure_definition
(structure_instantiator
(identifier)
(statement
(expression
(value
(integer))))))))
(index_expression
(identifier))))))
================================================================================
Structure Definition Index Function Call
================================================================================
struct {
bar = () <str> { 'bar' }
}:bar()
--------------------------------------------------------------------------------
(root
(statement
(expression
(function_call
(function_expression
(index
(index_expression
(value
(structure_definition
(structure_instantiator
(identifier)
(statement
(expression
(value
(function
(type_definition
(type))
(block
(statement
(expression
(value
(string)))))))))))))
(index_expression
(identifier))))))))

View File

@ -1,107 +0,0 @@
================================================================================
Simple Map
================================================================================
{ answer = 42 }
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer)))))))))
================================================================================
Map with Types
================================================================================
{
answer <num> = 42
stuff <[str]> = [ "some" "stuff" ]
}
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(map
(identifier)
(type_definition
(type))
(statement
(expression
(value
(integer))))
(identifier)
(type_definition
(type
(type)))
(statement
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(string))))))))))))
================================================================================
Nested Maps
================================================================================
x = {
y = {
foo = 'bar'
z = {
message = 'hiya'
}
}
f = 12
}
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(string))))
(identifier)
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(string))))))))))))
(identifier)
(statement
(expression
(value
(integer)))))))))))

View File

@ -0,0 +1,165 @@
================================================================================
Simple Structure Definition
================================================================================
struct { answer = 42 }
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(structure_definition
(structure_instantiator
(identifier)
(statement
(expression
(value
(integer))))))))))
================================================================================
Structure Definition with Types
================================================================================
struct {
answer <num> = 42
stuff <[str]> = [ "some" "stuff" ]
}
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(structure_definition
(structure_instantiator
(identifier)
(type_definition
(type))
(statement
(expression
(value
(integer))))
(identifier)
(type_definition
(type
(type)))
(statement
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(string)))))))))))))
================================================================================
Nested Structure Definition
================================================================================
struct {
bar <Bar>
baz <Baz>
}
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(structure_definition
(structure_instantiator
(identifier)
(type_definition
(type
(identifier)))
(identifier)
(type_definition
(type
(identifier)))))))))
================================================================================
Simple Structure
================================================================================
new Foo
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(structure
(identifier))))))
================================================================================
Complex Structure
================================================================================
User = struct {
id <int> = random:integer()
email <str>
name <option(str)> = none
}
bob = new User {
email = "bob@example.come"
}
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(structure_definition
(structure_instantiator
(identifier)
(type_definition
(type))
(statement
(expression
(function_call
(function_expression
(index
(index_expression
(value
(built_in_value)))
(index_expression
(identifier)))))))
(identifier)
(type_definition
(type))
(identifier)
(type_definition
(type
(type)))
(statement
(expression
(value
(option)))))))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(structure
(identifier)
(structure_instantiator
(identifier)
(statement
(expression
(value
(string))))))))))))

View File

@ -81,7 +81,8 @@ module.exports = grammar({
$.string,
$.boolean,
$.list,
$.map,
$.structure,
$.structure_definition,
$.option,
$.built_in_value,
),
@ -167,15 +168,38 @@ module.exports = grammar({
']',
),
map: $ =>
structure_definition: $ =>
seq(
'struct',
$.structure_instantiator,
),
structure: $ =>
prec.right(
seq(
'new',
$.identifier,
optional(
$.structure_instantiator,
),
),
),
structure_instantiator: $ =>
seq(
'{',
repeat1(
seq(
$.identifier,
optional($.type_definition),
'=',
$.statement,
choice(
$.type_definition,
seq('=', $.statement),
seq(
$.type_definition,
'=',
$.statement,
),
),
optional(','),
),
),
@ -347,10 +371,10 @@ module.exports = grammar({
'collection',
'float',
'int',
'map',
'none',
'num',
'str',
$.identifier,
seq('[', $.type, ']'),
seq(
'{',

View File

@ -235,7 +235,11 @@
},
{
"type": "SYMBOL",
"name": "map"
"name": "structure"
},
{
"type": "SYMBOL",
"name": "structure_definition"
},
{
"type": "SYMBOL",
@ -501,7 +505,49 @@
}
]
},
"map": {
"structure_definition": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "struct"
},
{
"type": "SYMBOL",
"name": "structure_instantiator"
}
]
},
"structure": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "new"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "structure_instantiator"
},
{
"type": "BLANK"
}
]
}
]
}
},
"structure_instantiator": {
"type": "SEQ",
"members": [
{
@ -525,18 +571,37 @@
"name": "type_definition"
},
{
"type": "BLANK"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "type_definition"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
}
]
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
},
{
"type": "CHOICE",
"members": [
@ -1099,10 +1164,6 @@
"type": "STRING",
"value": "int"
},
{
"type": "STRING",
"value": "map"
},
{
"type": "STRING",
"value": "none"
@ -1115,6 +1176,10 @@
"type": "STRING",
"value": "str"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SEQ",
"members": [

View File

@ -375,29 +375,6 @@
"named": true,
"fields": {}
},
{
"type": "map",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
},
{
"type": "match",
"named": true,
@ -533,6 +510,63 @@
]
}
},
{
"type": "structure",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "structure_instantiator",
"named": true
}
]
}
},
{
"type": "structure_definition",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "structure_instantiator",
"named": true
}
]
}
},
{
"type": "structure_instantiator",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
},
{
"type": "type",
"named": true,
@ -603,10 +637,6 @@
"type": "list",
"named": true
},
{
"type": "map",
"named": true
},
{
"type": "option",
"named": true
@ -614,6 +644,14 @@
{
"type": "string",
"named": true
},
{
"type": "structure",
"named": true
},
{
"type": "structure_definition",
"named": true
}
]
}
@ -802,11 +840,11 @@
},
{
"type": "float",
"named": true
"named": false
},
{
"type": "float",
"named": false
"named": true
},
{
"type": "for",
@ -845,11 +883,11 @@
"named": false
},
{
"type": "map",
"type": "match",
"named": false
},
{
"type": "match",
"type": "new",
"named": false
},
{
@ -886,10 +924,14 @@
},
{
"type": "string",
"named": true
"named": false
},
{
"type": "string",
"named": true
},
{
"type": "struct",
"named": false
},
{

File diff suppressed because it is too large Load Diff