121 lines
3.9 KiB
Rust
121 lines
3.9 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use tree_sitter::Node as SyntaxNode;
|
|
|
|
use crate::{
|
|
error::{RuntimeError, SyntaxError, ValidationError},
|
|
AbstractTree, Context, Format, Identifier, Map, MapNode, Statement, StructInstance, Type,
|
|
TypeDefinition, TypeSpecification, Value,
|
|
};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
pub struct StructDefinition {
|
|
name: Identifier,
|
|
properties: BTreeMap<Identifier, (Option<Statement>, Type)>,
|
|
}
|
|
|
|
impl StructDefinition {
|
|
pub fn instantiate(
|
|
&self,
|
|
new_properties: &MapNode,
|
|
source: &str,
|
|
context: &Context,
|
|
) -> Result<StructInstance, RuntimeError> {
|
|
let mut all_properties = Map::new();
|
|
|
|
for (key, (statement_option, _)) in &self.properties {
|
|
if let Some(statement) = statement_option {
|
|
let value = statement.run(source, context)?;
|
|
|
|
all_properties.set(key.clone(), value);
|
|
}
|
|
}
|
|
|
|
for (key, (statement, _)) in new_properties.properties() {
|
|
let value = statement.run(source, context)?;
|
|
|
|
all_properties.set(key.clone(), value);
|
|
}
|
|
|
|
Ok(StructInstance::new(self.name.clone(), all_properties))
|
|
}
|
|
}
|
|
|
|
impl AbstractTree for StructDefinition {
|
|
fn from_syntax(node: SyntaxNode, source: &str, context: &Context) -> Result<Self, SyntaxError> {
|
|
SyntaxError::expect_syntax_node("struct_definition", node)?;
|
|
|
|
let name_node = node.child(1).unwrap();
|
|
let name = Identifier::from_syntax(name_node, source, context)?;
|
|
|
|
let mut properties = BTreeMap::new();
|
|
let mut current_identifier: Option<Identifier> = None;
|
|
let mut current_type: Option<Type> = None;
|
|
let mut current_statement = None;
|
|
|
|
for index in 2..node.child_count() - 1 {
|
|
let child_syntax_node = node.child(index).unwrap();
|
|
|
|
if child_syntax_node.kind() == "identifier" {
|
|
if current_statement.is_none() {
|
|
if let (Some(identifier), Some(r#type)) = (¤t_identifier, ¤t_type) {
|
|
properties.insert(identifier.clone(), (None, r#type.clone()));
|
|
}
|
|
}
|
|
|
|
current_type = None;
|
|
current_identifier =
|
|
Some(Identifier::from_syntax(child_syntax_node, source, context)?);
|
|
}
|
|
|
|
if child_syntax_node.kind() == "type_specification" {
|
|
current_type = Some(
|
|
TypeSpecification::from_syntax(child_syntax_node, source, context)?
|
|
.take_inner(),
|
|
);
|
|
}
|
|
|
|
if child_syntax_node.kind() == "statement" {
|
|
current_statement =
|
|
Some(Statement::from_syntax(child_syntax_node, source, context)?);
|
|
|
|
if let Some(identifier) = ¤t_identifier {
|
|
let r#type = if let Some(r#type) = ¤t_type {
|
|
r#type.clone()
|
|
} else {
|
|
Type::None
|
|
};
|
|
|
|
properties.insert(
|
|
identifier.clone(),
|
|
(current_statement.clone(), r#type.clone()),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(StructDefinition { name, properties })
|
|
}
|
|
|
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
|
Ok(Type::None)
|
|
}
|
|
|
|
fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> {
|
|
Ok(())
|
|
}
|
|
|
|
fn run(&self, _source: &str, context: &Context) -> Result<Value, RuntimeError> {
|
|
context.set_definition(self.name.clone(), TypeDefinition::Struct(self.clone()))?;
|
|
|
|
Ok(Value::none())
|
|
}
|
|
}
|
|
|
|
impl Format for StructDefinition {
|
|
fn format(&self, _output: &mut String, _indent_level: u8) {
|
|
todo!()
|
|
}
|
|
}
|