Add type definitions as a first-class value
This commit is contained in:
parent
ed6e4cfd1a
commit
6c4efadb10
@ -4,7 +4,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, BuiltInValue, Error, Expression, Format, Function, FunctionNode, Identifier,
|
AbstractTree, BuiltInValue, Error, Expression, Format, Function, FunctionNode, Identifier,
|
||||||
List, Map, Result, Statement, Structure, SyntaxNode, Type, TypeSpecification, Value,
|
List, Map, Result, Statement, Structure, SyntaxNode, Type, TypeDefintion, TypeSpecification,
|
||||||
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -18,7 +19,7 @@ pub enum ValueNode {
|
|||||||
Option(Option<Box<Expression>>),
|
Option(Option<Box<Expression>>),
|
||||||
Map(BTreeMap<String, (Statement, Option<Type>)>),
|
Map(BTreeMap<String, (Statement, Option<Type>)>),
|
||||||
BuiltInValue(BuiltInValue),
|
BuiltInValue(BuiltInValue),
|
||||||
Structure(BTreeMap<String, (Option<Statement>, Type)>),
|
StructureDefinition(BTreeMap<String, (Option<Statement>, Type)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for ValueNode {
|
impl AbstractTree for ValueNode {
|
||||||
@ -159,7 +160,7 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueNode::Structure(btree_map)
|
ValueNode::StructureDefinition(btree_map)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
@ -229,7 +230,7 @@ impl AbstractTree for ValueNode {
|
|||||||
Value::Map(map)
|
Value::Map(map)
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.run(source, context)?,
|
||||||
ValueNode::Structure(node_map) => {
|
ValueNode::StructureDefinition(node_map) => {
|
||||||
let mut value_map = BTreeMap::new();
|
let mut value_map = BTreeMap::new();
|
||||||
|
|
||||||
for (key, (statement_option, r#type)) in node_map {
|
for (key, (statement_option, r#type)) in node_map {
|
||||||
@ -242,7 +243,7 @@ impl AbstractTree for ValueNode {
|
|||||||
value_map.insert(key.to_string(), (value_option, r#type.clone()));
|
value_map.insert(key.to_string(), (value_option, r#type.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Structure(Structure::new(value_map))
|
Value::TypeDefinition(TypeDefintion::Structure(Structure::new(value_map)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,7 +287,7 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
ValueNode::Map(_) => Type::Map(None),
|
ValueNode::Map(_) => Type::Map(None),
|
||||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
|
||||||
ValueNode::Structure(node_map) => {
|
ValueNode::StructureDefinition(node_map) => {
|
||||||
let mut value_map = BTreeMap::new();
|
let mut value_map = BTreeMap::new();
|
||||||
|
|
||||||
for (key, (_statement_option, r#type)) in node_map {
|
for (key, (_statement_option, r#type)) in node_map {
|
||||||
@ -356,7 +357,7 @@ impl Format for ValueNode {
|
|||||||
output.push('}');
|
output.push('}');
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInValue(built_in_value) => built_in_value.format(output, indent_level),
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.format(output, indent_level),
|
||||||
ValueNode::Structure(nodes) => {
|
ValueNode::StructureDefinition(nodes) => {
|
||||||
output.push('{');
|
output.push('{');
|
||||||
|
|
||||||
for (key, (value_option, r#type)) in nodes {
|
for (key, (value_option, r#type)) in nodes {
|
||||||
|
@ -8,7 +8,10 @@ pub use crate::{
|
|||||||
built_in_functions::BuiltInFunction,
|
built_in_functions::BuiltInFunction,
|
||||||
error::*,
|
error::*,
|
||||||
interpret::*,
|
interpret::*,
|
||||||
value::{function::Function, list::List, map::Map, structure::Structure, Value},
|
value::{
|
||||||
|
function::Function, list::List, map::Map, structure::Structure,
|
||||||
|
type_definition::TypeDefintion, Value,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use tree_sitter::Node as SyntaxNode;
|
pub use tree_sitter::Node as SyntaxNode;
|
||||||
|
@ -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, Structure, Type, TypeSpecification,
|
Function, Identifier, List, Map, Type, TypeDefintion, TypeSpecification,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
@ -22,6 +22,7 @@ pub mod function;
|
|||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod structure;
|
pub mod structure;
|
||||||
|
pub mod type_definition;
|
||||||
|
|
||||||
/// Dust value representation.
|
/// Dust value representation.
|
||||||
///
|
///
|
||||||
@ -38,7 +39,7 @@ pub enum Value {
|
|||||||
Integer(i64),
|
Integer(i64),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Option(Option<Box<Value>>),
|
Option(Option<Box<Value>>),
|
||||||
Structure(Structure),
|
TypeDefinition(TypeDefintion),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Value {
|
impl Default for Value {
|
||||||
@ -99,7 +100,7 @@ impl Value {
|
|||||||
Type::None
|
Type::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Structure(_) => todo!(),
|
Value::TypeDefinition(_) => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
r#type
|
r#type
|
||||||
@ -432,7 +433,7 @@ impl PartialEq for Value {
|
|||||||
(Value::Map(left), Value::Map(right)) => left == right,
|
(Value::Map(left), Value::Map(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,
|
||||||
(Value::Structure(left), Value::Structure(right)) => left == right,
|
(Value::TypeDefinition(left), Value::TypeDefinition(right)) => left == right,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -469,8 +470,8 @@ impl Ord for Value {
|
|||||||
(Value::Map(_), _) => Ordering::Greater,
|
(Value::Map(_), _) => 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::Structure(left), Value::Structure(right)) => left.cmp(right),
|
(Value::TypeDefinition(left), Value::TypeDefinition(right)) => left.cmp(right),
|
||||||
(Value::Structure(_), _) => Ordering::Greater,
|
(Value::TypeDefinition(_), _) => Ordering::Greater,
|
||||||
(Value::Option(left), Value::Option(right)) => left.cmp(right),
|
(Value::Option(left), Value::Option(right)) => left.cmp(right),
|
||||||
(Value::Option(_), _) => Ordering::Less,
|
(Value::Option(_), _) => Ordering::Less,
|
||||||
}
|
}
|
||||||
@ -500,7 +501,7 @@ impl Serialize for Value {
|
|||||||
Value::Option(inner) => inner.serialize(serializer),
|
Value::Option(inner) => inner.serialize(serializer),
|
||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Map(inner) => inner.serialize(serializer),
|
||||||
Value::Function(inner) => inner.serialize(serializer),
|
Value::Function(inner) => inner.serialize(serializer),
|
||||||
Value::Structure(inner) => inner.serialize(serializer),
|
Value::TypeDefinition(inner) => inner.serialize(serializer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -522,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::Map(map) => write!(f, "{map}"),
|
||||||
Value::Function(function) => write!(f, "{function}"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
Value::Structure(structure) => write!(f, "{structure}"),
|
Value::TypeDefinition(structure) => write!(f, "{structure}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/value/type_definition.rs
Normal file
16
src/value/type_definition.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::Structure;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub enum TypeDefintion {
|
||||||
|
Structure(Structure),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TypeDefintion {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{self}")
|
||||||
|
}
|
||||||
|
}
|
@ -10,5 +10,9 @@ fn simple_structure() {
|
|||||||
|
|
||||||
btree_map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer));
|
btree_map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer));
|
||||||
|
|
||||||
assert_eq!(Ok(Value::Structure(Structure::new(btree_map))), result);
|
let expected = Ok(Value::TypeDefinition(TypeDefintion::Structure(
|
||||||
|
Structure::new(btree_map),
|
||||||
|
)));
|
||||||
|
|
||||||
|
assert_eq!(expected, result);
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,14 @@ struct {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
|
(type_definition
|
||||||
(structure
|
(structure
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_specification
|
(type_specification
|
||||||
(type))
|
(type))
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_specification
|
(type_specification
|
||||||
(type)))))))
|
(type))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Complex Structure
|
Complex Structure
|
||||||
@ -44,6 +45,7 @@ Foo = struct {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
|
(type_definition
|
||||||
(structure
|
(structure
|
||||||
(identifier)
|
(identifier)
|
||||||
(type_specification
|
(type_specification
|
||||||
@ -67,4 +69,4 @@ Foo = struct {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))))))))))))
|
(integer)))))))))))))))
|
||||||
|
@ -85,6 +85,11 @@ module.exports = grammar({
|
|||||||
$.map,
|
$.map,
|
||||||
$.option,
|
$.option,
|
||||||
$.built_in_value,
|
$.built_in_value,
|
||||||
|
$.type_definition,
|
||||||
|
),
|
||||||
|
|
||||||
|
type_definition: $ =>
|
||||||
|
choice(
|
||||||
$.structure,
|
$.structure,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -249,6 +249,15 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "built_in_value"
|
"name": "built_in_value"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type_definition"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type_definition": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "structure"
|
"name": "structure"
|
||||||
|
@ -602,6 +602,21 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "type_definition",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "structure",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "type_specification",
|
"type": "type_specification",
|
||||||
"named": true,
|
"named": true,
|
||||||
@ -662,7 +677,7 @@
|
|||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "structure",
|
"type": "type_definition",
|
||||||
"named": true
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user