Implement structure value

This commit is contained in:
Jeff 2024-01-06 01:05:13 -05:00
parent 3cbd3bbf3c
commit 86d2e6aaf4
9 changed files with 18545 additions and 15893 deletions

View File

@ -19,6 +19,7 @@ pub enum ValueNode {
Option(Option<Box<Expression>>),
Map(BTreeMap<String, (Statement, Option<Type>)>),
BuiltInValue(BuiltInValue),
Structure(BTreeMap<String, (Option<Statement>, Type)>),
}
impl AbstractTree for ValueNode {
@ -109,9 +110,64 @@ impl AbstractTree for ValueNode {
context,
)?)
}
"structure" => {
let mut btree_map = BTreeMap::new();
let mut current_identifier: Option<Identifier> = None;
let mut current_type: Option<Type> = None;
let mut current_statement = None;
for index in 0..child.child_count() - 1 {
let child_syntax_node = child.child(index).unwrap();
if child_syntax_node.kind() == "identifier" {
if current_statement.is_none() {
if let (Some(identifier), Some(r#type)) =
(&current_identifier, &current_type)
{
btree_map
.insert(identifier.inner().clone(), (None, r#type.clone()));
}
}
current_type = None;
current_identifier = Some(Identifier::from_syntax_node(
source,
child_syntax_node,
context,
)?);
}
if child_syntax_node.kind() == "type_definition" {
current_type = Some(
TypeDefinition::from_syntax_node(source, child_syntax_node, context)?
.take_inner(),
);
}
if child_syntax_node.kind() == "statement" {
current_statement = Some(Statement::from_syntax_node(
source,
child_syntax_node,
context,
)?);
if let (Some(identifier), Some(r#type)) =
(&current_identifier, &current_type)
{
btree_map.insert(
identifier.inner().clone(),
(current_statement.clone(), r#type.clone()),
);
}
}
}
ValueNode::Structure(btree_map)
}
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected: "string, integer, float, boolean, list, map, or option".to_string(),
expected: "string, integer, float, boolean, list, map, option or structure"
.to_string(),
actual: child.kind().to_string(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
@ -163,6 +219,21 @@ impl AbstractTree for ValueNode {
Value::Map(map)
}
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
ValueNode::Structure(node_map) => {
let mut value_map = BTreeMap::new();
for (key, (statement_option, r#type)) in node_map {
let value = if let Some(statement) = statement_option {
statement.run(source, context)?
} else {
Value::none()
};
value_map.insert(key.to_string(), (Some(value), r#type.clone()));
}
Value::Structure(value_map)
}
};
Ok(value)
@ -205,6 +276,7 @@ impl AbstractTree for ValueNode {
}
ValueNode::Map(_) => Type::Map,
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
ValueNode::Structure(_) => todo!(),
};
Ok(r#type)

View File

@ -223,5 +223,6 @@ fn display_value(value: &Value, ui: &mut egui::Ui) {
ui.label("none");
}
},
Value::Structure(_) => todo!(),
}
}

View File

@ -12,6 +12,7 @@ use serde::{
use std::{
cmp::Ordering,
collections::BTreeMap,
convert::TryFrom,
fmt::{self, Display, Formatter},
marker::PhantomData,
@ -38,6 +39,7 @@ pub enum Value {
Integer(i64),
Boolean(bool),
Option(Option<Box<Value>>),
Structure(BTreeMap<String, (Option<Value>, Type)>),
}
impl Default for Value {
@ -98,6 +100,7 @@ impl Value {
Type::None
}
}
Value::Structure(_) => todo!(),
};
r#type
@ -444,6 +447,7 @@ impl PartialEq for Value {
(Value::Map(left), Value::Map(right)) => left == right,
(Value::Function(left), Value::Function(right)) => left == right,
(Value::Option(left), Value::Option(right)) => left == right,
(Value::Structure(left), Value::Structure(right)) => left == right,
_ => false,
}
}
@ -484,6 +488,8 @@ impl Ord for Value {
(Value::Map(_), _) => Ordering::Greater,
(Value::Function(left), Value::Function(right)) => left.cmp(right),
(Value::Function(_), _) => Ordering::Greater,
(Value::Structure(left), Value::Structure(right)) => left.cmp(right),
(Value::Structure(_), _) => Ordering::Greater,
(Value::Option(left), Value::Option(right)) => left.cmp(right),
(Value::Option(_), _) => Ordering::Less,
}
@ -513,6 +519,7 @@ impl Serialize for Value {
Value::Option(inner) => inner.serialize(serializer),
Value::Map(inner) => inner.serialize(serializer),
Value::Function(inner) => inner.serialize(serializer),
Value::Structure(inner) => inner.serialize(serializer),
}
}
}
@ -534,6 +541,18 @@ impl Display for Value {
Value::List(list) => write!(f, "{list}"),
Value::Map(map) => write!(f, "{map}"),
Value::Function(function) => write!(f, "{function}"),
Value::Structure(btree_map) => {
writeln!(f, "{{")?;
for (key, (value_option, r#type)) in btree_map {
if let Some(value) = value_option {
writeln!(f, " {key} {} = {value}", r#type)?;
} else {
writeln!(f, " {key} {}", r#type)?;
}
}
write!(f, "}}")
}
}
}
}

View File

@ -1,3 +1,20 @@
mod structure {
use std::collections::BTreeMap;
use dust_lang::*;
#[test]
fn simple_structure() {
let result = interpret("struct { x <int> = 0 }");
let mut btree_map = BTreeMap::new();
btree_map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer));
assert_eq!(Ok(Value::Structure(btree_map)), result);
}
}
mod assignment {
use dust_lang::*;

View File

@ -0,0 +1,70 @@
================================================================================
Simple Structure
================================================================================
struct {
x <int>
y <float>
}
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(structure
(identifier)
(type_definition
(type))
(identifier)
(type_definition
(type)))))))
================================================================================
Complex Structure
================================================================================
Foo = struct {
x <int>
y <float> = 0.0
bar <Bar> = new Bar {
baz = 42
}
}
--------------------------------------------------------------------------------
(root
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(structure
(identifier)
(type_definition
(type))
(identifier)
(type_definition
(type))
(statement
(expression
(value
(float))))
(identifier)
(type_definition
(type
(identifier)))
(statement
(expression
(new
(identifier)
(identifier)
(statement
(expression
(value
(integer))))))))))))))

