Beispiel #1
0
func (p *parser) parseReturnStmt(n *parse.Node) ast.Stmt {
	ret := ast.ReturnStmt{
		Return: token.Pos(n.Child(0).Pos()),
	}
	if n.ChildCount() > 1 {
		ret.Results = p.parseExprList(n.Child(1))
	}
	return &ret
}
Beispiel #2
0
func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
	if a.fnType == nil {
		a.diag("cannot return at the top level")
		return
	}

	if len(s.Results) == 0 && (len(a.fnType.Out) == 0 || a.outVarsNamed) {
		// Simple case.  Simply exit from the function.
		a.flow.putTerm()
		a.push(func(v *Thread) { v.pc = returnPC })
		return
	}

	bc := a.enterChild()
	defer bc.exit()

	// Compile expressions
	bad := false
	rs := make([]*expr, len(s.Results))
	for i, re := range s.Results {
		rs[i] = a.compileExpr(bc.block, false, re)
		if rs[i] == nil {
			bad = true
		}
	}
	if bad {
		return
	}

	// Create assigner

	// However, if the expression list in the "return" statement
	// is a single call to a multi-valued function, the values
	// returned from the called function will be returned from
	// this one.
	assign := a.compileAssign(s.Pos(), bc.block, NewMultiType(a.fnType.Out), rs, "return", "value")

	// XXX(Spec) "The result types of the current function and the
	// called function must match."  Match is fuzzy.  It should
	// say that they must be assignment compatible.

	// Compile
	start := len(a.fnType.In)
	nout := len(a.fnType.Out)
	a.flow.putTerm()
	a.push(func(t *Thread) {
		assign(multiV(t.f.Vars[start:start+nout]), t)
		t.pc = returnPC
	})
}
Beispiel #3
0
func (f *File) validRetStmt(ret *ast.ReturnStmt) *Error {
	// returning nothing is ok
	if ret.Results == nil || len(ret.Results) == 0 {
		return nil
	}
	// Cannot return multiple values
	if len(ret.Results) > 1 {
		return &Error{errors.New("Return statements can only have one result"), ret.Pos()}
	}
	expr := ret.Results[0]
	if err := f.validRetExpr(expr); err != nil {
		return err
	}
	return nil
}