Overhaul built-ins and identifiers

This commit is contained in:
Jeff 2024-02-15 15:20:29 -05:00
parent 91e94a5adc
commit c2ba519240
29 changed files with 330 additions and 387 deletions

View File

@ -54,14 +54,13 @@ impl AbstractTree for Assignment {
fn validate(&self, source: &str, context: &Context) -> Result<(), ValidationError> {
if let AssignmentOperator::Equal = self.operator {
let key = self.identifier.inner().clone();
let r#type = if let Some(definition) = &self.type_specification {
definition.inner().clone()
} else {
self.statement.expected_type(context)?
};
context.set_type(key, r#type)?;
context.set_type(self.identifier.clone(), r#type)?;
}
if let Some(type_specification) = &self.type_specification {
@ -130,30 +129,33 @@ impl AbstractTree for Assignment {
}
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let key = self.identifier.inner();
let value = self.statement.run(source, context)?;
let new_value = match self.operator {
AssignmentOperator::PlusEqual => {
if let Some(mut previous_value) = context.get_value(key)? {
if let Some(mut previous_value) = context.get_value(&self.identifier)? {
previous_value += value;
previous_value
} else {
return Err(RuntimeError::VariableIdentifierNotFound(key.clone()));
return Err(RuntimeError::VariableIdentifierNotFound(
self.identifier.clone(),
));
}
}
AssignmentOperator::MinusEqual => {
if let Some(mut previous_value) = context.get_value(key)? {
if let Some(mut previous_value) = context.get_value(&self.identifier)? {
previous_value -= value;
previous_value
} else {
return Err(RuntimeError::VariableIdentifierNotFound(key.clone()));
return Err(RuntimeError::VariableIdentifierNotFound(
self.identifier.clone(),
));
}
}
AssignmentOperator::Equal => value,
};
context.set_value(key.clone(), new_value)?;
context.set_value(self.identifier.clone(), new_value)?;
Ok(Value::none())
}

View File

@ -27,8 +27,8 @@ impl EnumDefinition {
}
}
pub fn instantiate(&self, variant: String, content: Option<Value>) -> EnumInstance {
EnumInstance::new(self.identifier.inner().clone(), variant, content)
pub fn instantiate(&self, variant: Identifier, content: Option<Value>) -> EnumInstance {
EnumInstance::new(self.identifier.clone(), variant, content)
}
pub fn identifier(&self) -> &Identifier {
@ -86,10 +86,7 @@ impl AbstractTree for EnumDefinition {
}
fn run(&self, _source: &str, context: &Context) -> Result<Value, RuntimeError> {
context.set_definition(
self.identifier.inner().clone(),
TypeDefinition::Enum(self.clone()),
)?;
context.set_definition(self.identifier.clone(), TypeDefinition::Enum(self.clone()))?;
Ok(Value::none())
}

View File

@ -76,7 +76,7 @@ impl AbstractTree for For {
position: self.source_position,
});
};
let key = self.item_id.inner().clone();
let key = self.item_id.clone();
self.context.inherit_from(context)?;
self.context.set_type(key, item_type)?;
@ -87,7 +87,7 @@ impl AbstractTree for For {
self.context.inherit_from(context)?;
let expression_run = self.collection.run(source, context)?;
let key = self.item_id.inner();
let key = &self.item_id;
if let Value::Range(range) = expression_run {
if self.is_async {

View File

@ -142,16 +142,11 @@ impl AbstractTree for FunctionCall {
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let value = match &self.function_expression {
FunctionExpression::Identifier(identifier) => {
let key = identifier.inner();
if let Some(value) = context.get_value(key)? {
self.context
.set_value(identifier.inner().clone(), value.clone())?;
if let Some(value) = context.get_value(identifier)? {
self.context.set_value(identifier.clone(), value.clone())?;
value.clone()
} else {
return Err(RuntimeError::VariableIdentifierNotFound(
identifier.inner().clone(),
));
return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone()));
}
}
FunctionExpression::FunctionCall(function_call) => {
@ -181,7 +176,7 @@ impl AbstractTree for FunctionCall {
for (identifier, expression) in parameter_expression_pairs {
let value = expression.run(source, context)?;
self.context.set_value(identifier.inner().clone(), value)?;
self.context.set_value(identifier.clone(), value)?;
}
function_node.call(source, &self.context)

View File

@ -118,7 +118,7 @@ impl AbstractTree for FunctionNode {
let validation_context = Context::new();
for (parameter, r#type) in self.parameters.iter().zip(parameter_types.iter()) {
validation_context.set_type(parameter.inner().clone(), r#type.clone())?;
validation_context.set_type(parameter.clone(), r#type.clone())?;
}
let actual = self.body.expected_type(&validation_context)?;

View File

@ -1,8 +1,12 @@
use std::fmt::{self, Display, Formatter};
use std::{
fmt::{self, Display, Formatter},
sync::Arc,
};
use serde::{Deserialize, Serialize};
use serde::{de::Visitor, Deserialize, Serialize};
use crate::{
built_in_identifiers::all_built_in_identifiers,
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Format, SyntaxNode, Type, Value,
};
@ -10,22 +14,30 @@ use crate::{
/// A string by which a variable is known to a context.
///
/// Every variable is a key-value pair. An identifier holds the key part of that
/// pair. Its inner value can be used to retrieve a Value instance from a Map.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Identifier(String);
/// pair and can be used to retrieve a Value instance from a Map or Context.
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Identifier(Arc<String>);
impl Identifier {
pub fn new<T: Into<String>>(inner: T) -> Self {
Identifier(inner.into())
pub fn new(key: &str) -> Self {
for built_in_identifier in all_built_in_identifiers() {
let identifier = built_in_identifier.get();
if &key == identifier.inner().as_ref() {
return identifier.clone();
}
}
Identifier(Arc::new(key.to_string()))
}
pub fn take_inner(self) -> String {
self.0
}
pub fn inner(&self) -> &String {
pub fn inner(&self) -> &Arc<String> {
&self.0
}
pub fn contains(&self, string: &str) -> bool {
self.0.as_ref() == string
}
}
impl AbstractTree for Identifier {
@ -40,7 +52,7 @@ impl AbstractTree for Identifier {
debug_assert!(!text.is_empty());
Ok(Identifier(text.to_string()))
Ok(Identifier::new(text))
}
fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> {
@ -48,7 +60,7 @@ impl AbstractTree for Identifier {
}
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
if let Some(r#type) = context.get_type(&self.0)? {
if let Some(r#type) = context.get_type(self)? {
Ok(r#type)
} else {
Err(ValidationError::VariableIdentifierNotFound(self.clone()))
@ -56,10 +68,10 @@ impl AbstractTree for Identifier {
}
fn run(&self, _source: &str, context: &Context) -> Result<Value, RuntimeError> {
if let Some(value) = context.get_value(&self.0)? {
if let Some(value) = context.get_value(self)? {
Ok(value.clone())
} else {
Err(RuntimeError::VariableIdentifierNotFound(self.0.clone()))
Err(RuntimeError::VariableIdentifierNotFound(self.clone()))
}
}
}
@ -75,3 +87,38 @@ impl Display for Identifier {
write!(f, "{}", self.0)
}
}
impl Serialize for Identifier {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.0.as_ref())
}
}
impl<'de> Deserialize<'de> for Identifier {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_string(IdentifierVisitor)
}
}
struct IdentifierVisitor;
impl<'de> Visitor<'de> for IdentifierVisitor {
type Value = Identifier;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("valid UFT-8 sequence")
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Identifier(Arc::new(v)))
}
}

View File

@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
use crate::{
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Format, IndexExpression, List, SourcePosition, SyntaxNode, Type, Value,
AbstractTree, Context, Format, Identifier, IndexExpression, SourcePosition, SyntaxNode, Type,
Value,
};
/// Abstract representation of an index expression.
@ -12,7 +13,6 @@ use crate::{
pub struct Index {
pub collection: IndexExpression,
pub index: IndexExpression,
pub index_end: Option<IndexExpression>,
source_position: SourcePosition,
}
@ -26,21 +26,9 @@ impl AbstractTree for Index {
let index_node = node.child(2).unwrap();
let index = IndexExpression::from_syntax(index_node, source, context)?;
let index_end_node = node.child(4);
let index_end = if let Some(index_end_node) = index_end_node {
Some(IndexExpression::from_syntax(
index_end_node,
source,
context,
)?)
} else {
None
};
Ok(Index {
collection,
index,
index_end,
source_position: SourcePosition::from(node.range()),
})
}
@ -58,10 +46,6 @@ impl AbstractTree for Index {
self.collection.validate(_source, _context)?;
self.index.validate(_source, _context)?;
if let Some(index_end) = &self.index_end {
index_end.validate(_source, _context)?;
}
Ok(())
}
@ -71,36 +55,28 @@ impl AbstractTree for Index {
match value {
Value::List(list) => {
let index = self.index.run(source, context)?.as_integer()? as usize;
let item = if let Some(index_end) = &self.index_end {
let index_end = index_end.run(source, context)?.as_integer()? as usize;
let sublist = list.items()[index..=index_end].to_vec();
Value::List(List::with_items(sublist))
} else {
list.items().get(index).cloned().unwrap_or_default()
};
let item = list.items().get(index).cloned().unwrap_or_default();
Ok(item)
}
Value::Map(map) => {
let map = map.inner();
let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index {
let key = identifier.inner();
let value = map.get(key).unwrap_or_default();
let (identifier, value) =
if let IndexExpression::Identifier(identifier) = &self.index {
let value = map.get(identifier).unwrap_or_default();
(key.clone(), value)
} else {
let index_value = self.index.run(source, context)?;
let key = index_value.as_string()?;
let value = map.get(key.as_str()).unwrap_or_default();
(identifier.clone(), value)
} else {
let index_value = self.index.run(source, context)?;
let identifier = Identifier::new(index_value.as_string()?);
let value = map.get(&identifier).unwrap_or_default();
(key.clone(), value)
};
(identifier, value)
};
if value.is_none() {
Err(RuntimeError::VariableIdentifierNotFound(key))
Err(RuntimeError::VariableIdentifierNotFound(identifier))
} else {
Ok(value.clone())
}
@ -121,10 +97,5 @@ impl Format for Index {
self.collection.format(output, indent_level);
output.push(':');
self.index.format(output, indent_level);
if let Some(expression) = &self.index_end {
output.push_str("..");
expression.format(output, indent_level);
}
}
}

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use crate::{
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, AssignmentOperator, Context, Format, Index, IndexExpression, Statement,
SyntaxNode, Type, Value,
AbstractTree, AssignmentOperator, Context, Format, Identifier, Index, IndexExpression,
Statement, SyntaxNode, Type, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -44,11 +44,14 @@ impl AbstractTree for IndexAssignment {
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let _index_collection = self.index.collection.run(source, context)?;
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier.inner()
let index_identifier = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier
} else {
let index_run = self.index.index.run(source, context)?;
let expected_identifier = Identifier::new(index_run.as_string()?);
return Err(RuntimeError::VariableIdentifierNotFound(
self.index.index.run(source, context)?.to_string(),
expected_identifier,
));
};
@ -56,7 +59,7 @@ impl AbstractTree for IndexAssignment {
let new_value = match self.operator {
AssignmentOperator::PlusEqual => {
if let Some(mut previous_value) = context.get_value(index_key)? {
if let Some(mut previous_value) = context.get_value(index_identifier)? {
previous_value += value;
previous_value
} else {
@ -64,7 +67,7 @@ impl AbstractTree for IndexAssignment {
}
}
AssignmentOperator::MinusEqual => {
if let Some(mut previous_value) = context.get_value(index_key)? {
if let Some(mut previous_value) = context.get_value(index_identifier)? {
previous_value -= value;
previous_value
} else {
@ -74,7 +77,7 @@ impl AbstractTree for IndexAssignment {
AssignmentOperator::Equal => value,
};
context.set_value(index_key.clone(), new_value)?;
context.set_value(index_identifier.clone(), new_value)?;
Ok(Value::none())
}

View File

@ -11,12 +11,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct MapNode {
properties: BTreeMap<String, (Statement, Option<Type>)>,
properties: BTreeMap<Identifier, (Statement, Option<Type>)>,
position: SourcePosition,
}
impl MapNode {
pub fn properties(&self) -> &BTreeMap<String, (Statement, Option<Type>)> {
pub fn properties(&self) -> &BTreeMap<Identifier, (Statement, Option<Type>)> {
&self.properties
}
}
@ -26,14 +26,14 @@ impl AbstractTree for MapNode {
SyntaxError::expect_syntax_node(source, "map", node)?;
let mut properties = BTreeMap::new();
let mut current_key = "".to_string();
let mut current_identifier = None;
let mut current_type = None;
for index in 0..node.child_count() - 1 {
let child = node.child(index).unwrap();
if child.kind() == "identifier" {
current_key = Identifier::from_syntax(child, source, context)?.take_inner();
current_identifier = Some(Identifier::from_syntax(child, source, context)?);
current_type = None;
}
@ -45,7 +45,9 @@ impl AbstractTree for MapNode {
if child.kind() == "statement" {
let statement = Statement::from_syntax(child, source, context)?;
properties.insert(current_key.clone(), (statement, current_type.clone()));
if let Some(identifier) = &current_identifier {
properties.insert(identifier.clone(), (statement, current_type.clone()));
}
}
}

View File

@ -84,16 +84,15 @@ impl AbstractTree for Match {
if let (Value::Enum(enum_instance), MatchPattern::EnumPattern(enum_pattern)) =
(&matcher_value, pattern)
{
if enum_instance.name() == enum_pattern.name().inner()
&& enum_instance.variant_name() == enum_pattern.variant().inner()
if enum_instance.name() == enum_pattern.name()
&& enum_instance.variant() == enum_pattern.variant()
{
let statement_context = Context::with_variables_from(context)?;
if let (Some(identifier), Some(value)) =
(enum_pattern.inner_identifier(), enum_instance.value())
{
statement_context
.set_value(identifier.inner().clone(), value.as_ref().clone())?;
statement_context.set_value(identifier.clone(), value.as_ref().clone())?;
}
return statement.run(source, &statement_context);

View File

@ -12,7 +12,7 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructDefinition {
name: Identifier,
properties: BTreeMap<String, (Option<Statement>, Type)>,
properties: BTreeMap<Identifier, (Option<Statement>, Type)>,
}
impl StructDefinition {
@ -38,10 +38,7 @@ impl StructDefinition {
all_properties.set(key.clone(), value);
}
Ok(StructInstance::new(
self.name.inner().clone(),
all_properties,
))
Ok(StructInstance::new(self.name.clone(), all_properties))
}
}
@ -63,7 +60,7 @@ impl AbstractTree for StructDefinition {
if child_syntax_node.kind() == "identifier" {
if current_statement.is_none() {
if let (Some(identifier), Some(r#type)) = (&current_identifier, &current_type) {
properties.insert(identifier.inner().clone(), (None, r#type.clone()));
properties.insert(identifier.clone(), (None, r#type.clone()));
}
}
@ -91,7 +88,7 @@ impl AbstractTree for StructDefinition {
};
properties.insert(
identifier.inner().clone(),
identifier.clone(),
(current_statement.clone(), r#type.clone()),
);
}
@ -110,10 +107,7 @@ impl AbstractTree for StructDefinition {
}
fn run(&self, _source: &str, context: &Context) -> Result<Value, RuntimeError> {
context.set_definition(
self.name.inner().clone(),
TypeDefinition::Struct(self.clone()),
)?;
context.set_definition(self.name.clone(), TypeDefinition::Struct(self.clone()))?;
Ok(Value::none())
}

View File

@ -1,11 +1,12 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node as SyntaxNode;
use crate::{
built_in_types::BuiltInType,
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Format, Identifier, SyntaxNode, Value,
AbstractTree, Context, Format, Identifier, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -13,10 +14,9 @@ pub enum Type {
Any,
Boolean,
Collection,
Custom(Identifier),
CustomWithArgument {
Custom {
name: Identifier,
argument: Box<Type>,
argument: Option<Box<Type>>,
},
Float,
Function {
@ -33,8 +33,15 @@ pub enum Type {
}
impl Type {
pub fn custom(name: Identifier, argument: Option<Type>) -> Self {
Type::Custom {
name,
argument: argument.map(|r#type| Box::new(r#type)),
}
}
pub fn option(inner_type: Option<Type>) -> Self {
BuiltInType::Option.get(inner_type).clone()
BuiltInType::Option(inner_type).get().clone()
}
pub fn list(item_type: Type) -> Self {
@ -75,13 +82,12 @@ impl Type {
| (Type::Integer, Type::Number)
| (Type::Float, Type::Number)
| (Type::String, Type::String) => true,
(Type::Custom(left), Type::Custom(right)) => left == right,
(
Type::CustomWithArgument {
Type::Custom {
name: left_name,
argument: left_argument,
},
Type::CustomWithArgument {
Type::Custom {
name: right_name,
argument: right_argument,
},
@ -138,7 +144,7 @@ impl AbstractTree for Type {
fn from_syntax(
node: SyntaxNode,
_source: &str,
_context: &Context,
context: &Context,
) -> Result<Self, SyntaxError> {
SyntaxError::expect_syntax_node(_source, "type", node)?;
@ -146,23 +152,18 @@ impl AbstractTree for Type {
let r#type = match type_node.kind() {
"identifier" => {
if node.child_count() == 1 {
Type::Custom(Identifier::from_syntax(type_node, _source, _context)?)
let name = Identifier::from_syntax(type_node, _source, context)?;
let argument = if let Some(child) = node.child(2) {
Some(Type::from_syntax(child, _source, context)?)
} else {
let name = Identifier::from_syntax(type_node, _source, _context)?;
None
};
let argument_node = node.child(2).unwrap();
let argument = Type::from_syntax(argument_node, _source, _context)?;
Type::CustomWithArgument {
name,
argument: Box::new(argument),
}
}
Type::custom(name, argument)
}
"[" => {
let item_type_node = node.child(1).unwrap();
let item_type = Type::from_syntax(item_type_node, _source, _context)?;
let item_type = Type::from_syntax(item_type_node, _source, context)?;
Type::List(Box::new(item_type))
}
@ -178,7 +179,7 @@ impl AbstractTree for Type {
let child = node.child(index).unwrap();
if child.is_named() {
let parameter_type = Type::from_syntax(child, _source, _context)?;
let parameter_type = Type::from_syntax(child, _source, context)?;
parameter_types.push(parameter_type);
}
@ -186,7 +187,7 @@ impl AbstractTree for Type {
let final_node = node.child(child_count - 1).unwrap();
let return_type = if final_node.is_named() {
Type::from_syntax(final_node, _source, _context)?
Type::from_syntax(final_node, _source, context)?
} else {
Type::option(None)
};
@ -233,8 +234,7 @@ impl Format for Type {
Type::Any => output.push_str("any"),
Type::Boolean => output.push_str("bool"),
Type::Collection => output.push_str("collection"),
Type::Custom(_) => todo!(),
Type::CustomWithArgument {
Type::Custom {
name: _,
argument: _,
} => todo!(),
@ -279,9 +279,12 @@ impl Display for Type {
Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"),
Type::Collection => write!(f, "collection"),
Type::Custom(identifier) => write!(f, "{identifier}"),
Type::CustomWithArgument { name, argument } => {
write!(f, "{name}<{argument}>")
Type::Custom { name, argument } => {
if let Some(argument) = argument {
write!(f, "{name}<{argument}>")
} else {
write!(f, "{name}")
}
}
Type::Float => write!(f, "float"),
Type::Function {

View File

@ -121,7 +121,7 @@ impl AbstractTree for ValueNode {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,
ValueNode::Float(_) => Type::Float,
ValueNode::Function(function) => function.r#type().clone(),
ValueNode::Function(function) => function.r#type(),
ValueNode::Integer(_) => Type::Integer,
ValueNode::String(_) => Type::String,
ValueNode::List(expressions) => {
@ -147,17 +147,20 @@ impl AbstractTree for ValueNode {
}
ValueNode::Map(_) => Type::Map,
ValueNode::Struct { name, .. } => {
Type::Custom(name.clone())
Type::Custom { name: name.clone(), argument: None }
}
ValueNode::Range(_) => Type::Range,
ValueNode::Enum { name, variant: _, expression } => {
if let Some(expression) = expression {
Type::CustomWithArgument {
Type::Custom {
name: name.clone(),
argument: Box::new(expression.expected_type(context)?)
argument: Some(Box::new(expression.expected_type(context)?))
}
} else {
Type::Custom(name.clone())
Type::Custom{
name: name.clone(),
argument: None,
}
}
},
};
@ -204,7 +207,7 @@ impl AbstractTree for ValueNode {
ValueNode::Map(map_node) => map_node.run(source, context)?,
ValueNode::Range(range) => Value::Range(range.clone()),
ValueNode::Struct { name, properties } => {
let instance = if let Some(definition) = context.get_definition(name.inner())? {
let instance = if let Some(definition) = context.get_definition(name)? {
if let TypeDefinition::Struct(struct_definition) = definition {
struct_definition.instantiate(properties, source, context)?
} else {
@ -212,7 +215,7 @@ impl AbstractTree for ValueNode {
}
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::TypeDefinitionNotFound(name.inner().clone())
ValidationError::TypeDefinitionNotFound(name.clone())
));
};
@ -225,9 +228,9 @@ impl AbstractTree for ValueNode {
} else {
Value::none()
};
let instance = if let Some(definition) = context.get_definition(name.inner())? {
let instance = if let Some(definition) = context.get_definition(name)? {
if let TypeDefinition::Enum(enum_defintion) = definition {
enum_defintion.instantiate(variant.inner().clone(), Some(value))
enum_defintion.instantiate(variant.clone(), Some(value))
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedEnumDefintion {
@ -237,7 +240,7 @@ impl AbstractTree for ValueNode {
}
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::TypeDefinitionNotFound(name.inner().clone())
ValidationError::TypeDefinitionNotFound(name.clone())
));
};

View File

@ -19,7 +19,7 @@ pub trait Callable {
&self,
arguments: &[Value],
source: &str,
outer_context: &Context,
context: &Context,
) -> Result<Value, RuntimeError>;
}
@ -72,7 +72,10 @@ impl Callable for BuiltInFunction {
match self {
BuiltInFunction::AssertEqual => Type::function(
vec![Type::Any, Type::Any],
Type::Custom(Identifier::new("Result")),
Type::Custom {
name: Identifier::new("Result"),
argument: None,
},
),
BuiltInFunction::Fs(fs_function) => fs_function.r#type(),
BuiltInFunction::Json(json_function) => json_function.r#type(),
@ -90,7 +93,7 @@ impl Callable for BuiltInFunction {
&self,
arguments: &[Value],
_source: &str,
_outer_context: &Context,
context: &Context,
) -> Result<Value, RuntimeError> {
match self {
BuiltInFunction::AssertEqual => {
@ -101,26 +104,22 @@ impl Callable for BuiltInFunction {
let result = if left == right {
Value::Enum(EnumInstance::new(
"Result".to_string(),
"Ok".to_string(),
Identifier::new("Result"),
Identifier::new("Ok"),
Some(Value::none()),
))
} else {
Value::Enum(EnumInstance::new(
"Result".to_string(),
"Error".to_string(),
Identifier::new("Result"),
Identifier::new("Error"),
Some(Value::none()),
))
};
Ok(result)
}
BuiltInFunction::Fs(fs_function) => {
fs_function.call(arguments, _source, _outer_context)
}
BuiltInFunction::Json(json_function) => {
json_function.call(arguments, _source, _outer_context)
}
BuiltInFunction::Fs(fs_function) => fs_function.call(arguments, _source, context),
BuiltInFunction::Json(json_function) => json_function.call(arguments, _source, context),
BuiltInFunction::Length => {
RuntimeError::expect_argument_amount(self.name(), 1, arguments.len())?;
@ -184,7 +183,7 @@ impl Callable for BuiltInFunction {
Ok(Value::Integer(random()))
}
BuiltInFunction::String(string_function) => {
string_function.call(arguments, _source, _outer_context)
string_function.call(arguments, _source, context)
}
}
}

View File

@ -1,7 +1,7 @@
use enum_iterator::Sequence;
use serde::{Deserialize, Serialize};
use crate::{error::RuntimeError, Context, EnumInstance, List, Type, Value};
use crate::{error::RuntimeError, Context, EnumInstance, Identifier, List, Type, Value};
use super::Callable;
@ -203,7 +203,7 @@ impl Callable for StrFunction {
&self,
arguments: &[Value],
_source: &str,
_outer_context: &Context,
context: &Context,
) -> Result<Value, RuntimeError> {
let value = match self {
StrFunction::AsBytes => {
@ -238,14 +238,14 @@ impl Callable for StrFunction {
if let Some(index) = find {
Value::Enum(EnumInstance::new(
"Option".to_string(),
"Some".to_string(),
Identifier::new("Option"),
Identifier::new("Some"),
Some(index),
))
} else {
Value::Enum(EnumInstance::new(
"Option".to_string(),
"None".to_string(),
Identifier::new("Option"),
Identifier::new("None"),
Some(Value::none()),
))
}
@ -477,8 +477,8 @@ impl Callable for StrFunction {
if let Some(value) = stripped {
Value::Enum(EnumInstance::new(
"Option".to_string(),
"Some".to_string(),
Identifier::new("Option"),
Identifier::new("Some"),
Some(value),
))
} else {

View File

@ -0,0 +1,29 @@
use std::sync::OnceLock;
use enum_iterator::{all, Sequence};
use crate::Identifier;
pub fn all_built_in_identifiers() -> impl Iterator<Item = BuiltInIdentifier> {
all()
}
const OPTION: OnceLock<Identifier> = OnceLock::new();
const NONE: OnceLock<Identifier> = OnceLock::new();
#[derive(Sequence)]
pub enum BuiltInIdentifier {
Option,
None,
}
impl BuiltInIdentifier {
pub fn get(&self) -> &Identifier {
match self {
BuiltInIdentifier::Option => {
return OPTION.get_or_init(|| Identifier::new("Option"));
}
BuiltInIdentifier::None => return NONE.get_or_init(|| Identifier::new("None")),
}
}
}

View File

@ -2,10 +2,13 @@ use std::sync::OnceLock;
use enum_iterator::{all, Sequence};
use crate::{EnumDefinition, Identifier, Type, TypeDefinition, VariantContent};
use crate::{
error::rw_lock_error::RwLockError, Context, EnumDefinition, Identifier, Type, TypeDefinition,
VariantContent,
};
static OPTION: OnceLock<TypeDefinition> = OnceLock::new();
static RESULT: OnceLock<TypeDefinition> = OnceLock::new();
static OPTION: OnceLock<Result<TypeDefinition, RwLockError>> = OnceLock::new();
static RESULT: OnceLock<Result<TypeDefinition, RwLockError>> = OnceLock::new();
pub fn all_built_in_type_definitions() -> impl Iterator<Item = BuiltInTypeDefinition> {
all()
@ -25,25 +28,29 @@ impl BuiltInTypeDefinition {
}
}
pub fn get(&self) -> &TypeDefinition {
pub fn get(&self, context: &Context) -> &Result<TypeDefinition, RwLockError> {
match self {
BuiltInTypeDefinition::Option => OPTION.get_or_init(|| {
TypeDefinition::Enum(EnumDefinition::new(
let definition = TypeDefinition::Enum(EnumDefinition::new(
Identifier::new(self.name()),
vec![
(Identifier::new("Some"), VariantContent::Type(Type::Any)),
(Identifier::new("None"), VariantContent::None),
],
))
));
Ok(definition)
}),
BuiltInTypeDefinition::Result => RESULT.get_or_init(|| {
TypeDefinition::Enum(EnumDefinition::new(
let definition = TypeDefinition::Enum(EnumDefinition::new(
Identifier::new(self.name()),
vec![
(Identifier::new("Ok"), VariantContent::Type(Type::Any)),
(Identifier::new("Err"), VariantContent::Type(Type::Any)),
],
))
));
Ok(definition)
}),
}
}

View File

@ -1,34 +1,33 @@
use std::sync::OnceLock;
use enum_iterator::Sequence;
use serde::{Deserialize, Serialize};
use crate::{Identifier, Type};
static OPTION: OnceLock<Type> = OnceLock::new();
#[derive(Sequence, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInType {
Option,
Option(Option<Type>),
}
impl BuiltInType {
pub fn name(&self) -> &'static str {
match self {
BuiltInType::Option => todo!(),
BuiltInType::Option(_) => "Option",
}
}
pub fn get(&self, inner_type: Option<Type>) -> &Type {
pub fn get(&self) -> &Type {
match self {
BuiltInType::Option => OPTION.get_or_init(|| {
if let Some(inner_type) = inner_type {
Type::CustomWithArgument {
BuiltInType::Option(content_type) => OPTION.get_or_init(|| {
if let Some(content_type) = content_type {
Type::Custom {
name: Identifier::new("Option"),
argument: Box::new(inner_type),
argument: Some(Box::new(content_type.clone())),
}
} else {
Type::Custom(Identifier::new("Option"))
Type::Custom {
name: Identifier::new("Option"),
argument: None,
}
}
}),
}

View File

@ -1,21 +1,19 @@
use std::{collections::BTreeMap, env::args, sync::OnceLock};
use std::{env::args, sync::OnceLock};
use enum_iterator::{all, Sequence};
use serde::{Deserialize, Serialize};
use crate::{
built_in_functions::{fs::fs_functions, json::json_functions, str::string_functions, Callable},
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, BuiltInFunction, Context, EnumInstance, Format, Function, Identifier, List, Map,
SyntaxNode, Type, Value,
BuiltInFunction, EnumInstance, Function, Identifier, List, Map, Value,
};
static ARGS: OnceLock<Value> = OnceLock::new();
static FS: OnceLock<Value> = OnceLock::new();
static JSON: OnceLock<Value> = OnceLock::new();
static RANDOM: OnceLock<Value> = OnceLock::new();
static STRING: OnceLock<Value> = OnceLock::new();
static NONE: OnceLock<Value> = OnceLock::new();
static RANDOM: OnceLock<Value> = OnceLock::new();
static STR: OnceLock<Value> = OnceLock::new();
/// Returns the entire built-in value API.
pub fn all_built_in_values() -> impl Iterator<Item = BuiltInValue> {
@ -86,23 +84,6 @@ impl BuiltInValue {
}
}
/// Returns the value's type.
///
/// This is checked with a unit test to ensure it matches the value.
pub fn r#type(&self) -> Type {
match self {
BuiltInValue::Args => Type::list(Type::String),
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
BuiltInValue::Fs => Type::Map,
BuiltInValue::Json => Type::Map,
BuiltInValue::Length => BuiltInFunction::Length.r#type(),
BuiltInValue::None => Type::Custom(Identifier::new("Option")),
BuiltInValue::Output => BuiltInFunction::Output.r#type(),
BuiltInValue::Random => Type::Map,
BuiltInValue::Str => Type::Map,
}
}
/// Returns the value by creating it or, if it has already been accessed, retrieving it from its
/// [OnceLock][].
pub fn get(&self) -> &Value {
@ -116,42 +97,40 @@ impl BuiltInValue {
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
}
BuiltInValue::Fs => FS.get_or_init(|| {
let mut fs_context = BTreeMap::new();
let mut fs_map = Map::new();
for fs_function in fs_functions() {
let key = fs_function.name().to_string();
let key = fs_function.name();
let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function)));
fs_context.insert(key, value);
fs_map.set(Identifier::new(key), value);
}
Value::Map(Map::with_values(fs_context))
Value::Map(fs_map)
}),
BuiltInValue::Json => JSON.get_or_init(|| {
let mut json_context = BTreeMap::new();
let mut json_map = Map::new();
for json_function in json_functions() {
let key = json_function.name().to_string();
let key = json_function.name();
let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function)));
json_context.insert(key, value);
json_map.set(Identifier::new(key), value);
}
Value::Map(Map::with_values(json_context))
Value::Map(json_map)
}),
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::None => NONE.get_or_init(|| {
Value::Enum(EnumInstance::new(
"Option".to_string(),
"None".to_string(),
None,
))
}),
BuiltInValue::None => &Value::Enum(EnumInstance::new(
Identifier::new("Option"),
Identifier::new("None"),
None,
)),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)),
BuiltInValue::Random => RANDOM.get_or_init(|| {
let mut random_context = BTreeMap::new();
let mut random_map = Map::new();
for built_in_function in [
BuiltInFunction::RandomBoolean,
@ -159,83 +138,28 @@ impl BuiltInValue {
BuiltInFunction::RandomFrom,
BuiltInFunction::RandomInteger,
] {
let key = built_in_function.name().to_string();
let identifier = Identifier::new(built_in_function.name());
let value = Value::Function(Function::BuiltIn(built_in_function));
random_context.insert(key, value);
random_map.set(identifier, value);
}
Value::Map(Map::with_values(random_context))
Value::Map(random_map)
}),
BuiltInValue::Str => STRING.get_or_init(|| {
let mut string_context = BTreeMap::new();
BuiltInValue::Str => STR.get_or_init(|| {
let mut str_map = Map::new();
for string_function in string_functions() {
let key = string_function.name().to_string();
let identifier = Identifier::new(string_function.name());
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function,
)));
string_context.insert(key, value);
str_map.set(identifier, value);
}
Value::Map(Map::with_values(string_context))
Value::Map(str_map)
}),
}
}
}
impl AbstractTree for BuiltInValue {
fn from_syntax(
node: SyntaxNode,
_source: &str,
_context: &Context,
) -> Result<Self, SyntaxError> {
let built_in_value = match node.kind() {
"args" => BuiltInValue::Args,
"assert_equal" => BuiltInValue::AssertEqual,
"fs" => BuiltInValue::Fs,
"json" => BuiltInValue::Json,
"length" => BuiltInValue::Length,
"output" => BuiltInValue::Output,
"random" => BuiltInValue::Random,
"str" => BuiltInValue::Str,
_ => todo!(),
};
Ok(built_in_value)
}
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(self.r#type())
}
fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> {
Ok(())
}
fn run(&self, _source: &str, _context: &Context) -> Result<Value, RuntimeError> {
Ok(self.get().clone())
}
}
impl Format for BuiltInValue {
fn format(&self, output: &mut String, _indent_level: u8) {
output.push_str(&self.get().to_string());
}
}
#[cfg(test)]
mod tests {
use super::all_built_in_values;
#[test]
fn check_built_in_types() {
for built_in_value in all_built_in_values() {
let expected = built_in_value.r#type();
let actual = built_in_value.get().r#type();
assert_eq!(expected, actual);
}
}
}

View File

@ -35,7 +35,7 @@ use std::{
use crate::{
built_in_type_definitions::all_built_in_type_definitions, built_in_values::all_built_in_values,
error::rw_lock_error::RwLockError, Type, TypeDefinition, Value,
error::rw_lock_error::RwLockError, Identifier, Type, TypeDefinition, Value,
};
/// An execution context that variable and type data during the [Interpreter]'s
@ -44,7 +44,7 @@ use crate::{
/// See the [module-level docs][self] for more info.
#[derive(Clone, Debug)]
pub struct Context {
inner: Arc<RwLock<BTreeMap<String, ValueData>>>,
inner: Arc<RwLock<BTreeMap<Identifier, ValueData>>>,
}
impl Context {
@ -56,7 +56,7 @@ impl Context {
}
/// Return a lock guard to the inner BTreeMap.
pub fn inner(&self) -> Result<RwLockReadGuard<BTreeMap<String, ValueData>>, RwLockError> {
pub fn inner(&self) -> Result<RwLockReadGuard<BTreeMap<Identifier, ValueData>>, RwLockError> {
Ok(self.inner.read()?)
}
@ -112,15 +112,15 @@ impl Context {
///
/// This will also return a built-in value if one matches the key. See the
/// [module-level docs][self] for more info.
pub fn get_value(&self, key: &str) -> Result<Option<Value>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(key) {
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(identifier) {
if let ValueData::Value { inner, .. } = value_data {
return Ok(Some(inner.clone()));
}
}
for built_in_value in all_built_in_values() {
if key == built_in_value.name() {
if built_in_value.name() == identifier.inner().as_ref() {
return Ok(Some(built_in_value.get().clone()));
}
}
@ -132,8 +132,8 @@ impl Context {
///
/// If the key matches a stored value, its type will be returned. It if
/// matches a type hint, the type hint will be returned.
pub fn get_type(&self, key: &str) -> Result<Option<Type>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(key) {
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(identifier) {
match value_data {
ValueData::Value { inner, .. } => return Ok(Some(inner.r#type())),
ValueData::TypeHint { inner, .. } => return Ok(Some(inner.clone())),
@ -141,12 +141,6 @@ impl Context {
}
}
for built_in_value in all_built_in_values() {
if key == built_in_value.name() {
return Ok(Some(built_in_value.r#type()));
}
}
Ok(None)
}
@ -154,16 +148,19 @@ impl Context {
///
/// This will also return a built-in type definition if one matches the key.
/// See the [module-level docs][self] for more info.
pub fn get_definition(&self, key: &str) -> Result<Option<TypeDefinition>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(key) {
pub fn get_definition(
&self,
identifier: &Identifier,
) -> Result<Option<TypeDefinition>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(identifier) {
if let ValueData::TypeDefinition(definition) = value_data {
return Ok(Some(definition.clone()));
}
}
for built_in_definition in all_built_in_type_definitions() {
if key == built_in_definition.name() {
return Ok(Some(built_in_definition.get().clone()));
if built_in_definition.name() == identifier.inner().as_ref() {
return Ok(Some(built_in_definition.get(self).clone()?));
}
}
@ -171,7 +168,7 @@ impl Context {
}
/// Set a value to a key.
pub fn set_value(&self, key: String, value: Value) -> Result<(), RwLockError> {
pub fn set_value(&self, key: Identifier, value: Value) -> Result<(), RwLockError> {
self.inner.write()?.insert(
key,
ValueData::Value {
@ -187,7 +184,7 @@ impl Context {
///
/// This allows the interpreter to check a value's type before the value
/// actually exists by predicting what the abstract tree will produce.
pub fn set_type(&self, key: String, r#type: Type) -> Result<(), RwLockError> {
pub fn set_type(&self, key: Identifier, r#type: Type) -> Result<(), RwLockError> {
self.inner
.write()?
.insert(key, ValueData::TypeHint { inner: r#type });
@ -201,7 +198,7 @@ impl Context {
/// later while using this context.
pub fn set_definition(
&self,
key: String,
key: Identifier,
definition: TypeDefinition,
) -> Result<(), RwLockError> {
self.inner
@ -212,7 +209,7 @@ impl Context {
}
/// Remove a key-value pair.
pub fn unset(&self, key: &str) -> Result<(), RwLockError> {
pub fn unset(&self, key: &Identifier) -> Result<(), RwLockError> {
self.inner.write()?.remove(key);
Ok(())

View File

@ -7,7 +7,7 @@ use std::{
time,
};
use crate::{Type, Value};
use crate::{Identifier, Type, Value};
use super::{rw_lock_error::RwLockError, ValidationError};
@ -106,7 +106,7 @@ pub enum RuntimeError {
Utf8(FromUtf8Error),
/// Failed to find a variable with a value for this key.
VariableIdentifierNotFound(String),
VariableIdentifierNotFound(Identifier),
/// A built-in function was called with the wrong amount of arguments.
ExpectedBuiltInFunctionArgumentAmount {

View File

@ -65,7 +65,7 @@ pub enum ValidationError {
VariableIdentifierNotFound(Identifier),
/// Failed to find a type definition with this key.
TypeDefinitionNotFound(String),
TypeDefinitionNotFound(Identifier),
/// Failed to find an enum definition with this key.
ExpectedEnumDefintion { actual: TypeDefinition },

View File

@ -17,6 +17,7 @@ pub use tree_sitter::Node as SyntaxNode;
pub mod abstract_tree;
pub mod built_in_functions;
pub mod built_in_identifiers;
pub mod built_in_type_definitions;
pub mod built_in_types;
pub mod built_in_values;

View File

@ -2,30 +2,30 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::Value;
use crate::{Identifier, Value};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumInstance {
name: String,
variant_name: String,
name: Identifier,
variant: Identifier,
value: Option<Box<Value>>,
}
impl EnumInstance {
pub fn new(name: String, variant_name: String, value: Option<Value>) -> Self {
pub fn new(name: Identifier, variant_name: Identifier, value: Option<Value>) -> Self {
Self {
name,
variant_name,
variant: variant_name,
value: value.map(|value| Box::new(value)),
}
}
pub fn name(&self) -> &String {
pub fn name(&self) -> &Identifier {
&self.name
}
pub fn variant_name(&self) -> &String {
&self.variant_name
pub fn variant(&self) -> &Identifier {
&self.variant
}
pub fn value(&self) -> &Option<Box<Value>> {
@ -35,6 +35,6 @@ impl EnumInstance {
impl Display for EnumInstance {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}::{}({:?})", self.name, self.variant_name, self.value)
write!(f, "{}::{}({:?})", self.name, self.variant, self.value)
}
}

View File

@ -1,8 +1,4 @@
use std::{
cmp::Ordering,
fmt::{self, Display, Formatter},
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use std::fmt::{self, Display, Formatter};
use stanza::{
renderer::{console::Console, Renderer},
@ -12,8 +8,8 @@ use stanza::{
use crate::Value;
#[derive(Debug, Clone)]
pub struct List(Arc<RwLock<Vec<Value>>>);
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct List(Vec<Value>);
impl Default for List {
fn default() -> Self {
@ -23,23 +19,23 @@ impl Default for List {
impl List {
pub fn new() -> Self {
List(Arc::new(RwLock::new(Vec::new())))
List(Vec::new())
}
pub fn with_capacity(capacity: usize) -> Self {
List(Arc::new(RwLock::new(Vec::with_capacity(capacity))))
List(Vec::with_capacity(capacity))
}
pub fn with_items(items: Vec<Value>) -> Self {
List(Arc::new(RwLock::new(items)))
List(items)
}
pub fn items(&self) -> RwLockReadGuard<'_, Vec<Value>> {
self.0.read().unwrap()
pub fn items(&self) -> &Vec<Value> {
&self.0
}
pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec<Value>> {
self.0.write().unwrap()
pub fn items_mut(&mut self) -> &mut Vec<Value> {
&mut self.0
}
pub fn as_text_table(&self) -> Table {
@ -73,32 +69,6 @@ impl List {
}
}
impl Eq for List {}
impl PartialEq for List {
fn eq(&self, other: &Self) -> bool {
let left = self.0.read().unwrap().clone().into_iter();
let right = other.0.read().unwrap().clone().into_iter();
left.eq(right)
}
}
impl Ord for List {
fn cmp(&self, other: &Self) -> Ordering {
let left = self.0.read().unwrap().clone().into_iter();
let right = other.0.read().unwrap().clone().into_iter();
left.cmp(right)
}
}
impl PartialOrd for List {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Display for List {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let renderer = Console::default();

View File

@ -9,7 +9,7 @@ use std::{
fmt::{self, Display, Formatter},
};
use crate::value::Value;
use crate::{Identifier, Value};
/// A collection dust variables comprised of key-value pairs.
///
@ -17,7 +17,7 @@ use crate::value::Value;
/// to one another.
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Map {
inner: BTreeMap<String, Value>,
inner: BTreeMap<Identifier, Value>,
}
impl Map {
@ -28,19 +28,19 @@ impl Map {
}
}
pub fn with_values(variables: BTreeMap<String, Value>) -> Self {
pub fn with_values(variables: BTreeMap<Identifier, Value>) -> Self {
Map { inner: variables }
}
pub fn inner(&self) -> &BTreeMap<String, Value> {
pub fn inner(&self) -> &BTreeMap<Identifier, Value> {
&self.inner
}
pub fn get(&self, key: &str) -> Option<&Value> {
pub fn get(&self, key: &Identifier) -> Option<&Value> {
self.inner.get(key)
}
pub fn set(&mut self, key: String, value: Value) {
pub fn set(&mut self, key: Identifier, value: Value) {
self.inner.insert(key, value);
}
@ -63,7 +63,7 @@ impl Map {
vec![key.into(), list.as_text_table().into()],
));
} else {
table.push_row([key, &value.to_string()]);
table.push_row([key.to_string(), value.to_string()]);
};
}

View File

@ -11,7 +11,6 @@ use serde::{
use std::{
cmp::Ordering,
collections::BTreeMap,
convert::TryFrom,
fmt::{self, Display, Formatter},
marker::PhantomData,
@ -55,8 +54,8 @@ impl Value {
pub fn some(value: Value) -> Value {
Value::Enum(EnumInstance::new(
"Option".to_string(),
"Some".to_string(),
Identifier::new("Option"),
Identifier::new("Some"),
Some(value),
))
}
@ -97,7 +96,7 @@ impl Value {
for (key, value) in map.inner() {
identifier_types.push((
Identifier::new(key.clone()),
Identifier::new(key.inner()),
TypeSpecification::new(value.r#type()),
));
}
@ -828,13 +827,15 @@ impl<'de> Visitor<'de> for ValueVisitor {
where
M: MapAccess<'de>,
{
let mut map = BTreeMap::new();
let mut map = Map::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.insert(key, value);
let identifier = Identifier::new(&key);
map.set(identifier, value);
}
Ok(Value::Map(Map::with_values(map)))
Ok(Value::Map(map))
}
fn visit_enum<A>(self, data: A) -> std::result::Result<Self::Value, A::Error>

View File

@ -2,16 +2,16 @@ use std::fmt::{self, Display, Formatter};
use serde::{ser::SerializeMap, Serialize, Serializer};
use crate::Map;
use crate::{Identifier, Map};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructInstance {
name: String,
name: Identifier,
map: Map,
}
impl StructInstance {
pub fn new(name: String, map: Map) -> Self {
pub fn new(name: Identifier, map: Map) -> Self {
StructInstance { name, map }
}
}

View File

@ -138,7 +138,7 @@ fn function() {
};
assert_eq!(
&vec![Identifier::new("x".to_string())],
&vec![Identifier::new_or_get("x".to_string())],
function.parameters()
);
assert_eq!(&Type::Boolean, function.return_type());