Exemplo n.º 1
0
Arquivo: funcs.go Projeto: 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())
}
Exemplo n.º 2
0
Arquivo: funcs.go Projeto: sunclx/gsp
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)
}