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> { fn validate(&self, source: &str, context: &Context) -> Result<(), ValidationError> {
if let AssignmentOperator::Equal = self.operator { if let AssignmentOperator::Equal = self.operator {
let key = self.identifier.inner().clone();
let r#type = if let Some(definition) = &self.type_specification { let r#type = if let Some(definition) = &self.type_specification {
definition.inner().clone() definition.inner().clone()
} else { } else {
self.statement.expected_type(context)? 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 { 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> { fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let key = self.identifier.inner();
let value = self.statement.run(source, context)?; let value = self.statement.run(source, context)?;
let new_value = match self.operator { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { 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 += value;
previous_value previous_value
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound(key.clone())); return Err(RuntimeError::VariableIdentifierNotFound(
self.identifier.clone(),
));
} }
} }
AssignmentOperator::MinusEqual => { 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 -= value;
previous_value previous_value
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound(key.clone())); return Err(RuntimeError::VariableIdentifierNotFound(
self.identifier.clone(),
));
} }
} }
AssignmentOperator::Equal => value, AssignmentOperator::Equal => value,
}; };
context.set_value(key.clone(), new_value)?; context.set_value(self.identifier.clone(), new_value)?;
Ok(Value::none()) Ok(Value::none())
} }

View File

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

View File

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

View File

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

View File

