Revert "Remove structure from map types"

This reverts commit 5e685d6641.
This commit is contained in:
Jeff 2024-02-14 19:15:47 -05:00
parent 5e685d6641
commit 390d1aa504
6 changed files with 57 additions and 21 deletions

View File

@ -6,7 +6,8 @@ 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}, error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, BuiltInFunction, Context, Format, Function, List, Map, SyntaxNode, Type, Value, AbstractTree, BuiltInFunction, Context, Format, Function, List, Map, Structure, SyntaxNode,
Type, Value,
}; };
static ARGS: OnceLock<Value> = OnceLock::new(); static ARGS: OnceLock<Value> = OnceLock::new();
@ -86,12 +87,14 @@ impl BuiltInValue {
match self { match self {
BuiltInValue::Args => Type::list(Type::String), BuiltInValue::Args => Type::list(Type::String),
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
BuiltInValue::Fs => Type::Map, BuiltInValue::Fs => Type::Map(None),
BuiltInValue::Json => Type::Map, BuiltInValue::Json => Type::Map(Some(
Structure::from_map(self.get().as_map().unwrap()).unwrap(),
)),
BuiltInValue::Length => BuiltInFunction::Length.r#type(), BuiltInValue::Length => BuiltInFunction::Length.r#type(),
BuiltInValue::Output => BuiltInFunction::Output.r#type(), BuiltInValue::Output => BuiltInFunction::Output.r#type(),
BuiltInValue::Random => Type::Map, BuiltInValue::Random => Type::Map(None),
BuiltInValue::Str => Type::Map, BuiltInValue::Str => Type::Map(None),
} }
} }

View File

@ -48,7 +48,17 @@ impl AbstractTree for Index {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
match self.collection.expected_type(context)? { match self.collection.expected_type(context)? {
Type::List(item_type) => Ok(*item_type.clone()), Type::List(item_type) => Ok(*item_type.clone()),
Type::Map => Ok(Type::Any), Type::Map(structure) => {
if let Some(structure) = structure {
if let IndexExpression::Identifier(identifier) = &self.index {
if let Some((_, r#type)) = structure.inner().get(identifier.inner()) {
return Ok(r#type.clone());
}
}
}
Ok(Type::Any)
}
Type::None => Ok(Type::None), Type::None => Ok(Type::None),
r#type => Ok(r#type), r#type => Ok(r#type),
} }

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
error::{RuntimeError, SyntaxError, ValidationError}, error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Format, Identifier, SyntaxNode, Value, AbstractTree, Context, Format, Identifier, Structure, SyntaxNode, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -20,7 +20,7 @@ pub enum Type {
}, },
Integer, Integer,
List(Box<Type>), List(Box<Type>),
Map, Map(Option<Structure>),
None, None,
Number, Number,
String, String,
@ -58,13 +58,13 @@ impl Type {
| (Type::Collection, Type::Collection) | (Type::Collection, Type::Collection)
| (Type::Collection, Type::List(_)) | (Type::Collection, Type::List(_))
| (Type::List(_), Type::Collection) | (Type::List(_), Type::Collection)
| (Type::Collection, Type::Map) | (Type::Collection, Type::Map(_))
| (Type::Map, Type::Collection) | (Type::Map(_), Type::Collection)
| (Type::Collection, Type::String) | (Type::Collection, Type::String)
| (Type::String, Type::Collection) | (Type::String, Type::Collection)
| (Type::Float, Type::Float) | (Type::Float, Type::Float)
| (Type::Integer, Type::Integer) | (Type::Integer, Type::Integer)
| (Type::Map, Type::Map) | (Type::Map(_), Type::Map(_))
| (Type::Number, Type::Number) | (Type::Number, Type::Number)
| (Type::Number, Type::Integer) | (Type::Number, Type::Integer)
| (Type::Number, Type::Float) | (Type::Number, Type::Float)
@ -121,7 +121,7 @@ impl Type {
} }
pub fn is_map(&self) -> bool { pub fn is_map(&self) -> bool {
matches!(self, Type::Map) matches!(self, Type::Map(_))
} }
} }
@ -173,7 +173,7 @@ impl AbstractTree for Type {
} }
} }
"int" => Type::Integer, "int" => Type::Integer,
"map" => Type::Map, "map" => Type::Map(None),
"num" => Type::Number, "num" => Type::Number,
"none" => Type::None, "none" => Type::None,
"str" => Type::String, "str" => Type::String,
@ -241,8 +241,12 @@ impl Format for Type {
item_type.format(output, indent_level); item_type.format(output, indent_level);
output.push(']'); output.push(']');
} }
Type::Map => { Type::Map(structure_option) => {
output.push_str("map"); if let Some(structure) = structure_option {
output.push_str(&structure.to_string());
} else {
output.push_str("map");
}
} }
Type::None => output.push_str("none"), Type::None => output.push_str("none"),
Type::Number => output.push_str("num"), Type::Number => output.push_str("num"),
@ -284,7 +288,7 @@ impl Display for Type {
} }
Type::Integer => write!(f, "int"), Type::Integer => write!(f, "int"),
Type::List(item_type) => write!(f, "[{item_type}]"), Type::List(item_type) => write!(f, "[{item_type}]"),
Type::Map => write!(f, "map"), Type::Map(_) => write!(f, "map"),
Type::Number => write!(f, "num"), Type::Number => write!(f, "num"),
Type::None => write!(f, "none"), Type::None => write!(f, "none"),
Type::String => write!(f, "str"), Type::String => write!(f, "str"),

