func makeRecur(node *parser.CallNode) *ast.CallExpr { bindings := makeBindings(node.Args[0].(*parser.VectorNode), token.ASSIGN) loopUpdate := makeAssignStmt(h.E(EvalExpr(node.Args[1])), h.E(ast.NewIdent("true")), token.ASSIGN) body := append(h.EmptyS(), bindings...) body = append(body, loopUpdate, makeReturnStmt(h.E(ast.NewIdent("nil")))) resultType := makeFieldList([]*ast.Field{makeField(nil, anyType)}) fnType := makeFuncType(resultType, nil) fn := makeFuncLit(fnType, makeBlockStmt(body)) return makeFuncCall(fn, h.EmptyE()) }
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 makeIfStmtFunc(node *parser.CallNode) ast.Expr { var elseBody ast.Stmt if len(node.Args) > 2 { elseBody = makeBlockStmt(h.S(makeReturnStmt(h.E(EvalExpr(node.Args[2]))))) } else { elseBody = makeBlockStmt(h.S(makeReturnStmt(h.E(ast.NewIdent("nil"))))) } cond := EvalExpr(node.Args[0]) ifBody := makeBlockStmt(h.S(makeReturnStmt(h.E(EvalExpr(node.Args[1]))))) ifStmt := makeIfStmt(cond, ifBody, elseBody) fnBody := makeBlockStmt(h.S(ifStmt)) returnList := makeFieldList([]*ast.Field{makeField(nil, anyType)}) fnType := makeFuncType(returnList, nil) fn := makeFuncLit(fnType, fnBody) return makeFuncCall(fn, h.EmptyE()) }
func makeLetFun(node *parser.CallNode) ast.Expr { bindings := makeBindings(node.Args[0].(*parser.VectorNode), token.DEFINE) body := append(bindings, wrapExprsWithStmt(EvalExprs(node.Args[1:]))...) body[len(body)-1] = makeReturnStmt(h.E(body[len(body)-1].(*ast.ExprStmt).X)) fieldList := makeFieldList([]*ast.Field{makeField(nil, anyType)}) typ := makeFuncType(fieldList, nil) fn := makeFuncLit(typ, makeBlockStmt(body)) return makeFuncCall(fn, h.EmptyE()) }
func makeBindings(bindings *parser.VectorNode, assignmentType token.Token) []ast.Stmt { assignments := make([]ast.Stmt, len(bindings.Nodes)) for i, bind := range bindings.Nodes { b := bind.(*parser.VectorNode) idents := b.Nodes[:len(b.Nodes)-1] vars := make([]ast.Expr, len(idents)) for j, ident := range idents { vars[j] = makeIdomaticSelector(ident.(*parser.IdentNode).Ident) } assignments[i] = makeAssignStmt(vars, h.E(EvalExpr(b.Nodes[len(b.Nodes)-1])), assignmentType) } return assignments }
func makeFuncBody(exprs []ast.Expr) *ast.BlockStmt { wrapped := wrapExprsWithStmt(exprs) wrapped[len(wrapped)-1] = makeReturnStmt(h.E(wrapped[len(wrapped)-1].(*ast.ExprStmt).X)) return makeBlockStmt(wrapped) }