func makeLoop(node *parser.CallNode) *ast.CallExpr { returnIdent := generateIdent() loopIdent := generateIdent() fnBody := h.EmptyS() bindingsVector := node.Args[0].(*parser.VectorNode) addRecurLabelAndBindings(parser.NewIdentNode(loopIdent.String()), bindingsVector.Copy().(*parser.VectorNode), node.Args[1:]) bindings := makeBindings(bindingsVector, token.DEFINE) returnIdentValueSpec := makeValueSpec(h.I(returnIdent), nil, anyType) returnIdentDecl := makeDeclStmt(makeGeneralDecl(token.VAR, []ast.Spec{returnIdentValueSpec})) fnBody = append(fnBody, bindings...) fnBody = append(fnBody, returnIdentDecl) init := makeAssignStmt(h.E(loopIdent), h.E(ast.NewIdent("true")), token.DEFINE) forBody := h.EmptyS() forBody = append(forBody, makeAssignStmt(h.E(loopIdent), h.E(ast.NewIdent("false")), token.ASSIGN)) forBody = append(forBody, wrapExprsWithStmt(EvalExprs(node.Args[1:len(node.Args)-1]))...) forBody = append(forBody, makeAssignStmt(h.E(returnIdent), h.E(EvalExpr(node.Args[len(node.Args)-1])), token.ASSIGN)) forStmt := makeForStmt(init, nil, loopIdent, makeBlockStmt(forBody)) fnBody = append(fnBody, forStmt) fnBody = append(fnBody, makeReturnStmt(h.E(returnIdent))) results := makeFieldList([]*ast.Field{makeField(nil, anyType)}) fnType := makeFuncType(results, nil) fn := makeFuncLit(fnType, makeBlockStmt(fnBody)) return makeFuncCall(fn, h.EmptyE()) }
func evalFuncCall(node *parser.CallNode) ast.Expr { switch { case isUnaryOperator(node): return makeUnaryExpr(unaryOperatorMap[node.Callee.(*parser.IdentNode).Ident], EvalExpr(node.Args[0])) case isCallableOperator(node): return makeNAryCallableExpr(node) case isLogicOperator(node): return makeNAryLogicExpr(node) case isLoop(node): return makeLoop(node) case isRecur(node): return makeRecur(node) case isAssert(node): return makeAssert(node) case isCoreFunc(node): return makeCoreCall(node) case checkLetArgs(node): return makeLetFun(node) case checkIfArgs(node): return makeIfStmtFunc(node) case checkFuncArgs(node): // TODO: In case of type annotations change the following returnField := []*ast.Field{makeField(nil, anyType)} results := makeFieldList(returnField) argIdents, ellipsis := getArgIdentsFromVector(node.Args[0].(*parser.VectorNode)) params := make([]*ast.Field, 0, len(argIdents)) if len(argIdents) != 0 { params = append(params, makeField(argIdents, anyType)) } if ellipsis != nil { params = append(params, makeField(h.I(ellipsis), makeEllipsis(anyType))) } fnType := makeFuncType(results, makeFieldList(params)) body := makeFuncBody(EvalExprs(node.Args[1:])) return makeFuncLit(fnType, body) case checkDefArgs(node): panic("you can't have a def within an expression!") case checkNSArgs(node): panic("you can't define a namespace in an expression!") } callee := EvalExpr(node.Callee) args := EvalExprs(node.Args) if c, ok := callee.(*ast.Ident); ok { callee = makeIdomaticIdent(c.Name) field := &ast.Field{Type: &ast.Ident{Name: "core.Any"}} fields := []*ast.Field{} for _, _ = range node.Args { fields = append(fields, field) } callee = &ast.TypeAssertExpr{ X: &ast.CallExpr{ Fun: &ast.Ident{Name: "core.Any"}, Args: []ast.Expr{callee}, }, Type: &ast.FuncType{ Params: &ast.FieldList{ List: fields, }, Results: &ast.FieldList{ List: []*ast.Field{ &ast.Field{Type: &ast.Ident{Name: "core.Any"}}, }, }, }, } } return makeFuncCall(callee, args) }