View File

@ -217,9 +217,17 @@ impl AbstractTree for ValueNode {
Type::None Type::None
} }
} }
ValueNode::Map(_, _) => Type::Map, ValueNode::Map(_, _) => Type::Map(None),
ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?, ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?,
ValueNode::Structure(_) => Type::Map, ValueNode::Structure(node_map) => {
let mut value_map = BTreeMap::new();
for (key, (_statement_option, r#type)) in node_map {
value_map.insert(key.to_string(), (None, r#type.clone()));
}
Type::Map(Some(Structure::new(value_map)))
}
ValueNode::Range(_) => Type::Range, ValueNode::Range(_) => Type::Range,
}; };

View File

@ -1,5 +1,5 @@
//! Types that represent runtime values. //! Types that represent runtime values.
use crate::{error::RuntimeError, Type}; use crate::{error::RuntimeError, Identifier, Type, TypeSpecification};
use serde::{ use serde::{
de::{MapAccess, SeqAccess, Visitor}, de::{MapAccess, SeqAccess, Visitor},
@ -80,7 +80,18 @@ impl Value {
Type::List(Box::new(Type::Any)) Type::List(Box::new(Type::Any))
} }
} }
Value::Map(_) => Type::Map, Value::Map(map) => {
let mut identifier_types = Vec::new();
for (key, value) in map.inner().unwrap().iter() {
identifier_types.push((
Identifier::new(key.clone()),
TypeSpecification::new(value.r#type()),
));
}
Type::Map(None)
}
Value::Function(function) => function.r#type().clone(), Value::Function(function) => function.r#type().clone(),
Value::String(_) => Type::String, Value::String(_) => Type::String,
Value::Float(_) => Type::Float, Value::Float(_) => Type::Float,

View File

@ -39,7 +39,7 @@ fn conversion_runtime_error() {
interpret(&format!("json:parse('{JSON}') as [map]")), interpret(&format!("json:parse('{JSON}') as [map]")),
Err(Error::Runtime(RuntimeError::ConversionImpossible { Err(Error::Runtime(RuntimeError::ConversionImpossible {
value: json_value, value: json_value,
target_type: Type::List(Box::new(Type::Map)) target_type: Type::List(Box::new(Type::Map(None)))
})) }))
) )
} }