For loop with only a condition fails with "type error: object is not iterable (got bool)"
As documented in the syntax, for loops are supposed to support the for <cond> { ... } format (https://risor.io/docs/syntax#loops). However, if the condition is a call, it fails with the error mentioned in the issue title. For example:
for strings.contains("abc", "a") {
print("ok")
}
I believe the issue is in this block: https://github.com/risor-io/risor/blob/b83ab51d638a6041e7e0e10e002b69f1e1c8e080/compiler/compiler.go#L1393-L1420 . I think it should compile as compileForCondition.
The AST for the condition is of type *ast.ObjectCall, which falls to the default case and calls compileForRange, which emits the GetIter opcode and it expects an iterable, resulting in the error message since the value is not iterable (a boolean).
I've investigated this a bit to see if I could send a PR, but I'm not familiar enough with the AST to make sure I cover all cases... For example, this seems to solve this particular *ast.ObjectCall case:
case *ast.ObjectCall:
return c.compileForCondition(node, cond)
However, it will still fail for e.g. for true { .... }, so another case needed would be *ast.Bool. But then, it should work for other values (the Object interface defines an IsTruthy method, so it looks like there's a concept of "truthy" vs "falsy" values in Risor, so for "abc" { ... } should probably work too), and for variables, so it would require also the *ast.Ident case...
Maybe it's just that the default case should be a condition? I.e. if there's no Init nor Post defined in the for loop, then it's either a for <cond> or a for range, and the for range is covered by the other cases?
All this to say, I don't know the expected syntax and semantics of the language well enough to send a PR, but hopefully that explains a bit more the issue. Happy to test things out if it can help with the fix!
Martin
Thank you for reporting this! I should be able to fit it soon.