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