Begin adding fields to map type
This commit is contained in:
parent
37d59f562d
commit
5e8945cab5
@ -423,7 +423,7 @@ impl FunctionLogic for JsonParse {
|
|||||||
Type::Integer => Value::integer(from_str::<i64>(input_string)?),
|
Type::Integer => Value::integer(from_str::<i64>(input_string)?),
|
||||||
Type::List { .. } => todo!(),
|
Type::List { .. } => todo!(),
|
||||||
Type::ListOf(_) => todo!(),
|
Type::ListOf(_) => todo!(),
|
||||||
Type::Map => todo!(),
|
Type::Map(_) => todo!(),
|
||||||
Type::Range => todo!(),
|
Type::Range => todo!(),
|
||||||
Type::String => Value::string(from_str::<String>(input_string)?),
|
Type::String => Value::string(from_str::<String>(input_string)?),
|
||||||
Type::Structure { .. } => todo!(),
|
Type::Structure { .. } => todo!(),
|
||||||
|
@ -30,7 +30,13 @@ impl AbstractNode for MapIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
self.collection.validate(_context, _manage_memory)
|
self.collection.validate(_context, _manage_memory)?;
|
||||||
|
|
||||||
|
if let Expression::Identifier(identifier) = &self.index {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
self.index.validate(_context, _manage_memory)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
};
|
||||||
|
|
||||||
use clap::error::Result;
|
use clap::error::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -30,7 +33,7 @@ pub enum Type {
|
|||||||
item_type: Box<Type>,
|
item_type: Box<Type>,
|
||||||
},
|
},
|
||||||
ListOf(Box<Type>),
|
ListOf(Box<Type>),
|
||||||
Map,
|
Map(BTreeMap<Identifier, Type>),
|
||||||
Range,
|
Range,
|
||||||
String,
|
String,
|
||||||
Structure {
|
Structure {
|
||||||
@ -47,7 +50,6 @@ impl Type {
|
|||||||
| (Type::Boolean, Type::Boolean)
|
| (Type::Boolean, Type::Boolean)
|
||||||
| (Type::Float, Type::Float)
|
| (Type::Float, Type::Float)
|
||||||
| (Type::Integer, Type::Integer)
|
| (Type::Integer, Type::Integer)
|
||||||
| (Type::Map, Type::Map)
|
|
||||||
| (Type::Range, Type::Range)
|
| (Type::Range, Type::Range)
|
||||||
| (Type::String, Type::String) => return Ok(()),
|
| (Type::String, Type::String) => return Ok(()),
|
||||||
(
|
(
|
||||||
@ -190,6 +192,11 @@ impl Type {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(Type::Map(left), Type::Map(right)) => {
|
||||||
|
if left == right {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,8 +243,16 @@ impl Display for Type {
|
|||||||
}
|
}
|
||||||
Type::Integer => write!(f, "int"),
|
Type::Integer => write!(f, "int"),
|
||||||
Type::List { length, item_type } => write!(f, "[{length}; {}]", item_type),
|
Type::List { length, item_type } => write!(f, "[{length}; {}]", item_type),
|
||||||
Type::ListOf(item_type) => write!(f, "list({})", item_type),
|
Type::ListOf(item_type) => write!(f, "[{}]", item_type),
|
||||||
Type::Map => write!(f, "map"),
|
Type::Map(item_types) => {
|
||||||
|
writeln!(f, "{{")?;
|
||||||
|
|
||||||
|
for (identifier, r#type) in item_types {
|
||||||
|
writeln!(f, "{identifier}: {type}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "}}")
|
||||||
|
}
|
||||||
Type::Range => write!(f, "range"),
|
Type::Range => write!(f, "range"),
|
||||||
Type::String => write!(f, "str"),
|
Type::String => write!(f, "str"),
|
||||||
Type::Function {
|
Type::Function {
|
||||||
@ -300,7 +315,13 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(Type::Map.check(&Type::Map), Ok(()));
|
let mut map = BTreeMap::new();
|
||||||
|
|
||||||
|
map.insert(Identifier::new("x"), Type::Integer);
|
||||||
|
map.insert(Identifier::new("y"), Type::String);
|
||||||
|
map.insert(Identifier::new("z"), Type::Map(map.clone()));
|
||||||
|
|
||||||
|
assert_eq!(Type::Map(map.clone()).check(&Type::Map(map)), Ok(()));
|
||||||
assert_eq!(Type::Range.check(&Type::Range), Ok(()));
|
assert_eq!(Type::Range.check(&Type::Range), Ok(()));
|
||||||
assert_eq!(Type::String.check(&Type::String), Ok(()));
|
assert_eq!(Type::String.check(&Type::String), Ok(()));
|
||||||
}
|
}
|
||||||
@ -334,7 +355,7 @@ mod tests {
|
|||||||
item_type: Box::new(Type::Integer),
|
item_type: Box::new(Type::Integer),
|
||||||
},
|
},
|
||||||
Type::ListOf(Box::new(Type::Boolean)),
|
Type::ListOf(Box::new(Type::Boolean)),
|
||||||
Type::Map,
|
Type::Map(BTreeMap::new()),
|
||||||
Type::Range,
|
Type::Range,
|
||||||
Type::String,
|
Type::String,
|
||||||
];
|
];
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
};
|
||||||
|
|
||||||
|
use chumsky::container::Container;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{context::Context, error::ValidationError, identifier::Identifier};
|
use crate::{context::Context, error::ValidationError, identifier::Identifier};
|
||||||
@ -13,6 +17,7 @@ pub enum TypeConstructor {
|
|||||||
Invokation(TypeInvokationConstructor),
|
Invokation(TypeInvokationConstructor),
|
||||||
List(WithPosition<ListTypeConstructor>),
|
List(WithPosition<ListTypeConstructor>),
|
||||||
ListOf(WithPosition<Box<TypeConstructor>>),
|
ListOf(WithPosition<Box<TypeConstructor>>),
|
||||||
|
Map(WithPosition<Vec<(WithPosition<Identifier>, TypeConstructor)>>),
|
||||||
Raw(WithPosition<RawTypeConstructor>),
|
Raw(WithPosition<RawTypeConstructor>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +27,6 @@ pub enum RawTypeConstructor {
|
|||||||
Boolean,
|
Boolean,
|
||||||
Float,
|
Float,
|
||||||
Integer,
|
Integer,
|
||||||
Map,
|
|
||||||
Range,
|
Range,
|
||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
@ -47,6 +51,7 @@ impl TypeConstructor {
|
|||||||
}
|
}
|
||||||
TypeConstructor::List(WithPosition { position, .. }) => *position,
|
TypeConstructor::List(WithPosition { position, .. }) => *position,
|
||||||
TypeConstructor::ListOf(WithPosition { position, .. }) => *position,
|
TypeConstructor::ListOf(WithPosition { position, .. }) => *position,
|
||||||
|
TypeConstructor::Map(WithPosition { position, .. }) => *position,
|
||||||
TypeConstructor::Raw(WithPosition { position, .. }) => *position,
|
TypeConstructor::Raw(WithPosition { position, .. }) => *position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,12 +181,22 @@ impl TypeConstructor {
|
|||||||
|
|
||||||
Type::ListOf(Box::new(item_type))
|
Type::ListOf(Box::new(item_type))
|
||||||
}
|
}
|
||||||
|
TypeConstructor::Map(field_type_constructors) => {
|
||||||
|
let mut field_types = BTreeMap::with_capacity(field_type_constructors.node.len());
|
||||||
|
|
||||||
|
for (identifier, constructor) in &field_type_constructors.node {
|
||||||
|
let r#type = constructor.construct(context)?;
|
||||||
|
|
||||||
|
field_types.insert(identifier.node.clone(), r#type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Map(field_types)
|
||||||
|
}
|
||||||
TypeConstructor::Raw(raw_type) => match raw_type.node {
|
TypeConstructor::Raw(raw_type) => match raw_type.node {
|
||||||
RawTypeConstructor::Any => Type::Any,
|
RawTypeConstructor::Any => Type::Any,
|
||||||
RawTypeConstructor::Boolean => Type::Boolean,
|
RawTypeConstructor::Boolean => Type::Boolean,
|
||||||
RawTypeConstructor::Float => Type::Float,
|
RawTypeConstructor::Float => Type::Float,
|
||||||
RawTypeConstructor::Integer => Type::Integer,
|
RawTypeConstructor::Integer => Type::Integer,
|
||||||
RawTypeConstructor::Map => Type::Map,
|
|
||||||
RawTypeConstructor::Range => Type::Range,
|
RawTypeConstructor::Range => Type::Range,
|
||||||
RawTypeConstructor::String => Type::String,
|
RawTypeConstructor::String => Type::String,
|
||||||
},
|
},
|
||||||
|
@ -402,7 +402,25 @@ impl AbstractNode for ValueNode {
|
|||||||
item_type: Box::new(item_type),
|
item_type: Box::new(item_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Map(_) => Type::Map,
|
ValueNode::Map(fields) => {
|
||||||
|
let mut field_types = BTreeMap::new();
|
||||||
|
|
||||||
|
for (identifier, constructor_option, expression) in fields {
|
||||||
|
let r#type = if let Some(constructor) = constructor_option {
|
||||||
|
constructor.construct(context)?
|
||||||
|
} else {
|
||||||
|
if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::CannotAssignToNone(expression.position()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
field_types.insert(identifier.clone(), r#type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Map(field_types)
|
||||||
|
}
|
||||||
ValueNode::Range(_) => Type::Range,
|
ValueNode::Range(_) => Type::Range,
|
||||||
ValueNode::String(_) => Type::String,
|
ValueNode::String(_) => Type::String,
|
||||||
ValueNode::Function(FunctionNode {
|
ValueNode::Function(FunctionNode {
|
||||||
|
@ -82,7 +82,6 @@ pub fn parser<'src>(
|
|||||||
just(Token::Keyword(Keyword::Bool)).to(RawTypeConstructor::Boolean),
|
just(Token::Keyword(Keyword::Bool)).to(RawTypeConstructor::Boolean),
|
||||||
just(Token::Keyword(Keyword::Float)).to(RawTypeConstructor::Float),
|
just(Token::Keyword(Keyword::Float)).to(RawTypeConstructor::Float),
|
||||||
just(Token::Keyword(Keyword::Int)).to(RawTypeConstructor::Integer),
|
just(Token::Keyword(Keyword::Int)).to(RawTypeConstructor::Integer),
|
||||||
just(Token::Keyword(Keyword::Map)).to(RawTypeConstructor::Map),
|
|
||||||
just(Token::Keyword(Keyword::Range)).to(RawTypeConstructor::Range),
|
just(Token::Keyword(Keyword::Range)).to(RawTypeConstructor::Range),
|
||||||
just(Token::Keyword(Keyword::Str)).to(RawTypeConstructor::String),
|
just(Token::Keyword(Keyword::Str)).to(RawTypeConstructor::String),
|
||||||
))
|
))
|
||||||
@ -196,7 +195,24 @@ pub fn parser<'src>(
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let map_type = positioned_identifier
|
||||||
|
.clone()
|
||||||
|
.then_ignore(just(Token::Symbol(Symbol::Colon)))
|
||||||
|
.then(type_constructor.clone())
|
||||||
|
.separated_by(just(Token::Symbol(Symbol::Comma)))
|
||||||
|
.collect()
|
||||||
|
.delimited_by(
|
||||||
|
just(Token::Symbol(Symbol::CurlyOpen)),
|
||||||
|
just(Token::Symbol(Symbol::CurlyClose)),
|
||||||
|
)
|
||||||
|
.map_with(
|
||||||
|
|fields: Vec<(WithPosition<Identifier>, TypeConstructor)>, state| {
|
||||||
|
TypeConstructor::Map(fields.with_position(state.span()))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
|
map_type,
|
||||||
type_invokation,
|
type_invokation,
|
||||||
function_type,
|
function_type,
|
||||||
list_type,
|
list_type,
|
||||||
|
@ -592,7 +592,17 @@ impl ValueInner {
|
|||||||
item_type: Box::new(item_type),
|
item_type: Box::new(item_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueInner::Map(_) => Type::Map,
|
ValueInner::Map(value_map) => {
|
||||||
|
let mut type_map = BTreeMap::with_capacity(value_map.len());
|
||||||
|
|
||||||
|
for (identifier, value) in value_map {
|
||||||
|
let r#type = value.r#type(context)?;
|
||||||
|
|
||||||
|
type_map.insert(identifier.clone(), r#type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Map(type_map)
|
||||||
|
}
|
||||||
ValueInner::Range(_) => Type::Range,
|
ValueInner::Range(_) => Type::Range,
|
||||||
ValueInner::String(_) => Type::String,
|
ValueInner::String(_) => Type::String,
|
||||||
ValueInner::Function(function) => {
|
ValueInner::Function(function) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user