github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/compile/internal/gc/noder.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"fmt"
     9  	"strconv"
    10  	"strings"
    11  	"unicode/utf8"
    12  
    13  	"cmd/compile/internal/syntax"
    14  )
    15  
    16  func parseFile(filename string) {
    17  	p := noder{baseline: lexlineno}
    18  	file, err := syntax.ReadFile(filename, p.error, p.pragma, 0)
    19  	if err != nil {
    20  		Fatalf("syntax.ReadFile %s: %v", filename, err)
    21  	}
    22  
    23  	p.file(file)
    24  
    25  	if !imported_unsafe {
    26  		for _, x := range p.linknames {
    27  			p.error(0, x, "//go:linkname only allowed in Go files that import \"unsafe\"")
    28  		}
    29  	}
    30  
    31  	if nsyntaxerrors == 0 {
    32  		testdclstack()
    33  	}
    34  }
    35  
    36  // noder transforms package syntax's AST into a Nod tree.
    37  type noder struct {
    38  	baseline  int32
    39  	linknames []int // tracks //go:linkname lines
    40  }
    41  
    42  func (p *noder) file(file *syntax.File) {
    43  	p.lineno(file.PkgName)
    44  	mkpackage(file.PkgName.Value)
    45  
    46  	xtop = append(xtop, p.decls(file.DeclList)...)
    47  
    48  	lexlineno = p.baseline + int32(file.Lines) - 1
    49  	lineno = lexlineno
    50  }
    51  
    52  func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
    53  	var lastConstGroup *syntax.Group
    54  	var lastConstRHS []*Node
    55  	var iotaVal int64
    56  
    57  	for _, decl := range decls {
    58  		p.lineno(decl)
    59  		switch decl := decl.(type) {
    60  		case *syntax.ImportDecl:
    61  			p.importDecl(decl)
    62  
    63  		case *syntax.AliasDecl:
    64  			p.aliasDecl(decl)
    65  
    66  		case *syntax.VarDecl:
    67  			l = append(l, p.varDecl(decl)...)
    68  
    69  		case *syntax.ConstDecl:
    70  			// Tricky to handle golang.org/issue/15550 correctly.
    71  
    72  			prevIota := iota_
    73  
    74  			if decl.Group == nil || decl.Group != lastConstGroup {
    75  				iotaVal = 0
    76  				lastConstRHS = nil
    77  			}
    78  
    79  			iota_ = iotaVal
    80  			lastconst = lastConstRHS
    81  
    82  			l = append(l, p.constDecl(decl)...)
    83  
    84  			lastConstRHS = lastconst
    85  			lastconst = nil
    86  
    87  			iota_ = prevIota
    88  			iotaVal++
    89  
    90  			lastConstGroup = decl.Group
    91  
    92  		case *syntax.TypeDecl:
    93  			l = append(l, p.typeDecl(decl))
    94  
    95  		case *syntax.FuncDecl:
    96  			l = append(l, p.funcDecl(decl))
    97  
    98  		default:
    99  			panic("unhandled Decl")
   100  		}
   101  	}
   102  
   103  	return
   104  }
   105  
   106  func (p *noder) importDecl(imp *syntax.ImportDecl) {
   107  	val := p.basicLit(imp.Path)
   108  	importfile(&val, nil)
   109  	ipkg := importpkg
   110  	importpkg = nil
   111  
   112  	if ipkg == nil {
   113  		if nerrors == 0 {
   114  			Fatalf("phase error in import")
   115  		}
   116  		return
   117  	}
   118  
   119  	ipkg.Direct = true
   120  
   121  	var my *Sym
   122  	if imp.LocalPkgName != nil {
   123  		my = p.name(imp.LocalPkgName)
   124  	} else {
   125  		my = lookup(ipkg.Name)
   126  	}
   127  
   128  	pack := p.nod(imp, OPACK, nil, nil)
   129  	pack.Sym = my
   130  	pack.Name.Pkg = ipkg
   131  
   132  	if my.Name == "." {
   133  		importdot(ipkg, pack)
   134  		return
   135  	}
   136  	if my.Name == "init" {
   137  		yyerrorl(pack.Lineno, "cannot import package as init - init must be a func")
   138  		return
   139  	}
   140  	if my.Name == "_" {
   141  		return
   142  	}
   143  	if my.Def != nil {
   144  		lineno = pack.Lineno
   145  		redeclare(my, "as imported package name")
   146  	}
   147  	my.Def = pack
   148  	my.Lastlineno = pack.Lineno
   149  	my.Block = 1 // at top level
   150  }
   151  
   152  func (p *noder) aliasDecl(decl *syntax.AliasDecl) {
   153  	// Because alias declarations must refer to imported entities
   154  	// which are already set up, we can do all checks right here.
   155  	// We won't know anything about entities that have not been
   156  	// declared yet, but since they cannot have been imported, we
   157  	// know there's an error and we don't care about the details.
   158  
   159  	// The original entity must be denoted by a qualified identifier.
   160  	// (The parser doesn't make this restriction to be more error-
   161  	// tolerant.)
   162  	qident, ok := decl.Orig.(*syntax.SelectorExpr)
   163  	if !ok {
   164  		// TODO(gri) This prints a dot-imported object with qualification
   165  		//           (confusing error). Fix this.
   166  		yyerror("invalid alias: %v is not a package-qualified identifier", p.expr(decl.Orig))
   167  		return
   168  	}
   169  
   170  	pkg := p.expr(qident.X)
   171  	if pkg.Op != OPACK {
   172  		yyerror("invalid alias: %v is not a package", pkg)
   173  		return
   174  	}
   175  	pkg.Used = true
   176  
   177  	// Resolve original entity
   178  	orig := oldname(restrictlookup(qident.Sel.Value, pkg.Name.Pkg))
   179  	if orig.Sym.Flags&SymAlias != 0 {
   180  		Fatalf("original %v marked as alias", orig.Sym)
   181  	}
   182  
   183  	// An alias declaration must not refer to package unsafe.
   184  	if orig.Sym.Pkg == unsafepkg {
   185  		yyerror("invalid alias: %v refers to package unsafe (%v)", decl.Name.Value, orig)
   186  		return
   187  	}
   188  
   189  	// The aliased entity must be from a matching constant, type, variable,
   190  	// or function declaration, respectively.
   191  	var what string
   192  	switch decl.Tok {
   193  	case syntax.Const:
   194  		if orig.Op != OLITERAL {
   195  			what = "constant"
   196  		}
   197  	case syntax.Type:
   198  		if orig.Op != OTYPE {
   199  			what = "type"
   200  		}
   201  	case syntax.Var:
   202  		if orig.Op != ONAME || orig.Class != PEXTERN {
   203  			what = "variable"
   204  		}
   205  	case syntax.Func:
   206  		if orig.Op != ONAME || orig.Class != PFUNC {
   207  			what = "function"
   208  		}
   209  	default:
   210  		Fatalf("unexpected token: %s", decl.Tok)
   211  	}
   212  	if what != "" {
   213  		yyerror("invalid alias: %v is not a %s", orig, what)
   214  		return
   215  	}
   216  
   217  	// handle special cases
   218  	switch decl.Name.Value {
   219  	case "_":
   220  		return // don't declare blank aliases
   221  	case "init":
   222  		yyerror("cannot declare init - must be non-alias function declaration")
   223  		return
   224  	}
   225  
   226  	// declare alias
   227  	// (this is similar to handling dot imports)
   228  	asym := p.name(decl.Name)
   229  	if asym.Def != nil {
   230  		redeclare(asym, "in alias declaration")
   231  		return
   232  	}
   233  	asym.Flags |= SymAlias
   234  	asym.Def = orig
   235  	asym.Block = block
   236  	asym.Lastlineno = lineno
   237  
   238  	if exportname(asym.Name) {
   239  		// TODO(gri) newname(asym) is only needed to satisfy exportsym
   240  		// (and indirectly, exportlist). We should be able to just
   241  		// collect the Syms, eventually.
   242  		exportsym(newname(asym))
   243  	}
   244  }
   245  
   246  func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
   247  	names := p.declNames(decl.NameList)
   248  
   249  	var typ *Node
   250  	if decl.Type != nil {
   251  		typ = p.typeExpr(decl.Type)
   252  	}
   253  
   254  	var exprs []*Node
   255  	if decl.Values != nil {
   256  		exprs = p.exprList(decl.Values)
   257  	}
   258  
   259  	p.lineno(decl)
   260  	return variter(names, typ, exprs)
   261  }
   262  
   263  func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
   264  	names := p.declNames(decl.NameList)
   265  
   266  	var typ *Node
   267  	if decl.Type != nil {
   268  		typ = p.typeExpr(decl.Type)
   269  	}
   270  
   271  	var exprs []*Node
   272  	if decl.Values != nil {
   273  		exprs = p.exprList(decl.Values)
   274  	}
   275  
   276  	return constiter(names, typ, exprs)
   277  }
   278  
   279  func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
   280  	name := typedcl0(p.name(decl.Name))
   281  	name.Name.Param.Pragma = Pragma(decl.Pragma)
   282  
   283  	var typ *Node
   284  	if decl.Type != nil {
   285  		typ = p.typeExpr(decl.Type)
   286  	}
   287  
   288  	return typedcl1(name, typ, true)
   289  }
   290  
   291  func (p *noder) declNames(names []*syntax.Name) []*Node {
   292  	var nodes []*Node
   293  	for _, name := range names {
   294  		nodes = append(nodes, p.declName(name))
   295  	}
   296  	return nodes
   297  }
   298  
   299  func (p *noder) declName(name *syntax.Name) *Node {
   300  	// TODO(mdempsky): Set lineno?
   301  	return dclname(p.name(name))
   302  }
   303  
   304  func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
   305  	f := p.funcHeader(fun)
   306  	if f == nil {
   307  		return nil
   308  	}
   309  
   310  	var body []*Node
   311  	if fun.Body != nil {
   312  		body = p.stmts(fun.Body)
   313  		if body == nil {
   314  			body = []*Node{p.nod(fun, OEMPTY, nil, nil)}
   315  		}
   316  	}
   317  
   318  	pragma := Pragma(fun.Pragma)
   319  
   320  	f.Nbody.Set(body)
   321  	f.Noescape = pragma&Noescape != 0
   322  	if f.Noescape && len(body) != 0 {
   323  		yyerror("can only use //go:noescape with external func implementations")
   324  	}
   325  	f.Func.Pragma = pragma
   326  	lineno = p.baseline + int32(fun.EndLine) - 1
   327  	f.Func.Endlineno = lineno
   328  
   329  	funcbody(f)
   330  
   331  	return f
   332  }
   333  
   334  func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
   335  	name := p.name(fun.Name)
   336  	t := p.signature(fun.Recv, fun.Type)
   337  	f := p.nod(fun, ODCLFUNC, nil, nil)
   338  
   339  	if fun.Recv == nil {
   340  		// FunctionName Signature
   341  		if name.Name == "init" {
   342  			name = renameinit()
   343  			if t.List.Len() > 0 || t.Rlist.Len() > 0 {
   344  				yyerror("func init must have no arguments and no return values")
   345  			}
   346  		}
   347  
   348  		if localpkg.Name == "main" && name.Name == "main" {
   349  			if t.List.Len() > 0 || t.Rlist.Len() > 0 {
   350  				yyerror("func main must have no arguments and no return values")
   351  			}
   352  		}
   353  
   354  		f.Func.Nname = newfuncname(name)
   355  	} else {
   356  		// Receiver MethodName Signature
   357  
   358  		f.Func.Shortname = newfuncname(name)
   359  		f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
   360  	}
   361  
   362  	f.Func.Nname.Name.Defn = f
   363  	f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
   364  
   365  	declare(f.Func.Nname, PFUNC)
   366  	funchdr(f)
   367  	return f
   368  }
   369  
   370  func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node {
   371  	n := p.nod(typ, OTFUNC, nil, nil)
   372  	if recv != nil {
   373  		n.Left = p.param(recv, false, false)
   374  	}
   375  	n.List.Set(p.params(typ.ParamList, true))
   376  	n.Rlist.Set(p.params(typ.ResultList, false))
   377  	return n
   378  }
   379  
   380  func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node {
   381  	var nodes []*Node
   382  	for i, param := range params {
   383  		p.lineno(param)
   384  		nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
   385  	}
   386  	return nodes
   387  }
   388  
   389  func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node {
   390  	var name *Node
   391  	if param.Name != nil {
   392  		name = p.newname(param.Name)
   393  	}
   394  
   395  	typ := p.typeExpr(param.Type)
   396  	n := p.nod(param, ODCLFIELD, name, typ)
   397  
   398  	// rewrite ...T parameter
   399  	if typ.Op == ODDD {
   400  		if !dddOk {
   401  			yyerror("cannot use ... in receiver or result parameter list")
   402  		} else if !final {
   403  			yyerror("can only use ... with final parameter in list")
   404  		}
   405  		typ.Op = OTARRAY
   406  		typ.Right = typ.Left
   407  		typ.Left = nil
   408  		n.Isddd = true
   409  		if n.Left != nil {
   410  			n.Left.Isddd = true
   411  		}
   412  	}
   413  
   414  	return n
   415  }
   416  
   417  func (p *noder) exprList(expr syntax.Expr) []*Node {
   418  	if list, ok := expr.(*syntax.ListExpr); ok {
   419  		return p.exprs(list.ElemList)
   420  	}
   421  	return []*Node{p.expr(expr)}
   422  }
   423  
   424  func (p *noder) exprs(exprs []syntax.Expr) []*Node {
   425  	var nodes []*Node
   426  	for _, expr := range exprs {
   427  		nodes = append(nodes, p.expr(expr))
   428  	}
   429  	return nodes
   430  }
   431  
   432  func (p *noder) expr(expr syntax.Expr) *Node {
   433  	p.lineno(expr)
   434  	switch expr := expr.(type) {
   435  	case nil:
   436  		return nil
   437  	case *syntax.Name:
   438  		return p.mkname(expr)
   439  	case *syntax.BasicLit:
   440  		return p.setlineno(expr, nodlit(p.basicLit(expr)))
   441  
   442  	case *syntax.CompositeLit:
   443  		n := p.nod(expr, OCOMPLIT, nil, nil)
   444  		if expr.Type != nil {
   445  			n.Right = p.expr(expr.Type)
   446  		}
   447  		l := p.exprs(expr.ElemList)
   448  		for i, e := range l {
   449  			l[i] = p.wrapname(expr.ElemList[i], e)
   450  		}
   451  		n.List.Set(l)
   452  		lineno = p.baseline + int32(expr.EndLine) - 1
   453  		return n
   454  	case *syntax.KeyValueExpr:
   455  		return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
   456  	case *syntax.FuncLit:
   457  		closurehdr(p.typeExpr(expr.Type))
   458  		body := p.stmts(expr.Body)
   459  		lineno = p.baseline + int32(expr.EndLine) - 1
   460  		return p.setlineno(expr, closurebody(body))
   461  	case *syntax.ParenExpr:
   462  		return p.nod(expr, OPAREN, p.expr(expr.X), nil)
   463  	case *syntax.SelectorExpr:
   464  		// parser.new_dotname
   465  		obj := p.expr(expr.X)
   466  		if obj.Op == OPACK {
   467  			obj.Used = true
   468  			return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg))
   469  		}
   470  		return p.setlineno(expr, nodSym(OXDOT, obj, p.name(expr.Sel)))
   471  	case *syntax.IndexExpr:
   472  		return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index))
   473  	case *syntax.SliceExpr:
   474  		op := OSLICE
   475  		if expr.Full {
   476  			op = OSLICE3
   477  		}
   478  		n := p.nod(expr, op, p.expr(expr.X), nil)
   479  		var index [3]*Node
   480  		for i, x := range expr.Index {
   481  			if x != nil {
   482  				index[i] = p.expr(x)
   483  			}
   484  		}
   485  		n.SetSliceBounds(index[0], index[1], index[2])
   486  		return n
   487  	case *syntax.AssertExpr:
   488  		if expr.Type == nil {
   489  			panic("unexpected AssertExpr")
   490  		}
   491  		// TODO(mdempsky): parser.pexpr uses p.expr(), but
   492  		// seems like the type field should be parsed with
   493  		// ntype? Shrug, doesn't matter here.
   494  		return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.expr(expr.Type))
   495  	case *syntax.Operation:
   496  		x := p.expr(expr.X)
   497  		if expr.Y == nil {
   498  			if expr.Op == syntax.And {
   499  				x = unparen(x) // TODO(mdempsky): Needed?
   500  				if x.Op == OCOMPLIT {
   501  					// Special case for &T{...}: turn into (*T){...}.
   502  					// TODO(mdempsky): Switch back to p.nod after we
   503  					// get rid of gcCompat.
   504  					x.Right = nod(OIND, x.Right, nil)
   505  					x.Right.Implicit = true
   506  					return x
   507  				}
   508  			}
   509  			return p.nod(expr, p.unOp(expr.Op), x, nil)
   510  		}
   511  		return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y))
   512  	case *syntax.CallExpr:
   513  		n := p.nod(expr, OCALL, p.expr(expr.Fun), nil)
   514  		n.List.Set(p.exprs(expr.ArgList))
   515  		n.Isddd = expr.HasDots
   516  		return n
   517  
   518  	case *syntax.ArrayType:
   519  		var len *Node
   520  		if expr.Len != nil {
   521  			len = p.expr(expr.Len)
   522  		} else {
   523  			len = p.nod(expr, ODDD, nil, nil)
   524  		}
   525  		return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem))
   526  	case *syntax.SliceType:
   527  		return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem))
   528  	case *syntax.DotsType:
   529  		return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil)
   530  	case *syntax.StructType:
   531  		return p.structType(expr)
   532  	case *syntax.InterfaceType:
   533  		return p.interfaceType(expr)
   534  	case *syntax.FuncType:
   535  		return p.signature(nil, expr)
   536  	case *syntax.MapType:
   537  		return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))
   538  	case *syntax.ChanType:
   539  		n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil)
   540  		n.Etype = EType(p.chanDir(expr.Dir))
   541  		return n
   542  
   543  	case *syntax.TypeSwitchGuard:
   544  		n := p.nod(expr, OTYPESW, nil, p.expr(expr.X))
   545  		if expr.Lhs != nil {
   546  			n.Left = p.declName(expr.Lhs)
   547  			if isblank(n.Left) {
   548  				yyerror("invalid variable name %v in type switch", n.Left)
   549  			}
   550  		}
   551  		return n
   552  	}
   553  	panic("unhandled Expr")
   554  }
   555  
   556  func (p *noder) typeExpr(typ syntax.Expr) *Node {
   557  	// TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
   558  	return p.expr(typ)
   559  }
   560  
   561  func (p *noder) chanDir(dir syntax.ChanDir) ChanDir {
   562  	switch dir {
   563  	case 0:
   564  		return Cboth
   565  	case syntax.SendOnly:
   566  		return Csend
   567  	case syntax.RecvOnly:
   568  		return Crecv
   569  	}
   570  	panic("unhandled ChanDir")
   571  }
   572  
   573  func (p *noder) structType(expr *syntax.StructType) *Node {
   574  	var l []*Node
   575  	for i, field := range expr.FieldList {
   576  		p.lineno(field)
   577  		var n *Node
   578  		if field.Name == nil {
   579  			n = p.embedded(field.Type)
   580  		} else {
   581  			n = p.nod(field, ODCLFIELD, p.newname(field.Name), p.typeExpr(field.Type))
   582  		}
   583  		if i < len(expr.TagList) && expr.TagList[i] != nil {
   584  			n.SetVal(p.basicLit(expr.TagList[i]))
   585  		}
   586  		l = append(l, n)
   587  	}
   588  
   589  	p.lineno(expr)
   590  	n := p.nod(expr, OTSTRUCT, nil, nil)
   591  	n.List.Set(l)
   592  	return n
   593  }
   594  
   595  func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node {
   596  	var l []*Node
   597  	for _, method := range expr.MethodList {
   598  		p.lineno(method)
   599  		var n *Node
   600  		if method.Name == nil {
   601  			n = p.nod(method, ODCLFIELD, nil, oldname(p.packname(method.Type)))
   602  		} else {
   603  			mname := p.newname(method.Name)
   604  			sig := p.typeExpr(method.Type)
   605  			sig.Left = fakethis()
   606  			n = p.nod(method, ODCLFIELD, mname, sig)
   607  			ifacedcl(n)
   608  		}
   609  		l = append(l, n)
   610  	}
   611  
   612  	n := p.nod(expr, OTINTER, nil, nil)
   613  	n.List.Set(l)
   614  	return n
   615  }
   616  
   617  func (p *noder) packname(expr syntax.Expr) *Sym {
   618  	switch expr := expr.(type) {
   619  	case *syntax.Name:
   620  		name := p.name(expr)
   621  		if n := oldname(name); n.Name != nil && n.Name.Pack != nil {
   622  			n.Name.Pack.Used = true
   623  		}
   624  		return name
   625  	case *syntax.SelectorExpr:
   626  		name := p.name(expr.X.(*syntax.Name))
   627  		var pkg *Pkg
   628  		if name.Def == nil || name.Def.Op != OPACK {
   629  			yyerror("%v is not a package", name)
   630  			pkg = localpkg
   631  		} else {
   632  			name.Def.Used = true
   633  			pkg = name.Def.Name.Pkg
   634  		}
   635  		return restrictlookup(expr.Sel.Value, pkg)
   636  	}
   637  	panic(fmt.Sprintf("unexpected packname: %#v", expr))
   638  }
   639  
   640  func (p *noder) embedded(typ syntax.Expr) *Node {
   641  	op, isStar := typ.(*syntax.Operation)
   642  	if isStar {
   643  		if op.Op != syntax.Mul || op.Y != nil {
   644  			panic("unexpected Operation")
   645  		}
   646  		typ = op.X
   647  	}
   648  	n := embedded(p.packname(typ), localpkg)
   649  	if isStar {
   650  		n.Right = p.nod(op, OIND, n.Right, nil)
   651  	}
   652  	return n
   653  }
   654  
   655  func (p *noder) stmts(stmts []syntax.Stmt) []*Node {
   656  	var nodes []*Node
   657  	for _, stmt := range stmts {
   658  		s := p.stmt(stmt)
   659  		if s == nil {
   660  		} else if s.Op == OBLOCK && s.Ninit.Len() == 0 {
   661  			nodes = append(nodes, s.List.Slice()...)
   662  		} else {
   663  			nodes = append(nodes, s)
   664  		}
   665  	}
   666  	return nodes
   667  }
   668  
   669  func (p *noder) stmt(stmt syntax.Stmt) *Node {
   670  	p.lineno(stmt)
   671  	switch stmt := stmt.(type) {
   672  	case *syntax.EmptyStmt:
   673  		return nil
   674  	case *syntax.LabeledStmt:
   675  		return p.labeledStmt(stmt)
   676  	case *syntax.BlockStmt:
   677  		return p.body(stmt.Body)
   678  	case *syntax.ExprStmt:
   679  		return p.wrapname(stmt, p.expr(stmt.X))
   680  	case *syntax.SendStmt:
   681  		return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value))
   682  	case *syntax.DeclStmt:
   683  		return liststmt(p.decls(stmt.DeclList))
   684  	case *syntax.AssignStmt:
   685  		if stmt.Op != 0 && stmt.Op != syntax.Def {
   686  			n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))
   687  			n.Implicit = stmt.Rhs == syntax.ImplicitOne
   688  			n.Etype = EType(p.binOp(stmt.Op))
   689  			return n
   690  		}
   691  
   692  		lhs := p.exprList(stmt.Lhs)
   693  		rhs := p.exprList(stmt.Rhs)
   694  
   695  		n := p.nod(stmt, OAS, nil, nil) // assume common case
   696  
   697  		if stmt.Op == syntax.Def {
   698  			n.Colas = true
   699  			colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case
   700  		}
   701  
   702  		if len(lhs) == 1 && len(rhs) == 1 {
   703  			// common case
   704  			n.Left = lhs[0]
   705  			n.Right = rhs[0]
   706  		} else {
   707  			n.Op = OAS2
   708  			n.List.Set(lhs)
   709  			n.Rlist.Set(rhs)
   710  		}
   711  		return n
   712  
   713  	case *syntax.BranchStmt:
   714  		var op Op
   715  		switch stmt.Tok {
   716  		case syntax.Break:
   717  			op = OBREAK
   718  		case syntax.Continue:
   719  			op = OCONTINUE
   720  		case syntax.Fallthrough:
   721  			op = OXFALL
   722  		case syntax.Goto:
   723  			op = OGOTO
   724  		default:
   725  			panic("unhandled BranchStmt")
   726  		}
   727  		n := p.nod(stmt, op, nil, nil)
   728  		if stmt.Label != nil {
   729  			n.Left = p.newname(stmt.Label)
   730  		}
   731  		if op == OGOTO {
   732  			n.Sym = dclstack // context, for goto restriction
   733  		}
   734  		if op == OXFALL {
   735  			n.Xoffset = int64(block)
   736  		}
   737  		return n
   738  	case *syntax.CallStmt:
   739  		var op Op
   740  		switch stmt.Tok {
   741  		case syntax.Defer:
   742  			op = ODEFER
   743  		case syntax.Go:
   744  			op = OPROC
   745  		default:
   746  			panic("unhandled CallStmt")
   747  		}
   748  		return p.nod(stmt, op, p.expr(stmt.Call), nil)
   749  	case *syntax.ReturnStmt:
   750  		var results []*Node
   751  		if stmt.Results != nil {
   752  			results = p.exprList(stmt.Results)
   753  		}
   754  		n := p.nod(stmt, ORETURN, nil, nil)
   755  		n.List.Set(results)
   756  		if n.List.Len() == 0 && Curfn != nil {
   757  			for _, ln := range Curfn.Func.Dcl {
   758  				if ln.Class == PPARAM {
   759  					continue
   760  				}
   761  				if ln.Class != PPARAMOUT {
   762  					break
   763  				}
   764  				if ln.Sym.Def != ln {
   765  					yyerror("%s is shadowed during return", ln.Sym.Name)
   766  				}
   767  			}
   768  		}
   769  		return n
   770  	case *syntax.IfStmt:
   771  		return p.ifStmt(stmt)
   772  	case *syntax.ForStmt:
   773  		return p.forStmt(stmt)
   774  	case *syntax.SwitchStmt:
   775  		return p.switchStmt(stmt)
   776  	case *syntax.SelectStmt:
   777  		return p.selectStmt(stmt)
   778  	}
   779  	panic("unhandled Stmt")
   780  }
   781  
   782  func (p *noder) body(body []syntax.Stmt) *Node {
   783  	l := p.bodyList(body)
   784  	if len(l) == 0 {
   785  		// TODO(mdempsky): Line number?
   786  		return nod(OEMPTY, nil, nil)
   787  	}
   788  	return liststmt(l)
   789  }
   790  
   791  func (p *noder) bodyList(body []syntax.Stmt) []*Node {
   792  	markdcl()
   793  	nodes := p.stmts(body)
   794  	popdcl()
   795  	return nodes
   796  }
   797  
   798  func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
   799  	markdcl()
   800  	n := p.nod(stmt, OIF, nil, nil)
   801  	if stmt.Init != nil {
   802  		n.Ninit.Set1(p.stmt(stmt.Init))
   803  	}
   804  	if stmt.Cond != nil {
   805  		n.Left = p.expr(stmt.Cond)
   806  	}
   807  	n.Nbody.Set(p.bodyList(stmt.Then))
   808  	if stmt.Else != nil {
   809  		e := p.stmt(stmt.Else)
   810  		if e.Op == OBLOCK && e.Ninit.Len() == 0 {
   811  			n.Rlist.Set(e.List.Slice())
   812  		} else {
   813  			n.Rlist.Set1(e)
   814  		}
   815  	}
   816  	popdcl()
   817  	return n
   818  }
   819  
   820  func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
   821  	markdcl()
   822  	var n *Node
   823  	if r, ok := stmt.Init.(*syntax.RangeClause); ok {
   824  		if stmt.Cond != nil || stmt.Post != nil {
   825  			panic("unexpected RangeClause")
   826  		}
   827  
   828  		n = p.nod(r, ORANGE, nil, p.expr(r.X))
   829  		if r.Lhs != nil {
   830  			lhs := p.exprList(r.Lhs)
   831  			n.List.Set(lhs)
   832  			if r.Def {
   833  				n.Colas = true
   834  				colasdefn(lhs, n)
   835  			}
   836  		}
   837  	} else {
   838  		n = p.nod(stmt, OFOR, nil, nil)
   839  		if stmt.Init != nil {
   840  			n.Ninit.Set1(p.stmt(stmt.Init))
   841  		}
   842  		if stmt.Cond != nil {
   843  			n.Left = p.expr(stmt.Cond)
   844  		}
   845  		if stmt.Post != nil {
   846  			n.Right = p.stmt(stmt.Post)
   847  		}
   848  	}
   849  	n.Nbody.Set(p.bodyList(stmt.Body))
   850  	popdcl()
   851  	return n
   852  }
   853  
   854  func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
   855  	markdcl()
   856  	n := p.nod(stmt, OSWITCH, nil, nil)
   857  	if stmt.Init != nil {
   858  		n.Ninit.Set1(p.stmt(stmt.Init))
   859  	}
   860  	if stmt.Tag != nil {
   861  		n.Left = p.expr(stmt.Tag)
   862  	}
   863  
   864  	tswitch := n.Left
   865  	if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) {
   866  		tswitch = nil
   867  	}
   868  
   869  	n.List.Set(p.caseClauses(stmt.Body, tswitch))
   870  
   871  	popdcl()
   872  	return n
   873  }
   874  
   875  func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node {
   876  	var nodes []*Node
   877  	for _, clause := range clauses {
   878  		p.lineno(clause)
   879  		markdcl()
   880  		n := p.nod(clause, OXCASE, nil, nil)
   881  		if clause.Cases != nil {
   882  			n.List.Set(p.exprList(clause.Cases))
   883  		}
   884  		if tswitch != nil {
   885  			nn := newname(tswitch.Left.Sym)
   886  			declare(nn, dclcontext)
   887  			n.Rlist.Set1(nn)
   888  			// keep track of the instances for reporting unused
   889  			nn.Name.Defn = tswitch
   890  		}
   891  		n.Xoffset = int64(block)
   892  		n.Nbody.Set(p.stmts(clause.Body))
   893  		popdcl()
   894  		nodes = append(nodes, n)
   895  	}
   896  	return nodes
   897  }
   898  
   899  func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node {
   900  	n := p.nod(stmt, OSELECT, nil, nil)
   901  	n.List.Set(p.commClauses(stmt.Body))
   902  	return n
   903  }
   904  
   905  func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
   906  	var nodes []*Node
   907  	for _, clause := range clauses {
   908  		p.lineno(clause)
   909  		markdcl()
   910  		n := p.nod(clause, OXCASE, nil, nil)
   911  		if clause.Comm != nil {
   912  			n.List.Set1(p.stmt(clause.Comm))
   913  		}
   914  		n.Xoffset = int64(block)
   915  		n.Nbody.Set(p.stmts(clause.Body))
   916  		popdcl()
   917  		nodes = append(nodes, n)
   918  	}
   919  	return nodes
   920  }
   921  
   922  func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
   923  	lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
   924  	lhs.Sym = dclstack
   925  
   926  	var ls *Node
   927  	if label.Stmt != nil { // TODO(mdempsky): Should always be present.
   928  		ls = p.stmt(label.Stmt)
   929  	}
   930  
   931  	lhs.Name.Defn = ls
   932  	l := []*Node{lhs}
   933  	if ls != nil {
   934  		if ls.Op == OBLOCK && ls.Ninit.Len() == 0 {
   935  			l = append(l, ls.List.Slice()...)
   936  		} else {
   937  			l = append(l, ls)
   938  		}
   939  	}
   940  	return liststmt(l)
   941  }
   942  
   943  var unOps = [...]Op{
   944  	syntax.Recv: ORECV,
   945  	syntax.Mul:  OIND,
   946  	syntax.And:  OADDR,
   947  
   948  	syntax.Not: ONOT,
   949  	syntax.Xor: OCOM,
   950  	syntax.Add: OPLUS,
   951  	syntax.Sub: OMINUS,
   952  }
   953  
   954  func (p *noder) unOp(op syntax.Operator) Op {
   955  	if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
   956  		panic("invalid Operator")
   957  	}
   958  	return unOps[op]
   959  }
   960  
   961  var binOps = [...]Op{
   962  	syntax.OrOr:   OOROR,
   963  	syntax.AndAnd: OANDAND,
   964  
   965  	syntax.Eql: OEQ,
   966  	syntax.Neq: ONE,
   967  	syntax.Lss: OLT,
   968  	syntax.Leq: OLE,
   969  	syntax.Gtr: OGT,
   970  	syntax.Geq: OGE,
   971  
   972  	syntax.Add: OADD,
   973  	syntax.Sub: OSUB,
   974  	syntax.Or:  OOR,
   975  	syntax.Xor: OXOR,
   976  
   977  	syntax.Mul:    OMUL,
   978  	syntax.Div:    ODIV,
   979  	syntax.Rem:    OMOD,
   980  	syntax.And:    OAND,
   981  	syntax.AndNot: OANDNOT,
   982  	syntax.Shl:    OLSH,
   983  	syntax.Shr:    ORSH,
   984  }
   985  
   986  func (p *noder) binOp(op syntax.Operator) Op {
   987  	if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
   988  		panic("invalid Operator")
   989  	}
   990  	return binOps[op]
   991  }
   992  
   993  func (p *noder) basicLit(lit *syntax.BasicLit) Val {
   994  	// TODO: Don't try to convert if we had syntax errors (conversions may fail).
   995  	//       Use dummy values so we can continue to compile. Eventually, use a
   996  	//       form of "unknown" literals that are ignored during type-checking so
   997  	//       we can continue type-checking w/o spurious follow-up errors.
   998  	switch s := lit.Value; lit.Kind {
   999  	case syntax.IntLit:
  1000  		x := new(Mpint)
  1001  		x.SetString(s)
  1002  		return Val{U: x}
  1003  
  1004  	case syntax.FloatLit:
  1005  		x := newMpflt()
  1006  		x.SetString(s)
  1007  		return Val{U: x}
  1008  
  1009  	case syntax.ImagLit:
  1010  		x := new(Mpcplx)
  1011  		x.Imag.SetString(strings.TrimSuffix(s, "i"))
  1012  		return Val{U: x}
  1013  
  1014  	case syntax.RuneLit:
  1015  		var r rune
  1016  		if u, err := strconv.Unquote(s); err == nil && len(u) > 0 {
  1017  			// Package syntax already reported any errors.
  1018  			// Check for them again though because 0 is a
  1019  			// better fallback value for invalid rune
  1020  			// literals than 0xFFFD.
  1021  			if len(u) == 1 {
  1022  				r = rune(u[0])
  1023  			} else {
  1024  				r, _ = utf8.DecodeRuneInString(u)
  1025  			}
  1026  		}
  1027  		x := new(Mpint)
  1028  		x.SetInt64(int64(r))
  1029  		x.Rune = true
  1030  		return Val{U: x}
  1031  
  1032  	case syntax.StringLit:
  1033  		if len(s) > 0 && s[0] == '`' {
  1034  			// strip carriage returns from raw string
  1035  			s = strings.Replace(s, "\r", "", -1)
  1036  		}
  1037  		// Ignore errors because package syntax already reported them.
  1038  		u, _ := strconv.Unquote(s)
  1039  		return Val{U: u}
  1040  
  1041  	default:
  1042  		panic("unhandled BasicLit kind")
  1043  	}
  1044  }
  1045  
  1046  func (p *noder) name(name *syntax.Name) *Sym {
  1047  	return lookup(name.Value)
  1048  }
  1049  
  1050  func (p *noder) mkname(name *syntax.Name) *Node {
  1051  	// TODO(mdempsky): Set line number?
  1052  	return mkname(p.name(name))
  1053  }
  1054  
  1055  func (p *noder) newname(name *syntax.Name) *Node {
  1056  	// TODO(mdempsky): Set line number?
  1057  	return newname(p.name(name))
  1058  }
  1059  
  1060  func (p *noder) wrapname(n syntax.Node, x *Node) *Node {
  1061  	// These nodes do not carry line numbers.
  1062  	// Introduce a wrapper node to give them the correct line.
  1063  	switch x.Op {
  1064  	case OTYPE, OLITERAL:
  1065  		if x.Sym == nil {
  1066  			break
  1067  		}
  1068  		fallthrough
  1069  	case ONAME, ONONAME, OPACK:
  1070  		x = p.nod(n, OPAREN, x, nil)
  1071  		x.Implicit = true
  1072  	}
  1073  	return x
  1074  }
  1075  
  1076  func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node {
  1077  	return p.setlineno(orig, nod(op, left, right))
  1078  }
  1079  
  1080  func (p *noder) setlineno(src syntax.Node, dst *Node) *Node {
  1081  	l := int32(src.Line())
  1082  	if l == 0 {
  1083  		// TODO(mdempsky): Shouldn't happen. Fix package syntax.
  1084  		return dst
  1085  	}
  1086  	dst.Lineno = p.baseline + l - 1
  1087  	return dst
  1088  }
  1089  
  1090  func (p *noder) lineno(n syntax.Node) {
  1091  	if n == nil {
  1092  		return
  1093  	}
  1094  	l := int32(n.Line())
  1095  	if l == 0 {
  1096  		// TODO(mdempsky): Shouldn't happen. Fix package syntax.
  1097  		return
  1098  	}
  1099  	lineno = p.baseline + l - 1
  1100  }
  1101  
  1102  func (p *noder) error(_, line int, msg string) {
  1103  	yyerrorl(p.baseline+int32(line)-1, "%s", msg)
  1104  }
  1105  
  1106  func (p *noder) pragma(pos, line int, text string) syntax.Pragma {
  1107  	switch {
  1108  	case strings.HasPrefix(text, "line "):
  1109  		i := strings.IndexByte(text, ':')
  1110  		if i < 0 {
  1111  			break
  1112  		}
  1113  		n, err := strconv.Atoi(text[i+1:])
  1114  		if err != nil {
  1115  			// todo: make this an error instead? it is almost certainly a bug.
  1116  			break
  1117  		}
  1118  		if n > 1e8 {
  1119  			p.error(pos, line, "line number out of range")
  1120  			errorexit()
  1121  		}
  1122  		if n <= 0 {
  1123  			break
  1124  		}
  1125  		lexlineno = p.baseline + int32(line)
  1126  		linehistupdate(text[5:i], n)
  1127  
  1128  	case strings.HasPrefix(text, "go:linkname "):
  1129  		// Record line number so we can emit an error later if
  1130  		// the file doesn't import package unsafe.
  1131  		p.linknames = append(p.linknames, line)
  1132  
  1133  		f := strings.Fields(text)
  1134  		if len(f) != 3 {
  1135  			p.error(pos, line, "usage: //go:linkname localname linkname")
  1136  			break
  1137  		}
  1138  		lookup(f[1]).Linkname = f[2]
  1139  
  1140  	case strings.HasPrefix(text, "go:cgo_"):
  1141  		pragcgobuf += pragcgo(text)
  1142  		fallthrough // because of //go:cgo_unsafe_args
  1143  	default:
  1144  		verb := text
  1145  		if i := strings.Index(text, " "); i >= 0 {
  1146  			verb = verb[:i]
  1147  		}
  1148  		return syntax.Pragma(pragmaValue(verb))
  1149  	}
  1150  
  1151  	return 0
  1152  }