1
0

Fix garbage collection bug

This commit is contained in:
Jeff 2024-02-18 16:43:47 -05:00
parent 255843cb3b
commit 37fd722fa6
8 changed files with 87 additions and 19 deletions

View File

@ -2,7 +2,7 @@ data = json:parse(fs:read_file('examples/assets/jq_data.json'))
new_data = [] new_data = []
for commit_data in data { for commit_data in data as collection {
new_data += { new_data += {
message = commit_data:commit:message message = commit_data:commit:message
name = commit_data:commit:committer:name name = commit_data:commit:committer:name

View File

@ -37,9 +37,15 @@ impl AbstractTree for As {
fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> { fn validate(&self, _source: &str, context: &Context) -> Result<(), ValidationError> {
let initial_type = self.expression.expected_type(context)?; 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 { if let Type::ListOf(item_type) = &self.r#type {
match &initial_type { match &initial_type {
Type::ListOf(expected_item_type) => { Type::ListOf(expected_item_type) => {
println!("{item_type} {expected_item_type}");
if !item_type.accepts(&expected_item_type) { if !item_type.accepts(&expected_item_type) {
return Err(ValidationError::TypeCheck { return Err(ValidationError::TypeCheck {
expected: self.r#type.clone(), expected: self.r#type.clone(),
@ -77,7 +83,9 @@ impl AbstractTree for As {
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> { fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let value = self.expression.run(source, context)?; 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 { match value {
Value::List(list) => Value::List(list), Value::List(list) => Value::List(list),
Value::String(string) => { Value::String(string) => {

View File

@ -66,16 +66,22 @@ impl AbstractTree for For {
self.collection.validate(_source, context)?; self.collection.validate(_source, context)?;
let collection_type = self.collection.expected_type(context)?; let collection_type = self.collection.expected_type(context)?;
let item_type = if let Type::ListOf(item_type) = collection_type { let item_type = match collection_type {
item_type.as_ref().clone() Type::Any => Type::Any,
} else if let Type::Range = collection_type { Type::Collection => Type::Any,
Type::Integer Type::List => Type::Any,
} else { Type::ListOf(_) => todo!(),
Type::ListExact(_) => todo!(),
Type::Map(_) => todo!(),
Type::String => todo!(),
Type::Range => todo!(),
_ => {
return Err(ValidationError::TypeCheck { return Err(ValidationError::TypeCheck {
expected: Type::Collection, expected: Type::Collection,
actual: collection_type, actual: collection_type,
position: self.source_position, position: self.source_position,
}); });
}
}; };
let key = self.item_id.clone(); let key = self.item_id.clone();
@ -116,6 +122,7 @@ impl AbstractTree for For {
})?; })?;
} else { } else {
for value in list.items()?.iter() { for value in list.items()?.iter() {
self.context.add_allowance(key)?;
self.context.set_value(key.clone(), value.clone())?; self.context.set_value(key.clone(), value.clone())?;
self.block.run(source, &self.context)?; self.block.run(source, &self.context)?;
} }

View File

@ -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 { match self {
IndexExpression::Value(value_node) => value_node.validate(_source, _context), IndexExpression::Value(value_node) => value_node.validate(_source, context),
IndexExpression::Identifier(identifier) => identifier.validate(_source, _context), IndexExpression::Identifier(identifier) => {
IndexExpression::Index(index) => index.validate(_source, _context), context.add_allowance(identifier)?;
Ok(())
}
IndexExpression::Index(index) => index.validate(_source, context),
IndexExpression::FunctionCall(function_call) => { IndexExpression::FunctionCall(function_call) => {
function_call.validate(_source, _context) function_call.validate(_source, context)
} }
} }
} }

View File

@ -210,6 +210,15 @@ impl AbstractTree for Type {
Type::ListOf(Box::new(item_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, "any" => Type::Any,
"bool" => Type::Boolean, "bool" => Type::Boolean,
"collection" => Type::Collection, "collection" => Type::Collection,
@ -247,7 +256,8 @@ impl AbstractTree for Type {
"str" => Type::String, "str" => Type::String,
_ => { _ => {
return Err(SyntaxError::UnexpectedSyntaxNode { 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(), actual: type_node.kind().to_string(),
position: node.range().into(), position: node.range().into(),
}) })

View File

@ -104,7 +104,18 @@ impl Value {
Value::Boolean(_) => Type::Boolean, Value::Boolean(_) => Type::Boolean,
Value::Range(_) => todo!(), Value::Range(_) => todo!(),
Value::Struct(_) => 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) Ok(r#type)

View File

@ -11,6 +11,7 @@ fn override_built_ins() {
} }
my_option <Option> = Option::Some('foo') my_option <Option> = Option::Some('foo')
my_option
" "
), ),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(

View File

@ -53,3 +53,30 @@ fn nested_enum() {
))) )))
); );
} }
#[test]
fn enum_with_argument() {
let result = interpret(
"
enum FooBar<T> {
Foo<T>,
Bar,
}
Foobar::Bar(Fizzbuzz::Fizz)
",
);
assert_eq!(
result,
Ok(Value::Enum(EnumInstance::new(
Identifier::new("Foobar"),
Identifier::new("Bar"),
Some(Value::Enum(EnumInstance::new(
Identifier::new("Fizzbuzz"),
Identifier::new("Fizz"),
Some(Value::none())
)))
)))
);
}