1
0

Pass index tests; Begin implementing specific maps

This commit is contained in:
Jeff 2024-02-18 06:28:31 -05:00
parent 4afc8face8
commit 52027db6c3
11 changed files with 19877 additions and 19338 deletions

View File

@ -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) {}
self.index.validate(_source, _context)?;
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(())
}

View File

@ -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> {

View File

@ -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"),

View File

@ -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 }
}

View File

@ -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,

View File

@ -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,

View File

@ -0,0 +1,8 @@
================================================================================
Specific Map
================================================================================
x <{ y <int> }> = { y = 2 }
--------------------------------------------------------------------------------

View File

@ -355,6 +355,17 @@ module.exports = grammar({
'float',
'int',
'map',
seq(
'map',
'{',
repeat1(
seq(
$.identifier,
$.type_specification,
),
),
'}',
),
'none',
'num',
'str',

View File

@ -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"

View File

@ -730,6 +730,10 @@
{
"type": "type",
"named": true
},
{
"type": "type_specification",
"named": true
}
]
}

File diff suppressed because it is too large Load Diff