View File

@ -49,6 +49,7 @@ module.exports = grammar({
$.math,
$.value,
$.yield,
$.new,
),
),
@ -84,6 +85,56 @@ module.exports = grammar({
$.map,
$.option,
$.built_in_value,
$.structure,
),
structure: $ =>
seq(
'struct',
'{',
repeat(
choice(
seq(
$.identifier,
$.type_definition,
),
seq(
$.identifier,
'=',
$.statement,
),
seq(
$.identifier,
$.type_definition,
'=',
$.statement,
),
),
),
'}',
),
new: $ =>
seq(
'new',
$.identifier,
'{',
repeat(
choice(
seq(
$.identifier,
'=',
$.statement,
),
seq(
$.identifier,
$.type_definition,
'=',
$.statement,
),
),
),
'}',
),
integer: $ =>
@ -351,6 +402,7 @@ module.exports = grammar({
'none',
'num',
'str',
$.identifier,
seq('[', $.type, ']'),
seq(
'(',

View File

@ -138,6 +138,10 @@
{
"type": "SYMBOL",
"name": "yield"
},
{
"type": "SYMBOL",
"name": "new"
}
]
}
@ -244,6 +248,153 @@
{
"type": "SYMBOL",
"name": "built_in_value"
},
{
"type": "SYMBOL",
"name": "structure"
}
]
},
"structure": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "struct"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "type_definition"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "type_definition"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
}
]
}
},
{
"type": "STRING",
"value": "}"
}
]
},
"new": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "new"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "type_definition"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}
]
}
]
}
},
{
"type": "STRING",
"value": "}"
}
]
},
@ -1115,6 +1266,10 @@
"type": "STRING",
"value": "str"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SEQ",
"members": [
@ -1132,27 +1287,6 @@
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "type_definition"
},
{
"type": "STRING",
"value": "}"
}
]
},
{
"type": "SEQ",
"members": [

View File

@ -118,6 +118,10 @@
"type": "math",
"named": true
},
{
"type": "new",
"named": true
},
{
"type": "value",
"named": true
@ -441,6 +445,29 @@
"named": true,
"fields": {}
},
{
"type": "new",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
},
{
"type": "option",
"named": true,
@ -533,6 +560,29 @@
]
}
},
{
"type": "structure",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
},
{
"type": "type",
"named": true,
@ -548,10 +598,6 @@
{
"type": "type",
"named": true
},
{
"type": "type_definition",
"named": true
}
]
}
@ -614,6 +660,10 @@
{
"type": "string",
"named": true
},
{
"type": "structure",
"named": true
}
]
}
@ -802,11 +852,11 @@
},
{
"type": "float",
"named": true
"named": false
},
{
"type": "float",
"named": false
"named": true
},
{
"type": "for",
@ -852,6 +902,10 @@
"type": "match",
"named": false
},
{
"type": "new",
"named": false
},
{
"type": "none",
"named": false
@ -892,6 +946,10 @@
"type": "string",
"named": false
},
{
"type": "struct",
"named": false
},
{
"type": "true",
"named": false

File diff suppressed because it is too large Load Diff