Implement structure value, type and syntax
This commit is contained in:
parent
614bb6f23e
commit
2a18f9fb7c
@ -1,10 +1,4 @@
|
|||||||
type Cards {
|
Cards = struct {
|
||||||
rooms <[str]>
|
|
||||||
suspects <[str]>
|
|
||||||
weapons <[str]>
|
|
||||||
}
|
|
||||||
|
|
||||||
cards = Cards {
|
|
||||||
rooms = ['Library' 'Kitchen' 'Conservatory']
|
rooms = ['Library' 'Kitchen' 'Conservatory']
|
||||||
suspects = ['White' 'Green' 'Scarlett']
|
suspects = ['White' 'Green' 'Scarlett']
|
||||||
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
weapons = ['Rope' 'Lead_Pipe' 'Knife']
|
||||||
@ -51,6 +45,8 @@ take_turn = (cards <Cards>, opponent_card <str>, current_room <str>) <none> {
|
|||||||
make_guess(cards current_room)
|
make_guess(cards current_room)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cards = new Cards
|
||||||
|
|
||||||
take_turn(cards 'Rope' 'Kitchen')
|
take_turn(cards 'Rope' 'Kitchen')
|
||||||
take_turn(cards 'Library' 'Kitchen')
|
take_turn(cards 'Library' 'Kitchen')
|
||||||
take_turn(cards 'Conservatory' 'Kitchen')
|
take_turn(cards 'Conservatory' 'Kitchen')
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Assignment {
|
pub struct Assignment {
|
||||||
@ -19,7 +21,7 @@ pub enum AssignmentOperator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Assignment {
|
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)?;
|
Error::expect_syntax_node(source, "assignment", node)?;
|
||||||
|
|
||||||
let child_count = node.child_count();
|
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)?;
|
let statement_type = self.statement.expected_type(context)?;
|
||||||
|
|
||||||
if let Some(type_definition) = &self.type_definition {
|
if let Some(type_definition) = &self.type_definition {
|
||||||
@ -110,7 +112,7 @@ impl AbstractTree for Assignment {
|
|||||||
Ok(())
|
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 key = self.identifier.inner();
|
||||||
let value = self.statement.run(source, context)?;
|
let value = self.statement.run(source, context)?;
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ impl AbstractTree for Assignment {
|
|||||||
Ok(Value::none())
|
Ok(Value::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(Type::None)
|
Ok(Type::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use rayon::prelude::*;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a block.
|
||||||
///
|
///
|
||||||
@ -21,7 +21,7 @@ pub struct Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "block", node)?;
|
||||||
|
|
||||||
let first_child = node.child(0).unwrap();
|
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 {
|
for statement in &self.statements {
|
||||||
if let Statement::Return(inner_statement) = statement {
|
if let Statement::Return(inner_statement) = statement {
|
||||||
return inner_statement.check_type(_context);
|
return inner_statement.check_type(_context);
|
||||||
@ -62,7 +62,7 @@ impl AbstractTree for Block {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
if self.is_async {
|
if self.is_async {
|
||||||
let statements = &self.statements;
|
let statements = &self.statements;
|
||||||
let final_result = RwLock::new(Ok(Value::none()));
|
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 Some(statement) = self.statements.iter().find(|statement| {
|
||||||
if let Statement::Return(_) = statement {
|
if let Statement::Return(_) = statement {
|
||||||
true
|
true
|
||||||
|
@ -5,7 +5,7 @@ use tree_sitter::Node;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, Identifier,
|
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();
|
static ARGS: OnceLock<Value> = OnceLock::new();
|
||||||
@ -31,29 +31,12 @@ impl BuiltInValue {
|
|||||||
match self {
|
match self {
|
||||||
BuiltInValue::Args => Type::list(Type::String),
|
BuiltInValue::Args => Type::list(Type::String),
|
||||||
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
|
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
|
||||||
BuiltInValue::Fs => Type::Map(Vec::new()),
|
BuiltInValue::Fs => Type::Structure(Identifier::from("fs")),
|
||||||
BuiltInValue::Json => Type::Map(Vec::new()),
|
BuiltInValue::Json => Type::Structure(Identifier::from("json")),
|
||||||
BuiltInValue::Length => BuiltInFunction::Length.r#type(),
|
BuiltInValue::Length => BuiltInFunction::Length.r#type(),
|
||||||
BuiltInValue::Output => BuiltInFunction::Output.r#type(),
|
BuiltInValue::Output => BuiltInFunction::Output.r#type(),
|
||||||
BuiltInValue::Random => Type::Map(vec![
|
BuiltInValue::Random => Type::Structure(Identifier::from("random")),
|
||||||
(
|
BuiltInValue::String => Type::Structure(Identifier::from("string")),
|
||||||
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()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +51,7 @@ impl BuiltInValue {
|
|||||||
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
|
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
|
||||||
}
|
}
|
||||||
BuiltInValue::Fs => FS.get_or_init(|| {
|
BuiltInValue::Fs => FS.get_or_init(|| {
|
||||||
let fs_context = Map::new();
|
let fs_context = Structure::default();
|
||||||
|
|
||||||
fs_context
|
fs_context
|
||||||
.set(
|
.set(
|
||||||
@ -78,10 +61,10 @@ impl BuiltInValue {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Value::Map(fs_context)
|
Value::Structure(fs_context)
|
||||||
}),
|
}),
|
||||||
BuiltInValue::Json => JSON.get_or_init(|| {
|
BuiltInValue::Json => JSON.get_or_init(|| {
|
||||||
let json_context = Map::new();
|
let json_context = Structure::default();
|
||||||
|
|
||||||
json_context
|
json_context
|
||||||
.set(
|
.set(
|
||||||
@ -91,12 +74,12 @@ impl BuiltInValue {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Value::Map(json_context)
|
Value::Structure(json_context)
|
||||||
}),
|
}),
|
||||||
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
|
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
|
||||||
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
|
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
|
||||||
BuiltInValue::Random => RANDOM.get_or_init(|| {
|
BuiltInValue::Random => RANDOM.get_or_init(|| {
|
||||||
let random_context = Map::new();
|
let random_context = Structure::default();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut variables = random_context.variables_mut().unwrap();
|
let mut variables = random_context.variables_mut().unwrap();
|
||||||
@ -115,10 +98,10 @@ impl BuiltInValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Map(random_context)
|
Value::Structure(random_context)
|
||||||
}),
|
}),
|
||||||
BuiltInValue::String => STRING.get_or_init(|| {
|
BuiltInValue::String => STRING.get_or_init(|| {
|
||||||
let string_context = Map::new();
|
let string_context = Structure::default();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut variables = string_context.variables_mut().unwrap();
|
let mut variables = string_context.variables_mut().unwrap();
|
||||||
@ -134,14 +117,14 @@ impl BuiltInValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Map(string_context)
|
Value::Structure(string_context)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for BuiltInValue {
|
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() {
|
let built_in_value = match node.kind() {
|
||||||
"args" => BuiltInValue::Args,
|
"args" => BuiltInValue::Args,
|
||||||
"assert_equal" => BuiltInValue::AssertEqual,
|
"assert_equal" => BuiltInValue::AssertEqual,
|
||||||
@ -157,11 +140,11 @@ impl AbstractTree for BuiltInValue {
|
|||||||
Ok(built_in_value)
|
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())
|
Ok(self.get().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(self.r#type())
|
Ok(self.r#type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
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};
|
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
||||||
@ -24,7 +25,7 @@ pub enum Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "expression", node)?;
|
||||||
|
|
||||||
let child = if node.child(0).unwrap().is_named() {
|
let child = if node.child(0).unwrap().is_named() {
|
||||||
@ -65,7 +66,7 @@ impl AbstractTree for Expression {
|
|||||||
Ok(expression)
|
Ok(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, _context: &Map) -> Result<()> {
|
fn check_type(&self, _context: &Structure) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Value(value_node) => value_node.check_type(_context),
|
Expression::Value(value_node) => value_node.check_type(_context),
|
||||||
Expression::Identifier(identifier) => identifier.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 {
|
match self {
|
||||||
Expression::Value(value_node) => value_node.run(source, context),
|
Expression::Value(value_node) => value_node.run(source, context),
|
||||||
Expression::Identifier(identifier) => identifier.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 {
|
match self {
|
||||||
Expression::Value(value_node) => value_node.expected_type(context),
|
Expression::Value(value_node) => value_node.expected_type(context),
|
||||||
Expression::Identifier(identifier) => identifier.expected_type(context),
|
Expression::Identifier(identifier) => identifier.expected_type(context),
|
||||||
|
@ -2,7 +2,7 @@ use rayon::prelude::*;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a for loop statement.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -14,7 +14,7 @@ pub struct For {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for For {
|
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)?;
|
Error::expect_syntax_node(source, "for", node)?;
|
||||||
|
|
||||||
let for_node = node.child(0).unwrap();
|
let for_node = node.child(0).unwrap();
|
||||||
@ -48,21 +48,21 @@ impl AbstractTree for For {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let expression_run = self.collection.run(source, context)?;
|
let expression_run = self.collection.run(source, context)?;
|
||||||
let values = expression_run.as_list()?.items();
|
let values = expression_run.as_list()?.items();
|
||||||
let key = self.item_id.inner();
|
let key = self.item_id.inner();
|
||||||
|
|
||||||
if self.is_async {
|
if self.is_async {
|
||||||
values.par_iter().try_for_each(|value| {
|
values.par_iter().try_for_each(|value| {
|
||||||
let iter_context = Map::clone_from(context)?;
|
let iter_context = Structure::clone_from(context)?;
|
||||||
|
|
||||||
iter_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, &iter_context).map(|_value| ())
|
||||||
})?;
|
})?;
|
||||||
} else {
|
} else {
|
||||||
let loop_context = Map::clone_from(context)?;
|
let loop_context = Structure::clone_from(context)?;
|
||||||
|
|
||||||
for value in values.iter() {
|
for value in values.iter() {
|
||||||
loop_context.set(key.clone(), value.clone(), None)?;
|
loop_context.set(key.clone(), value.clone(), None)?;
|
||||||
@ -74,7 +74,7 @@ impl AbstractTree for For {
|
|||||||
Ok(Value::none())
|
Ok(Value::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(Type::None)
|
Ok(Type::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
@ -19,7 +19,7 @@ impl FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "function_call", node)?;
|
||||||
|
|
||||||
let function_node = node.child(0).unwrap();
|
let function_node = node.child(0).unwrap();
|
||||||
@ -44,7 +44,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, context: &Map) -> Result<()> {
|
fn check_type(&self, context: &Structure) -> Result<()> {
|
||||||
let function_expression_type = self.function_expression.expected_type(context)?;
|
let function_expression_type = self.function_expression.expected_type(context)?;
|
||||||
let parameter_types = if let Type::Function {
|
let parameter_types = if let Type::Function {
|
||||||
parameter_types, ..
|
parameter_types, ..
|
||||||
@ -65,7 +65,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
|
|
||||||
if self.arguments.len() != parameter_types.len() {
|
if self.arguments.len() != parameter_types.len() {
|
||||||
return Err(Error::ExpectedFunctionArgumentAmount {
|
return Err(Error::ExpectedFunctionArgumentAmount {
|
||||||
source: "TODO".to_string(),
|
source: "TODO".to_string(), // TODO
|
||||||
expected: parameter_types.len(),
|
expected: parameter_types.len(),
|
||||||
actual: self.arguments.len(),
|
actual: self.arguments.len(),
|
||||||
});
|
});
|
||||||
@ -74,7 +74,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
Ok(())
|
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 {
|
let (name, value) = match &self.function_expression {
|
||||||
FunctionExpression::Identifier(identifier) => {
|
FunctionExpression::Identifier(identifier) => {
|
||||||
let key = identifier.inner();
|
let key = identifier.inner();
|
||||||
@ -118,7 +118,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
.call(name, &arguments, source, context)
|
.call(name, &arguments, source, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
match &self.function_expression {
|
match &self.function_expression {
|
||||||
FunctionExpression::Identifier(identifier) => {
|
FunctionExpression::Identifier(identifier) => {
|
||||||
let identifier_type = identifier.expected_type(context)?;
|
let identifier_type = identifier.expected_type(context)?;
|
||||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, Value, ValueNode,
|
AbstractTree, Error, FunctionCall, Identifier, Index, Result, Structure, Type, Value,
|
||||||
Yield,
|
ValueNode, Yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -16,7 +16,7 @@ pub enum FunctionExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "function_expression", node)?;
|
||||||
|
|
||||||
let first_child = node.child(0).unwrap();
|
let first_child = node.child(0).unwrap();
|
||||||
@ -54,7 +54,7 @@ impl AbstractTree for FunctionExpression {
|
|||||||
Ok(function_expression)
|
Ok(function_expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
FunctionExpression::Identifier(identifier) => identifier.run(source, context),
|
FunctionExpression::Identifier(identifier) => identifier.run(source, context),
|
||||||
FunctionExpression::FunctionCall(function_call) => function_call.run(source, context),
|
FunctionExpression::FunctionCall(function_call) => function_call.run(source, context),
|
||||||
@ -64,7 +64,7 @@ impl AbstractTree for FunctionExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
match self {
|
match self {
|
||||||
FunctionExpression::Identifier(identifier) => identifier.expected_type(context),
|
FunctionExpression::Identifier(identifier) => identifier.expected_type(context),
|
||||||
FunctionExpression::FunctionCall(function_call) => function_call.expected_type(context),
|
FunctionExpression::FunctionCall(function_call) => function_call.expected_type(context),
|
||||||
|
@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
@ -48,10 +49,10 @@ impl FunctionNode {
|
|||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
arguments: &[Value],
|
arguments: &[Value],
|
||||||
source: &str,
|
source: &str,
|
||||||
outer_context: &Map,
|
outer_context: &Structure,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter());
|
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 {
|
for (identifier, value) in parameter_argument_pairs {
|
||||||
let key = identifier.inner().clone();
|
let key = identifier.inner().clone();
|
||||||
@ -74,7 +75,7 @@ impl FunctionNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "function", node)?;
|
||||||
|
|
||||||
let child_count = node.child_count();
|
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()) {
|
for (parameter_name, parameter_type) in parameters.iter().zip(parameter_types.iter()) {
|
||||||
function_context.set(
|
function_context.set(
|
||||||
@ -118,18 +119,18 @@ impl AbstractTree for FunctionNode {
|
|||||||
Ok(FunctionNode::new(parameters, body, r#type))
|
Ok(FunctionNode::new(parameters, body, r#type))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, context: &Map) -> Result<()> {
|
fn check_type(&self, context: &Structure) -> Result<()> {
|
||||||
self.return_type()
|
self.return_type()
|
||||||
.check(&self.body.expected_type(context)?)?;
|
.check(&self.body.expected_type(context)?)?;
|
||||||
|
|
||||||
Ok(())
|
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())))
|
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())
|
Ok(self.r#type().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// A string by which a variable is known to a context.
|
||||||
///
|
///
|
||||||
@ -25,7 +25,7 @@ impl Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "identifier", node)?;
|
||||||
|
|
||||||
let text = &source[node.byte_range()];
|
let text = &source[node.byte_range()];
|
||||||
@ -35,7 +35,7 @@ impl AbstractTree for Identifier {
|
|||||||
Ok(Identifier(text.to_string()))
|
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 let Some((value, _)) = context.variables()?.get(&self.0) {
|
||||||
if !value.is_none() {
|
if !value.is_none() {
|
||||||
return Ok(value.clone());
|
return Ok(value.clone());
|
||||||
@ -45,7 +45,7 @@ impl AbstractTree for Identifier {
|
|||||||
Err(Error::VariableIdentifierNotFound(self.0.clone()))
|
Err(Error::VariableIdentifierNotFound(self.0.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
if let Some((_value, r#type)) = context.variables()?.get(&self.0) {
|
if let Some((_value, r#type)) = context.variables()?.get(&self.0) {
|
||||||
Ok(r#type.clone())
|
Ok(r#type.clone())
|
||||||
} else {
|
} else {
|
||||||
@ -53,3 +53,15 @@ impl AbstractTree for Identifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct IfElse {
|
pub struct IfElse {
|
||||||
@ -13,7 +13,7 @@ pub struct IfElse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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_node = node.child(0).unwrap().child(1).unwrap();
|
||||||
let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?;
|
let if_expression = Expression::from_syntax_node(source, if_expression_node, context)?;
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ impl AbstractTree for IfElse {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
|
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
|
||||||
|
|
||||||
if if_boolean {
|
if if_boolean {
|
||||||
@ -81,7 +81,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)
|
self.if_block.expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, IndexExpression, List, Map, Result, Type, Value};
|
use crate::{AbstractTree, Error, IndexExpression, List, Result, Structure, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of an index expression.
|
/// Abstract representation of an index expression.
|
||||||
///
|
///
|
||||||
@ -14,7 +14,7 @@ pub struct Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "index", node)?;
|
||||||
|
|
||||||
let collection_node = node.child(0).unwrap();
|
let collection_node = node.child(0).unwrap();
|
||||||
@ -41,7 +41,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)?;
|
let collection = self.collection.run(source, context)?;
|
||||||
|
|
||||||
match collection {
|
match collection {
|
||||||
@ -59,11 +59,12 @@ impl AbstractTree for Index {
|
|||||||
|
|
||||||
Ok(item)
|
Ok(item)
|
||||||
}
|
}
|
||||||
Value::Map(map) => {
|
Value::Structure(structure) => {
|
||||||
let value = if let IndexExpression::Identifier(identifier) = &self.index {
|
let value = if let IndexExpression::Identifier(identifier) = &self.index {
|
||||||
let key = identifier.inner();
|
let key = identifier.inner();
|
||||||
|
|
||||||
map.variables()?
|
structure
|
||||||
|
.variables()?
|
||||||
.get(key)
|
.get(key)
|
||||||
.map(|(value, _)| value.clone())
|
.map(|(value, _)| value.clone())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
@ -71,7 +72,8 @@ impl AbstractTree for Index {
|
|||||||
let value = self.index.run(source, context)?;
|
let value = self.index.run(source, context)?;
|
||||||
let key = value.as_string()?;
|
let key = value.as_string()?;
|
||||||
|
|
||||||
map.variables()?
|
structure
|
||||||
|
.variables()?
|
||||||
.get(key.as_str())
|
.get(key.as_str())
|
||||||
.map(|(value, _)| value.clone())
|
.map(|(value, _)| value.clone())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
@ -89,19 +91,50 @@ impl AbstractTree for Index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
match self.collection.expected_type(context)? {
|
match self.collection.expected_type(context)? {
|
||||||
Type::List(item_type) => Ok(*item_type.clone()),
|
Type::List(item_type) => Ok(*item_type.clone()),
|
||||||
Type::Map(identifier_types) => {
|
Type::Structure(definition_identifier) => {
|
||||||
if let IndexExpression::Identifier(index_identifier) = &self.index {
|
let (r#type, key) = if let IndexExpression::Identifier(identifier) = &self.index {
|
||||||
for (identifier, r#type) in identifier_types {
|
let get_type = context
|
||||||
if &identifier == index_identifier {
|
.variables()?
|
||||||
return Ok(r#type.take_inner());
|
.get(definition_identifier.inner())
|
||||||
}
|
.map(|(_, r#type)| r#type.clone());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Type::None)
|
if let Some(r#type) = get_type {
|
||||||
|
(r#type, identifier.inner())
|
||||||
|
} else {
|
||||||
|
return Err(Error::VariableIdentifierNotFound(
|
||||||
|
definition_identifier.inner().clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::ExpectedIndexIdentifier {
|
||||||
|
actual: self.index.clone(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Type::StructureDefinition(instantiator) = &r#type {
|
||||||
|
let get_type = instantiator.get(key);
|
||||||
|
|
||||||
|
if let Some((statement_option, type_option)) = get_type {
|
||||||
|
let r#type = if let Some(r#type) = type_option {
|
||||||
|
r#type.inner().clone()
|
||||||
|
} else {
|
||||||
|
if let Some(statement) = statement_option {
|
||||||
|
statement.expected_type(context)?
|
||||||
|
} else {
|
||||||
|
Type::None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(r#type)
|
||||||
|
} else {
|
||||||
|
Err(Error::VariableIdentifierNotFound(key.clone()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::ExpectedStructureDefinition { actual: r#type })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Type::None => Ok(Type::None),
|
Type::None => Ok(Type::None),
|
||||||
r#type => Ok(r#type),
|
r#type => Ok(r#type),
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct IndexAssignment {
|
pub struct IndexAssignment {
|
||||||
@ -18,7 +20,7 @@ pub enum AssignmentOperator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for IndexAssignment {
|
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)?;
|
Error::expect_syntax_node(source, "index_assignment", node)?;
|
||||||
|
|
||||||
let index_node = node.child(0).unwrap();
|
let index_node = node.child(0).unwrap();
|
||||||
@ -49,9 +51,9 @@ impl AbstractTree for IndexAssignment {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let index_collection = self.index.collection.run(source, context)?;
|
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 {
|
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
|
||||||
identifier.inner()
|
identifier.inner()
|
||||||
} else {
|
} else {
|
||||||
@ -91,7 +93,7 @@ impl AbstractTree for IndexAssignment {
|
|||||||
Ok(Value::none())
|
Ok(Value::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(Type::None)
|
Ok(Type::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type,
|
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Result, Structure,
|
||||||
Value,
|
Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -14,7 +14,11 @@ pub enum IndexExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "index_expression", node)?;
|
||||||
|
|
||||||
let first_child = node.child(0).unwrap();
|
let first_child = node.child(0).unwrap();
|
||||||
@ -48,7 +52,7 @@ impl AbstractTree for IndexExpression {
|
|||||||
Ok(abstract_node)
|
Ok(abstract_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
IndexExpression::Value(value_node) => value_node.run(source, context),
|
IndexExpression::Value(value_node) => value_node.run(source, context),
|
||||||
IndexExpression::Identifier(identifier) => identifier.run(source, context),
|
IndexExpression::Identifier(identifier) => identifier.run(source, context),
|
||||||
@ -57,7 +61,7 @@ impl AbstractTree for IndexExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
match self {
|
match self {
|
||||||
IndexExpression::Value(value_node) => value_node.expected_type(context),
|
IndexExpression::Value(value_node) => value_node.expected_type(context),
|
||||||
IndexExpression::Identifier(identifier) => identifier.expected_type(context),
|
IndexExpression::Identifier(identifier) => identifier.expected_type(context),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a logic expression.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -12,7 +12,7 @@ pub struct Logic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "logic", node)?;
|
||||||
|
|
||||||
let first_node = node.child(0).unwrap();
|
let first_node = node.child(0).unwrap();
|
||||||
@ -59,7 +59,7 @@ impl AbstractTree for Logic {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let left = self.left.run(source, context)?;
|
let left = self.left.run(source, context)?;
|
||||||
let right = self.right.run(source, context)?;
|
let right = self.right.run(source, context)?;
|
||||||
let result = match self.operator {
|
let result = match self.operator {
|
||||||
@ -88,7 +88,7 @@ impl AbstractTree for Logic {
|
|||||||
Ok(Value::Boolean(result))
|
Ok(Value::Boolean(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(Type::Boolean)
|
Ok(Type::Boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a match statement.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -17,7 +17,7 @@ pub struct Match {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "match", node)?;
|
||||||
|
|
||||||
let matcher_node = node.child(1).unwrap();
|
let matcher_node = node.child(1).unwrap();
|
||||||
@ -58,7 +58,7 @@ impl AbstractTree for Match {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let matcher_value = self.matcher.run(source, context)?;
|
let matcher_value = self.matcher.run(source, context)?;
|
||||||
|
|
||||||
for (expression, statement) in &self.options {
|
for (expression, statement) in &self.options {
|
||||||
@ -76,7 +76,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();
|
let (_, first_statement) = self.options.first().unwrap();
|
||||||
|
|
||||||
first_statement.expected_type(context)
|
first_statement.expected_type(context)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a math operation.
|
||||||
///
|
///
|
||||||
@ -15,7 +15,7 @@ pub struct Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "math", node)?;
|
||||||
|
|
||||||
let left_node = node.child(0).unwrap();
|
let left_node = node.child(0).unwrap();
|
||||||
@ -48,7 +48,7 @@ impl AbstractTree for Math {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let left = self.left.run(source, context)?;
|
let left = self.left.run(source, context)?;
|
||||||
let right = self.right.run(source, context)?;
|
let right = self.right.run(source, context)?;
|
||||||
let value = match self.operator {
|
let value = match self.operator {
|
||||||
@ -62,7 +62,7 @@ impl AbstractTree for Math {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
self.left.expected_type(context)
|
self.left.expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ pub mod logic;
|
|||||||
pub mod r#match;
|
pub mod r#match;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
|
pub mod structure_instantiator;
|
||||||
pub mod type_definition;
|
pub mod type_definition;
|
||||||
pub mod value_node;
|
pub mod value_node;
|
||||||
pub mod r#while;
|
pub mod r#while;
|
||||||
@ -32,19 +33,20 @@ pub use {
|
|||||||
assignment::*, block::*, built_in_value::*, expression::*, function_call::*,
|
assignment::*, block::*, built_in_value::*, expression::*, function_call::*,
|
||||||
function_expression::*, function_node::*, identifier::*, if_else::*, index::*,
|
function_expression::*, function_node::*, identifier::*, if_else::*, index::*,
|
||||||
index_assignment::IndexAssignment, index_expression::*, logic::*, math::*, r#for::*,
|
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 tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{Error, Map, Result, Value};
|
use crate::{Error, Result, Structure, Value};
|
||||||
|
|
||||||
pub struct Root {
|
pub struct Root {
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Root {
|
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)?;
|
Error::expect_syntax_node(source, "root", node)?;
|
||||||
|
|
||||||
let statement_count = node.child_count();
|
let statement_count = node.child_count();
|
||||||
@ -60,7 +62,7 @@ impl AbstractTree for Root {
|
|||||||
Ok(Root { statements })
|
Ok(Root { statements })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, _context: &Map) -> Result<()> {
|
fn check_type(&self, _context: &Structure) -> Result<()> {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
if let Statement::Return(inner_statement) = statement {
|
if let Statement::Return(inner_statement) = statement {
|
||||||
return inner_statement.check_type(_context);
|
return inner_statement.check_type(_context);
|
||||||
@ -72,7 +74,7 @@ impl AbstractTree for Root {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
let mut value = Value::none();
|
let mut value = Value::none();
|
||||||
|
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
@ -86,7 +88,7 @@ impl AbstractTree for Root {
|
|||||||
Ok(value)
|
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)
|
self.statements.last().unwrap().expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,15 +105,15 @@ pub trait AbstractTree: Sized {
|
|||||||
///
|
///
|
||||||
/// If necessary, the source code can be accessed directly by getting the
|
/// If necessary, the source code can be accessed directly by getting the
|
||||||
/// node's byte range.
|
/// 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.
|
/// Verify the type integrity of the node.
|
||||||
fn check_type(&self, _context: &Map) -> Result<()> {
|
fn check_type(&self, _context: &Structure) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute dust code by traversing the tree.
|
/// 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>;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match,
|
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Match,
|
||||||
Result, Type, Value, While,
|
Result, Structure, Type, Value, While,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract representation of a statement.
|
/// Abstract representation of a statement.
|
||||||
@ -21,7 +21,7 @@ pub enum Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "statement", node)?;
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
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 {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.check_type(_context),
|
Statement::Assignment(assignment) => assignment.check_type(_context),
|
||||||
Statement::Expression(expression) => expression.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 {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.run(source, context),
|
Statement::Assignment(assignment) => assignment.run(source, context),
|
||||||
Statement::Expression(expression) => expression.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 {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.expected_type(context),
|
Statement::Assignment(assignment) => assignment.expected_type(context),
|
||||||
Statement::Expression(expression) => expression.expected_type(context),
|
Statement::Expression(expression) => expression.expected_type(context),
|
||||||
|
111
src/abstract_tree/structure_instantiator.rs
Normal file
111
src/abstract_tree/structure_instantiator.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
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 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!()
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct TypeDefinition {
|
pub struct TypeDefinition {
|
||||||
@ -25,7 +25,7 @@ impl TypeDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "type_definition", node)?;
|
||||||
|
|
||||||
let type_node = node.child(1).unwrap();
|
let type_node = node.child(1).unwrap();
|
||||||
@ -34,11 +34,11 @@ impl AbstractTree for TypeDefinition {
|
|||||||
Ok(TypeDefinition { r#type })
|
Ok(TypeDefinition { r#type })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
self.r#type.run(source, context)
|
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)
|
self.r#type.expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,10 +61,11 @@ pub enum Type {
|
|||||||
},
|
},
|
||||||
Integer,
|
Integer,
|
||||||
List(Box<Type>),
|
List(Box<Type>),
|
||||||
Map(Vec<(Identifier, TypeDefinition)>),
|
|
||||||
None,
|
None,
|
||||||
Number,
|
Number,
|
||||||
String,
|
String,
|
||||||
|
Structure(Identifier),
|
||||||
|
StructureDefinition(StructureInstantiator),
|
||||||
Option(Box<Type>),
|
Option(Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,8 +93,8 @@ impl Type {
|
|||||||
| (Type::Collection, Type::Collection)
|
| (Type::Collection, Type::Collection)
|
||||||
| (Type::Collection, Type::List(_))
|
| (Type::Collection, Type::List(_))
|
||||||
| (Type::List(_), Type::Collection)
|
| (Type::List(_), Type::Collection)
|
||||||
| (Type::Collection, Type::Map(_))
|
| (Type::Collection, Type::Structure(_))
|
||||||
| (Type::Map(_), Type::Collection)
|
| (Type::Structure(_), Type::Collection)
|
||||||
| (Type::Collection, Type::String)
|
| (Type::Collection, Type::String)
|
||||||
| (Type::String, Type::Collection)
|
| (Type::String, Type::Collection)
|
||||||
| (Type::Float, Type::Float)
|
| (Type::Float, Type::Float)
|
||||||
@ -105,7 +106,7 @@ impl Type {
|
|||||||
| (Type::Float, Type::Number)
|
| (Type::Float, Type::Number)
|
||||||
| (Type::None, Type::None)
|
| (Type::None, Type::None)
|
||||||
| (Type::String, Type::String) => Ok(()),
|
| (Type::String, Type::String) => Ok(()),
|
||||||
(Type::Map(left), Type::Map(right)) => {
|
(Type::Structure(left), Type::Structure(right)) => {
|
||||||
if left == right {
|
if left == right {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -181,7 +182,7 @@ impl Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(_source, "type", node)?;
|
||||||
|
|
||||||
let type_node = node.child(0).unwrap();
|
let type_node = node.child(0).unwrap();
|
||||||
@ -228,32 +229,8 @@ impl AbstractTree for Type {
|
|||||||
"num" => Type::Number,
|
"num" => Type::Number,
|
||||||
"none" => Type::None,
|
"none" => Type::None,
|
||||||
"str" => Type::String,
|
"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" => {
|
||||||
identifier =
|
Type::Structure(Identifier::from_syntax_node(_source, type_node, _context)?)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
"option" => {
|
"option" => {
|
||||||
let inner_type_node = node.child(2).unwrap();
|
let inner_type_node = node.child(2).unwrap();
|
||||||
@ -274,11 +251,11 @@ impl AbstractTree for Type {
|
|||||||
Ok(r#type)
|
Ok(r#type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
fn run(&self, _source: &str, _context: &Structure) -> Result<Value> {
|
||||||
Ok(Value::none())
|
Ok(Value::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
Ok(Type::None)
|
Ok(Type::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,15 +286,8 @@ impl Display for Type {
|
|||||||
}
|
}
|
||||||
Type::Integer => write!(f, "int"),
|
Type::Integer => write!(f, "int"),
|
||||||
Type::List(item_type) => write!(f, "[{item_type}]"),
|
Type::List(item_type) => write!(f, "[{item_type}]"),
|
||||||
Type::Map(identifier_types) => {
|
Type::Structure(identifier) => write!(f, "{}", identifier.inner()),
|
||||||
write!(f, "{{")?;
|
Type::StructureDefinition(_) => todo!(),
|
||||||
|
|
||||||
for (identifier, r#type) in identifier_types {
|
|
||||||
write!(f, "{} {}", identifier.inner(), r#type)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "}}")
|
|
||||||
}
|
|
||||||
Type::Number => write!(f, "num"),
|
Type::Number => write!(f, "num"),
|
||||||
Type::None => write!(f, "none"),
|
Type::None => write!(f, "none"),
|
||||||
Type::String => write!(f, "str"),
|
Type::String => write!(f, "str"),
|
||||||
|
@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result,
|
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Result, Structure,
|
||||||
Statement, Type, TypeDefinition, Value,
|
StructureInstantiator, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -17,12 +17,16 @@ pub enum ValueNode {
|
|||||||
String(String),
|
String(String),
|
||||||
List(Vec<Expression>),
|
List(Vec<Expression>),
|
||||||
Option(Option<Box<Expression>>),
|
Option(Option<Box<Expression>>),
|
||||||
Map(BTreeMap<String, (Statement, Option<Type>)>),
|
Structure {
|
||||||
|
definition_name: Identifier,
|
||||||
|
instantiator: StructureInstantiator,
|
||||||
|
},
|
||||||
|
StructureDefinition(StructureInstantiator),
|
||||||
BuiltInValue(BuiltInValue),
|
BuiltInValue(BuiltInValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for ValueNode {
|
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)?;
|
Error::expect_syntax_node(source, "value", node)?;
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
@ -51,41 +55,32 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
ValueNode::List(expressions)
|
ValueNode::List(expressions)
|
||||||
}
|
}
|
||||||
"map" => {
|
"structure" => {
|
||||||
let mut child_nodes = BTreeMap::new();
|
let identifier_node = child.child(1).unwrap();
|
||||||
let mut current_key = "".to_string();
|
let identifier = Identifier::from_syntax_node(source, identifier_node, context)?;
|
||||||
let mut current_type = None;
|
|
||||||
|
|
||||||
for index in 0..child.child_count() - 1 {
|
let instantiator_node = child.child(2);
|
||||||
let child_syntax_node = child.child(index).unwrap();
|
|
||||||
|
|
||||||
if child_syntax_node.kind() == "identifier" {
|
if let Some(node) = instantiator_node {
|
||||||
current_key =
|
let instantiator =
|
||||||
Identifier::from_syntax_node(source, child_syntax_node, context)?
|
StructureInstantiator::from_syntax_node(source, node, context)?;
|
||||||
.take_inner();
|
|
||||||
current_type = None;
|
ValueNode::Structure {
|
||||||
|
definition_name: identifier,
|
||||||
|
instantiator,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if child_syntax_node.kind() == "type_definition" {
|
todo!()
|
||||||
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) = ¤t_type {
|
|
||||||
type_definition.check(&statement.expected_type(context)?)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
child_nodes.insert(current_key.clone(), (statement, current_type.clone()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"structure_definition" => {
|
||||||
|
let instantiator_node = child.child(1).unwrap();
|
||||||
|
|
||||||
ValueNode::Map(child_nodes)
|
ValueNode::StructureDefinition(StructureInstantiator::from_syntax_node(
|
||||||
|
source,
|
||||||
|
instantiator_node,
|
||||||
|
context,
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
"option" => {
|
"option" => {
|
||||||
let first_grandchild = child.child(0).unwrap();
|
let first_grandchild = child.child(0).unwrap();
|
||||||
@ -122,7 +117,26 @@ impl AbstractTree for ValueNode {
|
|||||||
Ok(value_node)
|
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 {
|
let value = match self {
|
||||||
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
|
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
|
||||||
ValueNode::Float(value_source) => Value::Float(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)
|
Value::Option(option_value)
|
||||||
}
|
}
|
||||||
ValueNode::Map(key_statement_pairs) => {
|
ValueNode::Structure {
|
||||||
let map = Map::new();
|
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 = if let Some(statement) = statement_option {
|
||||||
let value = statement.run(source, context)?;
|
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)?,
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
let r#type = match self {
|
let r#type = match self {
|
||||||
ValueNode::Boolean(_) => Type::Boolean,
|
ValueNode::Boolean(_) => Type::Boolean,
|
||||||
ValueNode::Float(_) => Type::Float,
|
ValueNode::Float(_) => Type::Float,
|
||||||
@ -203,17 +242,11 @@ impl AbstractTree for ValueNode {
|
|||||||
Type::None
|
Type::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Map(statements) => {
|
ValueNode::Structure {
|
||||||
let mut identifier_types = Vec::new();
|
definition_name, ..
|
||||||
|
} => Type::Structure(definition_name.clone()),
|
||||||
for (key, (statement, _)) in statements {
|
ValueNode::StructureDefinition(instantiator) => {
|
||||||
identifier_types.push((
|
Type::StructureDefinition(instantiator.clone())
|
||||||
Identifier::new(key.clone()),
|
|
||||||
TypeDefinition::new(statement.expected_type(context)?),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Type::Map(identifier_types)
|
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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.
|
/// Abstract representation of a while loop.
|
||||||
///
|
///
|
||||||
@ -13,7 +13,7 @@ pub struct While {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "while", node)?;
|
||||||
|
|
||||||
let expression_node = node.child(1).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
@ -25,7 +25,7 @@ impl AbstractTree for While {
|
|||||||
Ok(While { expression, block })
|
Ok(While { expression, block })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
while self.expression.run(source, context)?.as_boolean()? {
|
while self.expression.run(source, context)?.as_boolean()? {
|
||||||
self.block.run(source, context)?;
|
self.block.run(source, context)?;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ impl AbstractTree for While {
|
|||||||
Ok(Value::none())
|
Ok(Value::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Structure) -> Result<Type> {
|
||||||
self.block.expected_type(context)
|
self.block.expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Map,
|
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Result,
|
||||||
Result, Type, Value,
|
Structure, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract representation of a yield expression.
|
/// Abstract representation of a yield expression.
|
||||||
@ -15,7 +15,7 @@ pub struct Yield {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
Error::expect_syntax_node(source, "yield", node)?;
|
||||||
|
|
||||||
let input_node = node.child(0).unwrap();
|
let input_node = node.child(0).unwrap();
|
||||||
@ -44,11 +44,11 @@ impl AbstractTree for Yield {
|
|||||||
Ok(Yield { call })
|
Ok(Yield { call })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &Structure) -> Result<Value> {
|
||||||
self.call.run(source, context)
|
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)
|
self.call.expected_type(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@ -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))),
|
|
||||||
)
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ use std::fs::read_to_string;
|
|||||||
use rand::{random, thread_rng, Rng};
|
use rand::{random, thread_rng, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Error, Map, Result, Type, Value};
|
use crate::{Error, Result, Structure, Type, Value};
|
||||||
|
|
||||||
pub use string::{string_functions, StringFunction};
|
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 {
|
match self {
|
||||||
BuiltInFunction::AssertEqual => {
|
BuiltInFunction::AssertEqual => {
|
||||||
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
||||||
@ -86,7 +91,7 @@ impl BuiltInFunction {
|
|||||||
let value = arguments.first().unwrap();
|
let value = arguments.first().unwrap();
|
||||||
let length = if let Ok(list) = value.as_list() {
|
let length = if let Ok(list) = value.as_list() {
|
||||||
list.items().len()
|
list.items().len()
|
||||||
} else if let Ok(map) = value.as_map() {
|
} else if let Ok(map) = value.as_structure() {
|
||||||
map.variables()?.len()
|
map.variables()?.len()
|
||||||
} else if let Ok(str) = value.as_string() {
|
} else if let Ok(str) = value.as_string() {
|
||||||
str.chars().count()
|
str.chars().count()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use enum_iterator::{all, Sequence};
|
use enum_iterator::{all, Sequence};
|
||||||
use serde::{Deserialize, Serialize};
|
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> {
|
pub fn string_functions() -> impl Iterator<Item = StringFunction> {
|
||||||
all()
|
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 {
|
let value = match self {
|
||||||
StringFunction::AsBytes => {
|
StringFunction::AsBytes => {
|
||||||
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
||||||
|
19
src/error.rs
19
src/error.rs
@ -4,7 +4,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::{LanguageError, Node, Point};
|
use tree_sitter::{LanguageError, Node, Point};
|
||||||
|
|
||||||
use crate::{value::Value, FunctionExpression, Type};
|
use crate::{value::Value, FunctionExpression, IndexExpression, Type};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Formatter},
|
fmt::{self, Formatter},
|
||||||
@ -54,6 +54,10 @@ pub enum Error {
|
|||||||
actual: usize,
|
actual: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExpectedIndexIdentifier {
|
||||||
|
actual: IndexExpression,
|
||||||
|
},
|
||||||
|
|
||||||
/// An operator was called with the wrong amount of arguments.
|
/// An operator was called with the wrong amount of arguments.
|
||||||
ExpectedOperatorArgumentAmount {
|
ExpectedOperatorArgumentAmount {
|
||||||
expected: usize,
|
expected: usize,
|
||||||
@ -150,6 +154,14 @@ pub enum Error {
|
|||||||
actual: Value,
|
actual: Value,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExpectedDefaultValue {
|
||||||
|
variable_name: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
ExpectedStructureDefinition {
|
||||||
|
actual: Type,
|
||||||
|
},
|
||||||
|
|
||||||
/// A `VariableIdentifier` operation did not find its value in the context.
|
/// A `VariableIdentifier` operation did not find its value in the context.
|
||||||
VariableIdentifierNotFound(String),
|
VariableIdentifierNotFound(String),
|
||||||
|
|
||||||
@ -435,6 +447,11 @@ impl fmt::Display for Error {
|
|||||||
ExpectedFunctionExpression { actual } => {
|
ExpectedFunctionExpression { actual } => {
|
||||||
write!(f, "Expected a function expression but got {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:?}."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//! functions or by constructing your own Evaluator.
|
//! functions or by constructing your own Evaluator.
|
||||||
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
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.
|
/// 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)));
|
/// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6)));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn interpret(source: &str) -> Result<Value> {
|
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.
|
/// Interpret the given source code with the given context.
|
||||||
@ -40,7 +40,7 @@ pub fn interpret(source: &str) -> Result<Value> {
|
|||||||
/// Ok(Value::Integer(10))
|
/// 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 mut interpreter = Interpreter::new(context);
|
||||||
let value = interpreter.run(source)?;
|
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.
|
/// A source code interpreter for the Dust language.
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
parser: Parser,
|
parser: Parser,
|
||||||
context: Map,
|
context: Structure,
|
||||||
syntax_tree: Option<TSTree>,
|
syntax_tree: Option<TSTree>,
|
||||||
abstract_tree: Option<Root>,
|
abstract_tree: Option<Root>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
pub fn new(context: Map) -> Self {
|
pub fn new(context: Structure) -> Self {
|
||||||
let mut parser = Parser::new();
|
let mut parser = Parser::new();
|
||||||
|
|
||||||
parser
|
parser
|
||||||
@ -133,6 +133,6 @@ impl Interpreter {
|
|||||||
|
|
||||||
impl Default for Interpreter {
|
impl Default for Interpreter {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Interpreter::new(Map::new())
|
Interpreter::new(Structure::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ pub use crate::{
|
|||||||
built_in_functions::BuiltInFunction,
|
built_in_functions::BuiltInFunction,
|
||||||
error::*,
|
error::*,
|
||||||
interpret::*,
|
interpret::*,
|
||||||
value::{function::Function, list::List, map::Map, Value},
|
value::{function::Function, list::List, structure::Structure, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod abstract_tree;
|
mod abstract_tree;
|
||||||
|
@ -12,7 +12,7 @@ use tree_sitter::Parser as TSParser;
|
|||||||
|
|
||||||
use std::{borrow::Cow, fs::read_to_string};
|
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.
|
/// Command-line arguments to be parsed.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@ -53,7 +53,7 @@ fn main() {
|
|||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let context = Map::new();
|
let context = Structure::default();
|
||||||
|
|
||||||
if let Some(input) = args.input {
|
if let Some(input) = args.input {
|
||||||
context
|
context
|
||||||
@ -168,7 +168,7 @@ impl Highlighter for DustReadline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_cli_shell() {
|
fn run_cli_shell() {
|
||||||
let context = Map::new();
|
let context = Structure::default();
|
||||||
let mut interpreter = Interpreter::new(context);
|
let mut interpreter = Interpreter::new(context);
|
||||||
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
|
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum Function {
|
pub enum Function {
|
||||||
@ -28,7 +28,7 @@ impl Function {
|
|||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
arguments: &[Value],
|
arguments: &[Value],
|
||||||
source: &str,
|
source: &str,
|
||||||
outer_context: &Map,
|
outer_context: &Structure,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
Function::BuiltIn(built_in_function) => {
|
Function::BuiltIn(built_in_function) => {
|
||||||
@ -51,24 +51,24 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for 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)?;
|
let inner_function = FunctionNode::from_syntax_node(_source, _node, _context)?;
|
||||||
|
|
||||||
Ok(Function::ContextDefined(inner_function))
|
Ok(Function::ContextDefined(inner_function))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, _context: &Map) -> Result<()> {
|
fn check_type(&self, _context: &Structure) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Function::BuiltIn(_) => Ok(()),
|
Function::BuiltIn(_) => Ok(()),
|
||||||
Function::ContextDefined(defined_function) => defined_function.check_type(_context),
|
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()))
|
Ok(Value::Function(self.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
fn expected_type(&self, _context: &Structure) -> Result<Type> {
|
||||||
match self {
|
match self {
|
||||||
Function::BuiltIn(built_in) => Ok(built_in.r#type()),
|
Function::BuiltIn(built_in) => Ok(built_in.r#type()),
|
||||||
Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()),
|
Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Types that represent runtime values.
|
//! Types that represent runtime values.
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
Function, Identifier, List, Map, Type, TypeDefinition,
|
Function, List, Structure, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
@ -21,7 +21,7 @@ use std::{
|
|||||||
|
|
||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod map;
|
pub mod structure;
|
||||||
|
|
||||||
/// Dust value representation.
|
/// Dust value representation.
|
||||||
///
|
///
|
||||||
@ -31,7 +31,7 @@ pub mod map;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
List(List),
|
List(List),
|
||||||
Map(Map),
|
Structure(Structure),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
String(Arc<RwLock<String>>),
|
String(Arc<RwLock<String>>),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
@ -74,17 +74,8 @@ impl Value {
|
|||||||
Type::List(Box::new(Type::Any))
|
Type::List(Box::new(Type::Any))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Map(map) => {
|
Value::Structure(structure) => {
|
||||||
let mut identifier_types = Vec::new();
|
Type::StructureDefinition(structure.instantiator().clone())
|
||||||
|
|
||||||
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::Function(function) => function.r#type().clone(),
|
Value::Function(function) => function.r#type().clone(),
|
||||||
Value::String(_) => Type::String,
|
Value::String(_) => Type::String,
|
||||||
@ -148,11 +139,11 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_map(&self) -> bool {
|
pub fn is_map(&self) -> bool {
|
||||||
matches!(self, Value::Map(_))
|
matches!(self, Value::Structure(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_function(&self) -> bool {
|
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`.
|
/// 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`.
|
/// 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 {
|
match self {
|
||||||
Value::Map(map) => Ok(map),
|
Value::Structure(map) => Ok(map),
|
||||||
value => Err(Error::ExpectedMap {
|
value => Err(Error::ExpectedMap {
|
||||||
actual: value.clone(),
|
actual: value.clone(),
|
||||||
}),
|
}),
|
||||||
@ -441,7 +432,7 @@ impl PartialEq for Value {
|
|||||||
left.read().unwrap().as_str() == right.read().unwrap().as_str()
|
left.read().unwrap().as_str() == right.read().unwrap().as_str()
|
||||||
}
|
}
|
||||||
(Value::List(left), Value::List(right)) => left == right,
|
(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::Function(left), Value::Function(right)) => left == right,
|
||||||
(Value::Option(left), Value::Option(right)) => left == right,
|
(Value::Option(left), Value::Option(right)) => left == right,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -480,8 +471,8 @@ impl Ord for Value {
|
|||||||
(Value::Boolean(_), _) => Ordering::Greater,
|
(Value::Boolean(_), _) => Ordering::Greater,
|
||||||
(Value::List(left), Value::List(right)) => left.cmp(right),
|
(Value::List(left), Value::List(right)) => left.cmp(right),
|
||||||
(Value::List(_), _) => Ordering::Greater,
|
(Value::List(_), _) => Ordering::Greater,
|
||||||
(Value::Map(left), Value::Map(right)) => left.cmp(right),
|
(Value::Structure(left), Value::Structure(right)) => left.cmp(right),
|
||||||
(Value::Map(_), _) => Ordering::Greater,
|
(Value::Structure(_), _) => Ordering::Greater,
|
||||||
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
||||||
(Value::Function(_), _) => Ordering::Greater,
|
(Value::Function(_), _) => Ordering::Greater,
|
||||||
(Value::Option(left), Value::Option(right)) => left.cmp(right),
|
(Value::Option(left), Value::Option(right)) => left.cmp(right),
|
||||||
@ -511,7 +502,7 @@ impl Serialize for Value {
|
|||||||
list.end()
|
list.end()
|
||||||
}
|
}
|
||||||
Value::Option(inner) => inner.serialize(serializer),
|
Value::Option(inner) => inner.serialize(serializer),
|
||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Structure(inner) => inner.serialize(serializer),
|
||||||
Value::Function(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::List(list) => write!(f, "{list}"),
|
||||||
Value::Map(map) => write!(f, "{map}"),
|
Value::Structure(map) => write!(f, "{map}"),
|
||||||
Value::Function(function) => write!(f, "{function}"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -852,13 +843,13 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
M: MapAccess<'de>,
|
M: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
let map = Map::new();
|
let map = Structure::default();
|
||||||
|
|
||||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||||
map.set(key, value, None).unwrap();
|
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>
|
fn visit_enum<A>(self, data: A) -> std::result::Result<Self::Value, A::Error>
|
||||||
|
@ -11,25 +11,33 @@ use std::{
|
|||||||
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
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.
|
/// 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
|
/// The inner value is a BTreeMap in order to allow VariableMap instances to be sorted and compared
|
||||||
/// to one another.
|
/// to one another.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Map {
|
pub struct Structure {
|
||||||
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>,
|
variables: Arc<RwLock<BTreeMap<String, (Value, Type)>>>,
|
||||||
|
instantiator: StructureInstantiator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Map {
|
impl Structure {
|
||||||
/// Creates a new instace.
|
pub fn new(
|
||||||
pub fn new() -> Self {
|
variables: BTreeMap<String, (Value, Type)>,
|
||||||
Map {
|
instantiator: StructureInstantiator,
|
||||||
variables: Arc::new(RwLock::new(BTreeMap::new())),
|
) -> Self {
|
||||||
|
Structure {
|
||||||
|
variables: Arc::new(RwLock::new(variables)),
|
||||||
|
instantiator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn instantiator(&self) -> &StructureInstantiator {
|
||||||
|
&self.instantiator
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clone_from(other: &Self) -> Result<Self> {
|
pub fn clone_from(other: &Self) -> Result<Self> {
|
||||||
let mut new_map = BTreeMap::new();
|
let mut new_map = BTreeMap::new();
|
||||||
|
|
||||||
@ -37,8 +45,9 @@ impl Map {
|
|||||||
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
|
new_map.insert(key.clone(), (value.clone(), r#type.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Map {
|
Ok(Structure {
|
||||||
variables: Arc::new(RwLock::new(new_map)),
|
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 {
|
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 {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
let left = self.variables.read().unwrap().clone().into_iter();
|
let left = self.variables.read().unwrap().clone().into_iter();
|
||||||
let right = other.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 {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
let left = self.variables.read().unwrap().clone().into_iter();
|
let left = self.variables.read().unwrap().clone().into_iter();
|
||||||
let right = other.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> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Map {
|
impl Display for Structure {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
writeln!(f, "{{")?;
|
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>
|
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
@ -142,7 +154,7 @@ impl Serialize for Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct MapVisitor {
|
struct MapVisitor {
|
||||||
marker: PhantomData<fn() -> Map>,
|
marker: PhantomData<fn() -> Structure>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapVisitor {
|
impl MapVisitor {
|
||||||
@ -154,17 +166,17 @@ impl MapVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for MapVisitor {
|
impl<'de> Visitor<'de> for MapVisitor {
|
||||||
type Value = Map;
|
type Value = Structure;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||||
formatter.write_str("Any valid whale data.")
|
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
|
where
|
||||||
M: MapAccess<'de>,
|
M: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
let map = Map::new();
|
let map = Structure::default();
|
||||||
|
|
||||||
{
|
{
|
||||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
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>
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
@ -139,23 +139,31 @@ mod value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map() {
|
fn structure() {
|
||||||
let map = Map::new();
|
let structure = Structure::default();
|
||||||
|
|
||||||
map.set("x".to_string(), Value::Integer(1), None).unwrap();
|
structure
|
||||||
map.set("foo".to_string(), Value::string("bar".to_string()), None)
|
.set("x".to_string(), Value::Integer(1), None)
|
||||||
|
.unwrap();
|
||||||
|
structure
|
||||||
|
.set("foo".to_string(), Value::string("bar".to_string()), None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
|
assert_eq!(
|
||||||
|
interpret("{ x = 1, foo = 'bar' }"),
|
||||||
|
Ok(Value::Structure(structure))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_types() {
|
fn structure_types() {
|
||||||
let map = Map::new();
|
let structure = Structure::default();
|
||||||
|
|
||||||
map.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
|
structure
|
||||||
|
.set("x".to_string(), Value::Integer(1), Some(Type::Integer))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
map.set(
|
structure
|
||||||
|
.set(
|
||||||
"foo".to_string(),
|
"foo".to_string(),
|
||||||
Value::string("bar".to_string()),
|
Value::string("bar".to_string()),
|
||||||
Some(Type::String),
|
Some(Type::String),
|
||||||
@ -164,12 +172,12 @@ mod value {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Structure(structure))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_type_errors() {
|
fn structure_type_errors() {
|
||||||
assert!(interpret("{ foo <bool> = 'bar' }")
|
assert!(interpret("{ foo <bool> = 'bar' }")
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.is_type_check_error(&Error::TypeCheck {
|
.is_type_check_error(&Error::TypeCheck {
|
||||||
@ -341,7 +349,7 @@ mod index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_index() {
|
fn structure_index() {
|
||||||
let test = interpret("x = {y = {z = 2}} x:y:z").unwrap();
|
let test = interpret("x = {y = {z = 2}} x:y:z").unwrap();
|
||||||
|
|
||||||
assert_eq!(Value::Integer(2), test);
|
assert_eq!(Value::Integer(2), test);
|
||||||
|
@ -151,7 +151,7 @@ Complex Function Call
|
|||||||
foobar(
|
foobar(
|
||||||
"hi"
|
"hi"
|
||||||
42
|
42
|
||||||
Baz:new()
|
new Baz
|
||||||
)
|
)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -169,13 +169,9 @@ foobar(
|
|||||||
(value
|
(value
|
||||||
(integer)))
|
(integer)))
|
||||||
(expression
|
(expression
|
||||||
(function_call
|
(value
|
||||||
(function_expression
|
(structure
|
||||||
(index
|
(identifier))))))))
|
||||||
(index_expression
|
|
||||||
(identifier))
|
|
||||||
(index_expression
|
|
||||||
(identifier))))))))))
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Callback Function Call
|
Callback Function Call
|
||||||
|
@ -114,3 +114,64 @@ x:(y()):0
|
|||||||
(index_expression
|
(index_expression
|
||||||
(value
|
(value
|
||||||
(integer)))))))
|
(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))))))))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
================================================================================
|
================================================================================
|
||||||
Simple Structure
|
Simple Structure Definition
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
struct { answer = 42 }
|
struct { answer = 42 }
|
||||||
@ -10,15 +10,16 @@ struct { answer = 42 }
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(structure
|
(structure_definition
|
||||||
|
(structure_instantiator
|
||||||
(identifier)
|
(identifier)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer)))))))))
|
(integer))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Structure with Types
|
Structure Definition with Types
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -32,7 +33,8 @@ struct {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(structure
|
(structure_definition
|
||||||
|
(structure_instantiator
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_definition
|
(type_definition
|
||||||
(type))
|
(type))
|
||||||
@ -53,10 +55,10 @@ struct {
|
|||||||
(string)))
|
(string)))
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(string))))))))))))
|
(string)))))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Nested Structures
|
Nested Structure Definition
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -70,7 +72,8 @@ struct {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(structure
|
(structure_definition
|
||||||
|
(structure_instantiator
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_definition
|
(type_definition
|
||||||
(type
|
(type
|
||||||
@ -78,4 +81,85 @@ struct {
|
|||||||
(identifier)
|
(identifier)
|
||||||
(type_definition
|
(type_definition
|
||||||
(type
|
(type
|
||||||
(identifier))))))))
|
(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))))))))))))
|
||||||
|
@ -82,6 +82,7 @@ module.exports = grammar({
|
|||||||
$.boolean,
|
$.boolean,
|
||||||
$.list,
|
$.list,
|
||||||
$.structure,
|
$.structure,
|
||||||
|
$.structure_definition,
|
||||||
$.option,
|
$.option,
|
||||||
$.built_in_value,
|
$.built_in_value,
|
||||||
),
|
),
|
||||||
@ -167,16 +168,37 @@ module.exports = grammar({
|
|||||||
']',
|
']',
|
||||||
),
|
),
|
||||||
|
|
||||||
structure: $ =>
|
structure_definition: $ =>
|
||||||
seq(
|
seq(
|
||||||
'struct',
|
'struct',
|
||||||
|
$.structure_instantiator,
|
||||||
|
),
|
||||||
|
|
||||||
|
structure: $ =>
|
||||||
|
prec.right(
|
||||||
|
seq(
|
||||||
|
'new',
|
||||||
|
$.identifier,
|
||||||
|
optional(
|
||||||
|
$.structure_instantiator,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
structure_instantiator: $ =>
|
||||||
|
seq(
|
||||||
'{',
|
'{',
|
||||||
repeat1(
|
repeat1(
|
||||||
seq(
|
seq(
|
||||||
$.identifier,
|
$.identifier,
|
||||||
optional($.type_definition),
|
choice(
|
||||||
optional(
|
$.type_definition,
|
||||||
seq('=', $.statement),
|
seq('=', $.statement),
|
||||||
|
seq(
|
||||||
|
$.type_definition,
|
||||||
|
'=',
|
||||||
|
$.statement,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
optional(','),
|
optional(','),
|
||||||
),
|
),
|
||||||
|
@ -237,6 +237,10 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "structure"
|
"name": "structure"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "structure_definition"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "option"
|
"name": "option"
|
||||||
@ -501,13 +505,51 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"structure": {
|
"structure_definition": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "struct"
|
"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": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "{"
|
"value": "{"
|
||||||
@ -528,14 +570,6 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "type_definition"
|
"name": "type_definition"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
{
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
@ -550,7 +584,21 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type_definition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "statement"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -514,6 +514,40 @@
|
|||||||
"type": "structure",
|
"type": "structure",
|
||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"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": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
@ -614,6 +648,10 @@
|
|||||||
{
|
{
|
||||||
"type": "structure",
|
"type": "structure",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "structure_definition",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -848,6 +886,10 @@
|
|||||||
"type": "match",
|
"type": "match",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "new",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "none",
|
"type": "none",
|
||||||
"named": false
|
"named": false
|
||||||
@ -882,11 +924,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"named": true
|
"named": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"named": false
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "struct",
|
"type": "struct",
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user