Pass index tests; Begin implementing specific maps
This commit is contained in:
parent
4afc8face8
commit
52027db6c3
@ -36,7 +36,19 @@ impl AbstractTree for Index {
|
||||
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||
match self.collection.expected_type(context)? {
|
||||
Type::List(item_type) => Ok(*item_type.clone()),
|
||||
Type::Map => Ok(Type::Any),
|
||||
Type::Map(map_types_option) => {
|
||||
if let (Some(map_type), IndexExpression::Identifier(identifier)) =
|
||||
(map_types_option, &self.index)
|
||||
{
|
||||
if let Some(r#type) = map_type.get(&identifier) {
|
||||
Ok(r#type.clone())
|
||||
} else {
|
||||
Ok(Type::Any)
|
||||
}
|
||||
} else {
|
||||
Ok(Type::Any)
|
||||
}
|
||||
}
|
||||
Type::None => Ok(Type::None),
|
||||
r#type => Ok(r#type),
|
||||
}
|
||||
@ -46,11 +58,20 @@ impl AbstractTree for Index {
|
||||
self.collection.validate(_source, _context)?;
|
||||
|
||||
let collection_type = self.collection.expected_type(_context)?;
|
||||
let index_type = self.index.expected_type(_context)?;
|
||||
|
||||
if let (Type::Map, Type::String) = (collection_type, index_type) {}
|
||||
|
||||
if let (Type::Map(type_map_option), IndexExpression::Identifier(identifier)) =
|
||||
(collection_type, &self.index)
|
||||
{
|
||||
if let Some(type_map) = type_map_option {
|
||||
if !type_map.contains_key(identifier) {
|
||||
return Err(ValidationError::VariableIdentifierNotFound(
|
||||
identifier.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.index.validate(_source, _context)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -58,7 +58,19 @@ impl AbstractTree for MapNode {
|
||||
}
|
||||
|
||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||
Ok(Type::Map)
|
||||
let mut type_map = BTreeMap::new();
|
||||
|
||||
for (identifier, (statement, r#type_option)) in &self.properties {
|
||||
let r#type = if let Some(r#type) = type_option {
|
||||
r#type.clone()
|
||||
} else {
|
||||
statement.expected_type(_context)?
|
||||
};
|
||||
|
||||
type_map.insert(identifier.clone(), r#type);
|
||||
}
|
||||
|
||||
Ok(Type::Map(Some(type_map)))
|
||||
}
|
||||
|
||||
fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> {
|
||||
|
@ -1,4 +1,7 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
fmt::{self, Display, Formatter},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node as SyntaxNode;
|
||||
@ -25,7 +28,7 @@ pub enum Type {
|
||||
},
|
||||
Integer,
|
||||
List(Box<Type>),
|
||||
Map,
|
||||
Map(Option<BTreeMap<Identifier, Type>>),
|
||||
Number,
|
||||
String,
|
||||
Range,
|
||||
@ -69,13 +72,13 @@ impl Type {
|
||||
| (Type::Collection, Type::Collection)
|
||||
| (Type::Collection, Type::List(_))
|
||||
| (Type::List(_), Type::Collection)
|
||||
| (Type::Collection, Type::Map)
|
||||
| (Type::Map, Type::Collection)
|
||||
| (Type::Collection, Type::Map(_))
|
||||
| (Type::Map(_), Type::Collection)
|
||||
| (Type::Collection, Type::String)
|
||||
| (Type::String, Type::Collection)
|
||||
| (Type::Float, Type::Float)
|
||||
| (Type::Integer, Type::Integer)
|
||||
| (Type::Map, Type::Map)
|
||||
| (Type::Map(_), Type::Map(_))
|
||||
| (Type::Number, Type::Number)
|
||||
| (Type::Number, Type::Integer)
|
||||
| (Type::Number, Type::Float)
|
||||
@ -137,7 +140,7 @@ impl Type {
|
||||
}
|
||||
|
||||
pub fn is_map(&self) -> bool {
|
||||
matches!(self, Type::Map)
|
||||
matches!(self, Type::Map(_))
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +202,7 @@ impl AbstractTree for Type {
|
||||
}
|
||||
}
|
||||
"int" => Type::Integer,
|
||||
"map" => Type::Map,
|
||||
"map" => Type::Map(None),
|
||||
"num" => Type::Number,
|
||||
"none" => Type::None,
|
||||
"str" => Type::String,
|
||||
@ -262,7 +265,7 @@ impl Format for Type {
|
||||
item_type.format(output, indent_level);
|
||||
output.push(']');
|
||||
}
|
||||
Type::Map => {
|
||||
Type::Map(_) => {
|
||||
output.push_str("map");
|
||||
}
|
||||
Type::None => output.push_str("Option::None"),
|
||||
@ -306,7 +309,7 @@ impl Display for Type {
|
||||
}
|
||||
Type::Integer => write!(f, "int"),
|
||||
Type::List(item_type) => write!(f, "[{item_type}]"),
|
||||
Type::Map => write!(f, "map"),
|
||||
Type::Map(_) => write!(f, "map"),
|
||||
Type::Number => write!(f, "num"),
|
||||
Type::None => write!(f, "none"),
|
||||
Type::String => write!(f, "str"),
|
||||
|
@ -144,7 +144,7 @@ impl AbstractTree for ValueNode {
|
||||
Type::List(Box::new(Type::Any))
|
||||
}
|
||||
}
|
||||
ValueNode::Map(_) => Type::Map,
|
||||
ValueNode::Map(map_node) => map_node.expected_type(context)?,
|
||||
ValueNode::Struct { name, .. } => {
|
||||
Type::Custom { name: name.clone(), argument: None }
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ use serde::{
|
||||
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::BTreeMap,
|
||||
convert::TryFrom,
|
||||
fmt::{self, Display, Formatter},
|
||||
marker::PhantomData,
|
||||
@ -93,7 +94,15 @@ impl Value {
|
||||
Type::List(Box::new(Type::Any))
|
||||
}
|
||||
}
|
||||
Value::Map(_) => Type::Map,
|
||||
Value::Map(map) => {
|
||||
let mut type_map = BTreeMap::new();
|
||||
|
||||
for (identifier, value) in map.inner() {
|
||||
type_map.insert(identifier.clone(), value.r#type()?);
|
||||
}
|
||||
|
||||
Type::Map(Some(type_map))
|
||||
}
|
||||
Value::Function(function) => function.r#type().clone(),
|
||||
Value::String(_) => Type::String,
|
||||
Value::Float(_) => Type::Float,
|
||||
|
@ -39,7 +39,7 @@ fn conversion_runtime_error() {
|
||||
interpret(&format!("json:parse('{JSON}') as [map]")),
|
||||
Err(Error::Runtime(RuntimeError::ConversionImpossible {
|
||||
from: json_value.r#type().unwrap(),
|
||||
to: Type::List(Box::new(Type::Map)),
|
||||
to: Type::List(Box::new(Type::Map(None))),
|
||||
position: SourcePosition {
|
||||
start_byte: 0,
|
||||
end_byte: 0,
|
||||
|
8
tree-sitter-dust/corpus/types.txt
Normal file
8
tree-sitter-dust/corpus/types.txt
Normal file
@ -0,0 +1,8 @@
|
||||
================================================================================
|
||||
Specific Map
|
||||
================================================================================
|
||||
|
||||
x <{ y <int> }> = { y = 2 }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -355,6 +355,17 @@ module.exports = grammar({
|
||||
'float',
|
||||
'int',
|
||||
'map',
|
||||
seq(
|
||||
'map',
|
||||
'{',
|
||||
repeat1(
|
||||
seq(
|
||||
$.identifier,
|
||||
$.type_specification,
|
||||
),
|
||||
),
|
||||
'}',
|
||||
),
|
||||
'none',
|
||||
'num',
|
||||
'str',
|
||||
|
@ -1076,6 +1076,39 @@
|
||||
"type": "STRING",
|
||||
"value": "map"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "map"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT1",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "type_specification"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "none"
|
||||
|
@ -730,6 +730,10 @@
|
||||
{
|
||||
"type": "type",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "type_specification",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user