diff --git a/examples/jq_data.ds b/examples/jq_data.ds index 62e7092..d5292b0 100644 --- a/examples/jq_data.ds +++ b/examples/jq_data.ds @@ -2,7 +2,7 @@ data = json:parse(fs:read_file('examples/assets/jq_data.json')) new_data = [] -for commit_data in data { +for commit_data in data as collection { new_data += { message = commit_data:commit:message name = commit_data:commit:committer:name diff --git a/src/abstract_tree/as.rs b/src/abstract_tree/as.rs index 91ed54d..f5e88c0 100644 --- a/src/abstract_tree/as.rs +++ b/src/abstract_tree/as.rs @@ -37,9 +37,15 @@ impl AbstractTree for As { fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> { let initial_type = self.expression.expected_type(context)?; + if self.r#type.accepts(&initial_type) { + return Ok(()); + } + if let Type::ListOf(item_type) = &self.r#type { match &initial_type { Type::ListOf(expected_item_type) => { + println!("{item_type} {expected_item_type}"); + if !item_type.accepts(&expected_item_type) { return Err(ValidationError::TypeCheck { expected: self.r#type.clone(), @@ -77,7 +83,9 @@ impl AbstractTree for As { fn run(&self, source: &str, context: &Context) -> Result { let value = self.expression.run(source, context)?; - let converted_value = if let Type::ListOf(_) = self.r#type { + let converted_value = if self.r#type.accepts(&value.r#type()?) { + return Ok(value); + } else if let Type::ListOf(_) = self.r#type { match value { Value::List(list) => Value::List(list), Value::String(string) => { diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 5ede5af..2197e45 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -66,16 +66,22 @@ impl AbstractTree for For { self.collection.validate(_source, context)?; let collection_type = self.collection.expected_type(context)?; - let item_type = if let Type::ListOf(item_type) = collection_type { - item_type.as_ref().clone() - } else if let Type::Range = collection_type { - Type::Integer - } else { - return Err(ValidationError::TypeCheck { - expected: Type::Collection, - actual: collection_type, - position: self.source_position, - }); + let item_type = match collection_type { + Type::Any => Type::Any, + Type::Collection => Type::Any, + Type::List => Type::Any, + Type::ListOf(_) => todo!(), + Type::ListExact(_) => todo!(), + Type::Map(_) => todo!(), + Type::String => todo!(), + Type::Range => todo!(), + _ => { + return Err(ValidationError::TypeCheck { + expected: Type::Collection, + actual: collection_type, + position: self.source_position, + }); + } }; let key = self.item_id.clone(); @@ -116,6 +122,7 @@ impl AbstractTree for For { })?; } else { for value in list.items()?.iter() { + self.context.add_allowance(key)?; self.context.set_value(key.clone(), value.clone())?; self.block.run(source, &self.context)?; } diff --git a/src/abstract_tree/index_expression.rs b/src/abstract_tree/index_expression.rs index 4958140..c07b069 100644 --- a/src/abstract_tree/index_expression.rs +++ b/src/abstract_tree/index_expression.rs @@ -57,13 +57,17 @@ impl AbstractTree for IndexExpression { } } - fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> { match self { - IndexExpression::Value(value_node) => value_node.validate(_source, _context), - IndexExpression::Identifier(identifier) => identifier.validate(_source, _context), - IndexExpression::Index(index) => index.validate(_source, _context), + IndexExpression::Value(value_node) => value_node.validate(_source, context), + IndexExpression::Identifier(identifier) => { + context.add_allowance(identifier)?; + + Ok(()) + } + IndexExpression::Index(index) => index.validate(_source, context), IndexExpression::FunctionCall(function_call) => { - function_call.validate(_source, _context) + function_call.validate(_source, context) } } } diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs index 1ac8391..5e1abdc 100644 --- a/src/abstract_tree/type.rs +++ b/src/abstract_tree/type.rs @@ -210,6 +210,15 @@ impl AbstractTree for Type { Type::ListOf(Box::new(item_type)) } + "list" => { + let item_type_node = node.child(1); + + if let Some(child) = item_type_node { + Type::ListOf(Box::new(Type::from_syntax(child, _source, context)?)) + } else { + Type::List + } + } "any" => Type::Any, "bool" => Type::Boolean, "collection" => Type::Collection, @@ -247,7 +256,8 @@ impl AbstractTree for Type { "str" => Type::String, _ => { return Err(SyntaxError::UnexpectedSyntaxNode { - expected: "any, bool, float, int, num, str, custom type, (, [ or {".to_string(), + expected: "any, bool, float, int, num, str, list, map, custom type, (, [ or {" + .to_string(), actual: type_node.kind().to_string(), position: node.range().into(), }) diff --git a/src/value/mod.rs b/src/value/mod.rs index e7dc0ef..bd89747 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -104,7 +104,18 @@ impl Value { Value::Boolean(_) => Type::Boolean, Value::Range(_) => todo!(), Value::Struct(_) => todo!(), - Value::Enum(_) => todo!(), + Value::Enum(enum_instance) => { + let arguments = if let Some(value) = enum_instance.value() { + vec![value.r#type()?] + } else { + Vec::with_capacity(0) + }; + + Type::Custom { + name: enum_instance.name().clone(), + arguments, + } + } }; Ok(r#type) diff --git a/tests/built_in_type_definitions.rs b/tests/built_in_type_definitions.rs index 10a78cc..663dc18 100644 --- a/tests/built_in_type_definitions.rs +++ b/tests/built_in_type_definitions.rs @@ -11,6 +11,7 @@ fn override_built_ins() { } my_option