@ -118,7 +118,7 @@ impl AbstractTree for FunctionNode {
let validation_context = Context::new(); let validation_context = Context::new();
for (parameter, r#type) in self.parameters.iter().zip(parameter_types.iter()) { 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)?; 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::{ use crate::{
built_in_identifiers::all_built_in_identifiers,
error::{RuntimeError, SyntaxError, ValidationError}, error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Format, SyntaxNode, Type, Value, AbstractTree, Context, Format, SyntaxNode, Type, Value,
}; };
@ -10,22 +14,30 @@ use crate::{
/// A string by which a variable is known to a context. /// 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 /// 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. /// pair and can be used to retrieve a Value instance from a Map or Context.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Identifier(String); pub struct Identifier(Arc<String>);
impl Identifier { impl Identifier {
pub fn new<T: Into<String>>(inner: T) -> Self { pub fn new(key: &str) -> Self {
Identifier(inner.into()) 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 { pub fn inner(&self) -> &Arc<String> {
self.0
}
pub fn inner(&self) -> &String {
&self.0 &self.0
} }
pub fn contains(&self, string: &str) -> bool {
self.0.as_ref() == string
}
} }
impl AbstractTree for Identifier { impl AbstractTree for Identifier {
@ -40,7 +52,7 @@ impl AbstractTree for Identifier {
debug_assert!(!text.is_empty()); debug_assert!(!text.is_empty());
Ok(Identifier(text.to_string())) Ok(Identifier::new(text))
} }
fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { 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> { 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) Ok(r#type)
} else { } else {
Err(ValidationError::VariableIdentifierNotFound(self.clone())) Err(ValidationError::VariableIdentifierNotFound(self.clone()))
@ -56,10 +68,10 @@ impl AbstractTree for Identifier {
} }
fn run(&self, _source: &str, context: &Context) -> Result<Value, RuntimeError> { 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()) Ok(value.clone())
} else { } else {
Err(RuntimeError::VariableIdentifierNotFound(self.0.clone())) Err(RuntimeError::VariableIdentifierNotFound(self.clone()))
} }
} }
} }
@ -75,3 +87,38 @@ impl Display for Identifier {
write!(f, "{}", self.0) 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::{ use crate::{
error::{RuntimeError, SyntaxError, ValidationError}, 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. /// Abstract representation of an index expression.
@ -12,7 +13,6 @@ use crate::{
pub struct Index { pub struct Index {
pub collection: IndexExpression, pub collection: IndexExpression,
pub index: IndexExpression, pub index: IndexExpression,
pub index_end: Option<IndexExpression>,
source_position: SourcePosition, source_position: SourcePosition,
} }
@ -26,21 +26,9 @@ impl AbstractTree for Index {
let index_node = node.child(2).unwrap(); let index_node = node.child(2).unwrap();
let index = IndexExpression::from_syntax(index_node, source, context)?; 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 { Ok(Index {
collection, collection,
index, index,
index_end,
source_position: SourcePosition::from(node.range()), source_position: SourcePosition::from(node.range()),
}) })
} }
@ -58,10 +46,6 @@ impl AbstractTree for Index {
self.collection.validate(_source, _context)?; self.collection.validate(_source, _context)?;
self.index.validate(_source, _context)?; self.index.validate(_source, _context)?;
if let Some(index_end) = &self.index_end {
index_end.validate(_source, _context)?;
}
Ok(()) Ok(())
} }
@ -71,36 +55,28 @@ impl AbstractTree for Index {
match value { match value {
Value::List(list) => { Value::List(list) => {
let index = self.index.run(source, context)?.as_integer()? as usize; let index = self.index.run(source, context)?.as_integer()? as usize;
let item = list.items().get(index).cloned().unwrap_or_default();
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()
};
Ok(item) Ok(item)
} }
Value::Map(map) => { Value::Map(map) => {
let map = map.inner(); let map = map.inner();
let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index { let (identifier, value) =
let key = identifier.inner(); if let IndexExpression::Identifier(identifier) = &self.index {
let value = map.get(key).unwrap_or_default(); let value = map.get(identifier).unwrap_or_default();
(key.clone(), value) (identifier.clone(), value)
} else { } else {
let index_value = self.index.run(source, context)?; let index_value = self.index.run(source, context)?;
let key = index_value.as_string()?; let identifier = Identifier::new(index_value.as_string()?);
let value = map.get(key.as_str()).unwrap_or_default(); let value = map.get(&identifier).unwrap_or_default();
(key.clone(), value) (identifier, value)
}; };
if value.is_none() { if value.is_none() {
Err(RuntimeError::VariableIdentifierNotFound(key)) Err(RuntimeError::VariableIdentifierNotFound(identifier))
} else { } else {
Ok(value.clone()) Ok(value.clone())
} }
@ -121,10 +97,5 @@ impl Format for Index {
self.collection.format(output, indent_level); self.collection.format(output, indent_level);
output.push(':'); output.push(':');
self.index.format(output, indent_level); 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::{ use crate::{
error::{RuntimeError, SyntaxError, ValidationError}, error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, AssignmentOperator, Context, Format, Index, IndexExpression, Statement, AbstractTree, AssignmentOperator, Context, Format, Identifier, Index, IndexExpression,
SyntaxNode, Type, Value, Statement, SyntaxNode, Type, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[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> { fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let _index_collection = self.index.collection.run(source, context)?; let _index_collection = self.index.collection.run(source, context)?;
let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index { let index_identifier = if let IndexExpression::Identifier(identifier) = &self.index.index {
identifier.inner() identifier
} else { } else {
let index_run = self.index.index.run(source, context)?;
let expected_identifier = Identifier::new(index_run.as_string()?);
return Err(RuntimeError::VariableIdentifierNotFound( 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 { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { 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 += value;
previous_value previous_value
} else { } else {
@ -64,7 +67,7 @@ impl AbstractTree for IndexAssignment {
} }
} }
AssignmentOperator::MinusEqual => { 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 -= value;
previous_value previous_value
} else { } else {
@ -74,7 +77,7 @@ impl AbstractTree for IndexAssignment {
AssignmentOperator::Equal => value, AssignmentOperator::Equal => value,
}; };
context.set_value(index_key.clone(), new_value)?; context.set_value(index_identifier.clone(), new_value)?;
Ok(Value::none()) Ok(Value::none())
} }

View File

@ -11,12 +11,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct MapNode { pub struct MapNode {
properties: BTreeMap<String, (Statement, Option<Type>)>, properties: BTreeMap<Identifier, (Statement, Option<Type>)>,
position: SourcePosition, position: SourcePosition,
} }
impl MapNode { impl MapNode {
pub fn properties(&self) -> &BTreeMap<String, (Statement, Option<Type>)> { pub fn properties(&self) -> &BTreeMap<Identifier, (Statement, Option<Type>)> {
&self.properties &self.properties
} }
} }
@ -26,14 +26,14 @@ impl AbstractTree for MapNode {
SyntaxError::expect_syntax_node(source, "map", node)?; SyntaxError::expect_syntax_node(source, "map", node)?;
let mut properties = BTreeMap::new(); let mut properties = BTreeMap::new();
let mut current_key = "".to_string(); let mut current_identifier = None;
let mut current_type = None; let mut current_type = None;
for index in 0..node.child_count() - 1 { for index in 0..node.child_count() - 1 {
let child = node.child(index).unwrap(); let child = node.child(index).unwrap();
if child.kind() == "identifier" { 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; current_type = None;
} }
@ -45,7 +45,9 @@ impl AbstractTree for MapNode {
if child.kind() == "statement" { if child.kind() == "statement" {
let statement = Statement::from_syntax(child, source, context)?; 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)) = if let (Value::Enum(enum_instance), MatchPattern::EnumPattern(enum_pattern)) =
(&matcher_value, pattern) (&matcher_value, pattern)
{ {
if enum_instance.name() == enum_pattern.name().inner() if enum_instance.name() == enum_pattern.name()
&& enum_instance.variant_name() == enum_pattern.variant().inner() && enum_instance.variant() == enum_pattern.variant()
{ {
let statement_context = Context::with_variables_from(context)?; let statement_context = Context::with_variables_from(context)?;
if let (Some(identifier), Some(value)) = if let (Some(identifier), Some(value)) =
(enum_pattern.inner_identifier(), enum_instance.value()) (enum_pattern.inner_identifier(), enum_instance.value())
{ {
statement_context statement_context.set_value(identifier.clone(), value.as_ref().clone())?;
.set_value(identifier.inner().clone(), value.as_ref().clone())?;
} }
return statement.run(source, &statement_context); return statement.run(source, &statement_context);

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ pub trait Callable {
&self, &self,
arguments: &[Value], arguments: &[Value],
source: &str, source: &str,
outer_context: &Context, context: &Context,
) -> Result<Value, RuntimeError>; ) -> Result<Value, RuntimeError>;
} }
@ -72,7 +72,10 @@ impl Callable for BuiltInFunction {
match self { match self {
BuiltInFunction::AssertEqual => Type::function( BuiltInFunction::AssertEqual => Type::function(
vec![Type::Any, Type::Any], 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::Fs(fs_function) => fs_function.r#type(),
BuiltInFunction::Json(json_function) => json_function.r#type(), BuiltInFunction::Json(json_function) => json_function.r#type(),
@ -90,7 +93,7 @@ impl Callable for BuiltInFunction {
&self, &self,
arguments: &[Value], arguments: &[Value],
_source: &str, _source: &str,
_outer_context: &Context, context: &Context,
) -> Result<Value, RuntimeError> { ) -> Result<Value, RuntimeError> {
match self { match self {
BuiltInFunction::AssertEqual => { BuiltInFunction::AssertEqual => {
@ -101,26 +104,22 @@ impl Callable for BuiltInFunction {
let result = if left == right { let result = if left == right {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Ok".to_string(), Identifier::new("Ok"),
Some(Value::none()), Some(Value::none()),
)) ))
} else { } else {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Error".to_string(), Identifier::new("Error"),
Some(Value::none()), Some(Value::none()),
)) ))
}; };
Ok(result) Ok(result)
} }
BuiltInFunction::Fs(fs_function) => { BuiltInFunction::Fs(fs_function) => fs_function.call(arguments, _source, context),
fs_function.call(arguments, _source, _outer_context) BuiltInFunction::Json(json_function) => json_function.call(arguments, _source, context),
}
BuiltInFunction::Json(json_function) => {
json_function.call(arguments, _source, _outer_context)
}
BuiltInFunction::Length => { BuiltInFunction::Length => {
RuntimeError::expect_argument_amount(self.name(), 1, arguments.len())?; RuntimeError::expect_argument_amount(self.name(), 1, arguments.len())?;
@ -184,7 +183,7 @@ impl Callable for BuiltInFunction {
Ok(Value::Integer(random())) Ok(Value::Integer(random()))
} }
BuiltInFunction::String(string_function) => { 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 enum_iterator::Sequence;
use serde::{Deserialize, Serialize}; 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; use super::Callable;
@ -203,7 +203,7 @@ impl Callable for StrFunction {
&self, &self,
arguments: &[Value], arguments: &[Value],
_source: &str, _source: &str,
_outer_context: &Context, context: &Context,
) -> Result<Value, RuntimeError> { ) -> Result<Value, RuntimeError> {
let value = match self { let value = match self {
StrFunction::AsBytes => { StrFunction::AsBytes => {
@ -238,14 +238,14 @@ impl Callable for StrFunction {
if let Some(index) = find { if let Some(index) = find {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"Some".to_string(), Identifier::new("Some"),
Some(index), Some(index),
)) ))
} else { } else {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"None".to_string(), Identifier::new("None"),
Some(Value::none()), Some(Value::none()),
)) ))
} }
@ -477,8 +477,8 @@ impl Callable for StrFunction {
if let Some(value) = stripped { if let Some(value) = stripped {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"Some".to_string(), Identifier::new("Some"),
Some(value), Some(value),
)) ))
} else { } 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 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 OPTION: OnceLock<Result<TypeDefinition, RwLockError>> = OnceLock::new();
static RESULT: OnceLock<TypeDefinition> = OnceLock::new(); static RESULT: OnceLock<Result<TypeDefinition, RwLockError>> = OnceLock::new();
pub fn all_built_in_type_definitions() -> impl Iterator<Item = BuiltInTypeDefinition> { pub fn all_built_in_type_definitions() -> impl Iterator<Item = BuiltInTypeDefinition> {
all() all()
@ -25,25 +28,29 @@ impl BuiltInTypeDefinition {
} }
} }
pub fn get(&self) -> &TypeDefinition { pub fn get(&self, context: &Context) -> &Result<TypeDefinition, RwLockError> {
match self { match self {
BuiltInTypeDefinition::Option => OPTION.get_or_init(|| { BuiltInTypeDefinition::Option => OPTION.get_or_init(|| {
TypeDefinition::Enum(EnumDefinition::new( let definition = TypeDefinition::Enum(EnumDefinition::new(
Identifier::new(self.name()), Identifier::new(self.name()),
vec![ vec![
(Identifier::new("Some"), VariantContent::Type(Type::Any)), (Identifier::new("Some"), VariantContent::Type(Type::Any)),
(Identifier::new("None"), VariantContent::None), (Identifier::new("None"), VariantContent::None),
], ],
)) ));
Ok(definition)
}), }),
BuiltInTypeDefinition::Result => RESULT.get_or_init(|| { BuiltInTypeDefinition::Result => RESULT.get_or_init(|| {
TypeDefinition::Enum(EnumDefinition::new( let definition = TypeDefinition::Enum(EnumDefinition::new(
Identifier::new(self.name()), Identifier::new(self.name()),
vec![ vec![
(Identifier::new("Ok"), VariantContent::Type(Type::Any)), (Identifier::new("Ok"), VariantContent::Type(Type::Any)),
(Identifier::new("Err"), VariantContent::Type(Type::Any)), (Identifier::new("Err"), VariantContent::Type(Type::Any)),
], ],
)) ));
Ok(definition)
}), }),
} }
} }

View File

@ -1,34 +1,33 @@
use std::sync::OnceLock; use std::sync::OnceLock;
use enum_iterator::Sequence;
use serde::{Deserialize, Serialize};
use crate::{Identifier, Type}; use crate::{Identifier, Type};
static OPTION: OnceLock<Type> = OnceLock::new(); static OPTION: OnceLock<Type> = OnceLock::new();
#[derive(Sequence, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInType { pub enum BuiltInType {
Option, Option(Option<Type>),
} }
impl BuiltInType { impl BuiltInType {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
match self { match self {
BuiltInType::Option => todo!(), BuiltInType::Option(_) => "Option",
} }
} }
pub fn get(&self, inner_type: Option<Type>) -> &Type { pub fn get(&self) -> &Type {
match self { match self {
BuiltInType::Option => OPTION.get_or_init(|| { BuiltInType::Option(content_type) => OPTION.get_or_init(|| {
if let Some(inner_type) = inner_type { if let Some(content_type) = content_type {
Type::CustomWithArgument { Type::Custom {
name: Identifier::new("Option"), name: Identifier::new("Option"),
argument: Box::new(inner_type), argument: Some(Box::new(content_type.clone())),
} }
} else { } 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 enum_iterator::{all, Sequence};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
built_in_functions::{fs::fs_functions, json::json_functions, str::string_functions, Callable}, built_in_functions::{fs::fs_functions, json::json_functions, str::string_functions, Callable},
error::{RuntimeError, SyntaxError, ValidationError}, BuiltInFunction, EnumInstance, Function, Identifier, List, Map, Value,
AbstractTree, BuiltInFunction, Context, EnumInstance, Format, Function, Identifier, List, Map,
SyntaxNode, Type, Value,
}; };
static ARGS: OnceLock<Value> = OnceLock::new(); static ARGS: OnceLock<Value> = OnceLock::new();
static FS: OnceLock<Value> = OnceLock::new(); static FS: OnceLock<Value> = OnceLock::new();
static JSON: 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 NONE: OnceLock<Value> = OnceLock::new();
static RANDOM: OnceLock<Value> = OnceLock::new();
static STR: OnceLock<Value> = OnceLock::new();
/// Returns the entire built-in value API. /// Returns the entire built-in value API.
pub fn all_built_in_values() -> impl Iterator<Item = BuiltInValue> { 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 /// Returns the value by creating it or, if it has already been accessed, retrieving it from its
/// [OnceLock][]. /// [OnceLock][].
pub fn get(&self) -> &Value { pub fn get(&self) -> &Value {
@ -116,42 +97,40 @@ 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 mut fs_context = BTreeMap::new(); let mut fs_map = Map::new();
for fs_function in fs_functions() { for fs_function in fs_functions() {
let key = fs_function.name().to_string(); let key = fs_function.name();
let value = let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); 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(|| { BuiltInValue::Json => JSON.get_or_init(|| {
let mut json_context = BTreeMap::new(); let mut json_map = Map::new();
for json_function in json_functions() { for json_function in json_functions() {
let key = json_function.name().to_string(); let key = json_function.name();
let value = let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function))); 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::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
BuiltInValue::None => NONE.get_or_init(|| { BuiltInValue::None => &Value::Enum(EnumInstance::new(
Value::Enum(EnumInstance::new( Identifier::new("Option"),
"Option".to_string(), Identifier::new("None"),
"None".to_string(), None,
None, )),
))
}),
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 mut random_context = BTreeMap::new(); let mut random_map = Map::new();
for built_in_function in [ for built_in_function in [
BuiltInFunction::RandomBoolean, BuiltInFunction::RandomBoolean,
@ -159,83 +138,28 @@ impl BuiltInValue {
BuiltInFunction::RandomFrom, BuiltInFunction::RandomFrom,
BuiltInFunction::RandomInteger, 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)); 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(|| { BuiltInValue::Str => STR.get_or_init(|| {
let mut string_context = BTreeMap::new(); let mut str_map = Map::new();
for string_function in string_functions() { 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( let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function, 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::{ use crate::{
built_in_type_definitions::all_built_in_type_definitions, built_in_values::all_built_in_values, 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 /// 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. /// See the [module-level docs][self] for more info.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Context { pub struct Context {
inner: Arc<RwLock<BTreeMap<String, ValueData>>>, inner: Arc<RwLock<BTreeMap<Identifier, ValueData>>>,
} }
impl Context { impl Context {
@ -56,7 +56,7 @@ impl Context {
} }
/// Return a lock guard to the inner BTreeMap. /// 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()?) 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 /// This will also return a built-in value if one matches the key. See the
/// [module-level docs][self] for more info. /// [module-level docs][self] for more info.
pub fn get_value(&self, key: &str) -> Result<Option<Value>, RwLockError> { pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(key) { if let Some(value_data) = self.inner.read()?.get(identifier) {
if let ValueData::Value { inner, .. } = value_data { if let ValueData::Value { inner, .. } = value_data {
return Ok(Some(inner.clone())); return Ok(Some(inner.clone()));
} }
} }
for built_in_value in all_built_in_values() { 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())); 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 /// If the key matches a stored value, its type will be returned. It if
/// matches a type hint, the type hint will be returned. /// matches a type hint, the type hint will be returned.
pub fn get_type(&self, key: &str) -> Result<Option<Type>, RwLockError> { pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(key) { if let Some(value_data) = self.inner.read()?.get(identifier) {
match value_data { match value_data {
ValueData::Value { inner, .. } => return Ok(Some(inner.r#type())), ValueData::Value { inner, .. } => return Ok(Some(inner.r#type())),
ValueData::TypeHint { inner, .. } => return Ok(Some(inner.clone())), 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) Ok(None)
} }
@ -154,16 +148,19 @@ impl Context {
/// ///
/// This will also return a built-in type definition if one matches the key. /// This will also return a built-in type definition if one matches the key.
/// See the [module-level docs][self] for more info. /// See the [module-level docs][self] for more info.
pub fn get_definition(&self, key: &str) -> Result<Option<TypeDefinition>, RwLockError> { pub fn get_definition(
if let Some(value_data) = self.inner.read()?.get(key) { &self,
identifier: &Identifier,
) -> Result<Option<TypeDefinition>, RwLockError> {
if let Some(value_data) = self.inner.read()?.get(identifier) {
if let ValueData::TypeDefinition(definition) = value_data { if let ValueData::TypeDefinition(definition) = value_data {
return Ok(Some(definition.clone())); return Ok(Some(definition.clone()));
} }
} }
for built_in_definition in all_built_in_type_definitions() { for built_in_definition in all_built_in_type_definitions() {
if key == built_in_definition.name() { if built_in_definition.name() == identifier.inner().as_ref() {
return Ok(Some(built_in_definition.get().clone())); return Ok(Some(built_in_definition.get(self).clone()?));
} }
} }
@ -171,7 +168,7 @@ impl Context {
} }
/// Set a value to a key. /// 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( self.inner.write()?.insert(
key, key,
ValueData::Value { ValueData::Value {
@ -187,7 +184,7 @@ impl Context {
/// ///
/// This allows the interpreter to check a value's type before the value /// This allows the interpreter to check a value's type before the value
/// actually exists by predicting what the abstract tree will produce. /// 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 self.inner
.write()? .write()?
.insert(key, ValueData::TypeHint { inner: r#type }); .insert(key, ValueData::TypeHint { inner: r#type });
@ -201,7 +198,7 @@ impl Context {
/// later while using this context. /// later while using this context.
pub fn set_definition( pub fn set_definition(
&self, &self,
key: String, key: Identifier,
definition: TypeDefinition, definition: TypeDefinition,
) -> Result<(), RwLockError> { ) -> Result<(), RwLockError> {
self.inner self.inner
@ -212,7 +209,7 @@ impl Context {
} }
/// Remove a key-value pair. /// 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); self.inner.write()?.remove(key);
Ok(()) Ok(())

View File

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

View File

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

View File

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

View File

@ -2,30 +2,30 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::Value; use crate::{Identifier, Value};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumInstance { pub struct EnumInstance {
name: String, name: Identifier,
variant_name: String, variant: Identifier,
value: Option<Box<Value>>, value: Option<Box<Value>>,
} }
impl EnumInstance { 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 { Self {
name, name,
variant_name, variant: variant_name,
value: value.map(|value| Box::new(value)), value: value.map(|value| Box::new(value)),
} }
} }
pub fn name(&self) -> &String { pub fn name(&self) -> &Identifier {
&self.name &self.name
} }
pub fn variant_name(&self) -> &String { pub fn variant(&self) -> &Identifier {
&self.variant_name &self.variant
} }
pub fn value(&self) -> &Option<Box<Value>> { pub fn value(&self) -> &Option<Box<Value>> {
@ -35,6 +35,6 @@ impl EnumInstance {
impl Display for EnumInstance { impl Display for EnumInstance {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { 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::{ use std::fmt::{self, Display, Formatter};
cmp::Ordering,
fmt::{self, Display, Formatter},
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use stanza::{ use stanza::{
renderer::{console::Console, Renderer}, renderer::{console::Console, Renderer},
@ -12,8 +8,8 @@ use stanza::{
use crate::Value; use crate::Value;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct List(Arc<RwLock<Vec<Value>>>); pub struct List(Vec<Value>);
impl Default for List { impl Default for List {
fn default() -> Self { fn default() -> Self {
@ -23,23 +19,23 @@ impl Default for List {
impl List { impl List {
pub fn new() -> Self { pub fn new() -> Self {
List(Arc::new(RwLock::new(Vec::new()))) List(Vec::new())
} }
pub fn with_capacity(capacity: usize) -> Self { 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 { pub fn with_items(items: Vec<Value>) -> Self {
List(Arc::new(RwLock::new(items))) List(items)
} }
pub fn items(&self) -> RwLockReadGuard<'_, Vec<Value>> { pub fn items(&self) -> &Vec<Value> {
self.0.read().unwrap() &self.0
} }
pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec<Value>> { pub fn items_mut(&mut self) -> &mut Vec<Value> {
self.0.write().unwrap() &mut self.0
} }
pub fn as_text_table(&self) -> Table { 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 { impl Display for List {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let renderer = Console::default(); let renderer = Console::default();

View File

@ -9,7 +9,7 @@ use std::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
}; };
use crate::value::Value; use crate::{Identifier, Value};
/// A collection dust variables comprised of key-value pairs. /// A collection dust variables comprised of key-value pairs.
/// ///
@ -17,7 +17,7 @@ use crate::value::Value;
/// to one another. /// to one another.
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Map { pub struct Map {
inner: BTreeMap<String, Value>, inner: BTreeMap<Identifier, Value>,
} }
impl Map { 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 } Map { inner: variables }
} }
pub fn inner(&self) -> &BTreeMap<String, Value> { pub fn inner(&self) -> &BTreeMap<Identifier, Value> {
&self.inner &self.inner
} }
pub fn get(&self, key: &str) -> Option<&Value> { pub fn get(&self, key: &Identifier) -> Option<&Value> {
self.inner.get(key) 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); self.inner.insert(key, value);
} }
@ -63,7 +63,7 @@ impl Map {
vec![key.into(), list.as_text_table().into()], vec![key.into(), list.as_text_table().into()],
)); ));
} else { } 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::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::BTreeMap,
convert::TryFrom, convert::TryFrom,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
marker::PhantomData, marker::PhantomData,
@ -55,8 +54,8 @@ impl Value {
pub fn some(value: Value) -> Value { pub fn some(value: Value) -> Value {
Value::Enum(EnumInstance::new( Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"Some".to_string(), Identifier::new("Some"),
Some(value), Some(value),
)) ))
} }
@ -97,7 +96,7 @@ impl Value {
for (key, value) in map.inner() { for (key, value) in map.inner() {
identifier_types.push(( identifier_types.push((
Identifier::new(key.clone()), Identifier::new(key.inner()),
TypeSpecification::new(value.r#type()), TypeSpecification::new(value.r#type()),
)); ));
} }
@ -828,13 +827,15 @@ impl<'de> Visitor<'de> for ValueVisitor {
where where
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
let mut map = BTreeMap::new(); let mut map = Map::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? { 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> 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 serde::{ser::SerializeMap, Serialize, Serializer};
use crate::Map; use crate::{Identifier, Map};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructInstance { pub struct StructInstance {
name: String, name: Identifier,
map: Map, map: Map,
} }
impl StructInstance { impl StructInstance {
pub fn new(name: String, map: Map) -> Self { pub fn new(name: Identifier, map: Map) -> Self {
StructInstance { name, map } StructInstance { name, map }
} }
} }

View File

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