lang: Add a for loop statement for iterating over a list
This adds a for statement which is used to iterate over a list with a body of statements. This is an important data transformation tool which should be used sparingly, but is important to have. An import statement inside of a for loop is not currently supported. We have a simple hack to detect the obvious cases, but more deeply nested scenarios probably won't be caught, and you'll get an obscure error message if you try to do this. This was incredibly challenging to get right, and it's all thanks to Sam for his brilliance. Co-authored-by: Samuel Gélineau <gelisam@gmail.com>
This commit is contained in:
@@ -339,11 +339,54 @@ func trueCallee(apparentCallee interfaces.Expr) interfaces.Expr {
|
||||
return trueCallee(x.Definition)
|
||||
case *ExprSingleton:
|
||||
return trueCallee(x.Definition)
|
||||
case *ExprIterated:
|
||||
return trueCallee(x.Definition)
|
||||
case *ExprPoly: // XXX: Did we want this one added too?
|
||||
return trueCallee(x.Definition)
|
||||
|
||||
default:
|
||||
return apparentCallee
|
||||
}
|
||||
}
|
||||
|
||||
// findExprPoly is a helper used in SetScope.
|
||||
func findExprPoly(apparentCallee interfaces.Expr) *ExprPoly {
|
||||
switch x := apparentCallee.(type) {
|
||||
case *ExprTopLevel:
|
||||
return findExprPoly(x.Definition)
|
||||
case *ExprSingleton:
|
||||
return findExprPoly(x.Definition)
|
||||
case *ExprIterated:
|
||||
return findExprPoly(x.Definition)
|
||||
case *ExprPoly:
|
||||
return x // found it!
|
||||
default:
|
||||
return nil // not found!
|
||||
}
|
||||
}
|
||||
|
||||
// newExprParam is a helper function to create an ExprParam with the internal
|
||||
// key set to the pointer of the thing we're creating.
|
||||
func newExprParam(name string, typ *types.Type) *ExprParam {
|
||||
expr := &ExprParam{
|
||||
Name: name,
|
||||
typ: typ,
|
||||
}
|
||||
expr.envKey = expr
|
||||
return expr
|
||||
}
|
||||
|
||||
// newExprIterated is a helper function to create an ExprIterated with the
|
||||
// internal key set to the pointer of the thing we're creating.
|
||||
func newExprIterated(name string, definition interfaces.Expr) *ExprIterated {
|
||||
expr := &ExprIterated{
|
||||
Name: name,
|
||||
Definition: definition,
|
||||
}
|
||||
expr.envKey = expr
|
||||
return expr
|
||||
}
|
||||
|
||||
// variableScopeFeedback logs some messages about what is actually in scope so
|
||||
// that the user gets a hint about what's going on. This is useful for catching
|
||||
// bugs in our programming or in user code!
|
||||
|
||||
Reference in New Issue
Block a user