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