예제 #1
0
파일: funcs.go 프로젝트: sunclx/gsp
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())
}
예제 #2
0
파일: funcs.go 프로젝트: sunclx/gsp
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())
}
예제 #3
0
파일: makers.go 프로젝트: sunclx/gsp
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())
}
예제 #4
0
파일: makers.go 프로젝트: sunclx/gsp
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())
}
예제 #5
0
파일: makers.go 프로젝트: sunclx/gsp
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
}
예제 #6
0
파일: funcs.go 프로젝트: sunclx/gsp
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)
}