[dev.cc] cmd/internal/gc, cmd/new6g etc: convert from cmd/gc, cmd/6g etc

First draft of converted Go compiler, using rsc.io/c2go rev 83d795a.

Change-Id: I29f4c7010de07d2ff1947bbca9865879d83c32c3
Reviewed-on: https://go-review.googlesource.com/4851
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/src/cmd/internal/gc/dcl.go b/src/cmd/internal/gc/dcl.go
new file mode 100644
index 0000000..0aeb587
--- /dev/null
+++ b/src/cmd/internal/gc/dcl.go
@@ -0,0 +1,1565 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gc
+
+import (
+	"cmd/internal/obj"
+	"fmt"
+	"strings"
+)
+
+func dflag() int {
+	if !(Debug['d'] != 0) {
+		return 0
+	}
+	if Debug['y'] != 0 {
+		return 1
+	}
+	if incannedimport != 0 {
+		return 0
+	}
+	return 1
+}
+
+/*
+ * declaration stack & operations
+ */
+func dcopy(a *Sym, b *Sym) {
+	a.Pkg = b.Pkg
+	a.Name = b.Name
+	a.Def = b.Def
+	a.Block = b.Block
+	a.Lastlineno = b.Lastlineno
+}
+
+func push() *Sym {
+	var d *Sym
+
+	d = new(Sym)
+	d.Lastlineno = lineno
+	d.Link = dclstack
+	dclstack = d
+	return d
+}
+
+func pushdcl(s *Sym) *Sym {
+	var d *Sym
+
+	d = push()
+	dcopy(d, s)
+	if dflag() != 0 {
+		fmt.Printf("\t%v push %v %p\n", Ctxt.Line(int(lineno)), Sconv(s, 0), s.Def)
+	}
+	return d
+}
+
+func popdcl() {
+	var d *Sym
+	var s *Sym
+	var lno int
+
+	//	if(dflag())
+	//		print("revert\n");
+
+	for d = dclstack; d != nil; d = d.Link {
+		if d.Name == "" {
+			break
+		}
+		s = Pkglookup(d.Name, d.Pkg)
+		lno = int(s.Lastlineno)
+		dcopy(s, d)
+		d.Lastlineno = int32(lno)
+		if dflag() != 0 {
+			fmt.Printf("\t%v pop %v %p\n", Ctxt.Line(int(lineno)), Sconv(s, 0), s.Def)
+		}
+	}
+
+	if d == nil {
+		Fatal("popdcl: no mark")
+	}
+	dclstack = d.Link
+	block = d.Block
+}
+
+func poptodcl() {
+	// pop the old marker and push a new one
+	// (cannot reuse the existing one)
+	// because we use the markers to identify blocks
+	// for the goto restriction checks.
+	popdcl()
+
+	markdcl()
+}
+
+func markdcl() {
+	var d *Sym
+
+	d = push()
+	d.Name = "" // used as a mark in fifo
+	d.Block = block
+
+	blockgen++
+	block = blockgen
+}
+
+//	if(dflag())
+//		print("markdcl\n");
+func dumpdcl(st string) {
+	var s *Sym
+	var d *Sym
+	var i int
+
+	i = 0
+	for d = dclstack; d != nil; d = d.Link {
+		i++
+		fmt.Printf("    %.2d %p", i, d)
+		if d.Name == "" {
+			fmt.Printf("\n")
+			continue
+		}
+
+		fmt.Printf(" '%s'", d.Name)
+		s = Pkglookup(d.Name, d.Pkg)
+		fmt.Printf(" %v\n", Sconv(s, 0))
+	}
+}
+
+func testdclstack() {
+	var d *Sym
+
+	for d = dclstack; d != nil; d = d.Link {
+		if d.Name == "" {
+			if nerrors != 0 {
+				errorexit()
+			}
+			Yyerror("mark left on the stack")
+			continue
+		}
+	}
+}
+
+func redeclare(s *Sym, where string) {
+	var pkgstr *Strlit
+	var line1 int
+	var line2 int
+
+	if s.Lastlineno == 0 {
+		var tmp *Strlit
+		if s.Origpkg != nil {
+			tmp = s.Origpkg.Path
+		} else {
+			tmp = s.Pkg.Path
+		}
+		pkgstr = tmp
+		Yyerror("%v redeclared %s\n"+"\tprevious declaration during import \"%v\"", Sconv(s, 0), where, Zconv(pkgstr, 0))
+	} else {
+		line1 = parserline()
+		line2 = int(s.Lastlineno)
+
+		// When an import and a declaration collide in separate files,
+		// present the import as the "redeclared", because the declaration
+		// is visible where the import is, but not vice versa.
+		// See issue 4510.
+		if s.Def == nil {
+			line2 = line1
+			line1 = int(s.Lastlineno)
+		}
+
+		yyerrorl(int(line1), "%v redeclared %s\n"+"\tprevious declaration at %v", Sconv(s, 0), where, Ctxt.Line(line2))
+	}
+}
+
+var vargen int
+
+/*
+ * declare individual names - var, typ, const
+ */
+
+var declare_typegen int
+
+func declare(n *Node, ctxt int) {
+	var s *Sym
+	var gen int
+
+	if ctxt == PDISCARD {
+		return
+	}
+
+	if isblank(n) {
+		return
+	}
+
+	n.Lineno = int32(parserline())
+	s = n.Sym
+
+	// kludgy: typecheckok means we're past parsing.  Eg genwrapper may declare out of package names later.
+	if importpkg == nil && !(typecheckok != 0) && s.Pkg != localpkg {
+		Yyerror("cannot declare name %v", Sconv(s, 0))
+	}
+
+	if ctxt == PEXTERN && s.Name == "init" {
+		Yyerror("cannot declare init - must be func", s)
+	}
+
+	gen = 0
+	if ctxt == PEXTERN {
+		externdcl = list(externdcl, n)
+		if dflag() != 0 {
+			fmt.Printf("\t%v global decl %v %p\n", Ctxt.Line(int(lineno)), Sconv(s, 0), n)
+		}
+	} else {
+		if Curfn == nil && ctxt == PAUTO {
+			Fatal("automatic outside function")
+		}
+		if Curfn != nil {
+			Curfn.Dcl = list(Curfn.Dcl, n)
+		}
+		if n.Op == OTYPE {
+			declare_typegen++
+			gen = declare_typegen
+		} else if n.Op == ONAME && ctxt == PAUTO && !strings.Contains(s.Name, "·") {
+			vargen++
+			gen = vargen
+		}
+		pushdcl(s)
+		n.Curfn = Curfn
+	}
+
+	if ctxt == PAUTO {
+		n.Xoffset = 0
+	}
+
+	if s.Block == block {
+		// functype will print errors about duplicate function arguments.
+		// Don't repeat the error here.
+		if ctxt != PPARAM && ctxt != PPARAMOUT {
+			redeclare(s, "in this block")
+		}
+	}
+
+	s.Block = block
+	s.Lastlineno = int32(parserline())
+	s.Def = n
+	n.Vargen = int32(gen)
+	n.Funcdepth = Funcdepth
+	n.Class = uint8(ctxt)
+
+	autoexport(n, ctxt)
+}
+
+func addvar(n *Node, t *Type, ctxt int) {
+	if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil {
+		Fatal("addvar: n=%v t=%v nil", Nconv(n, 0), Tconv(t, 0))
+	}
+
+	n.Op = ONAME
+	declare(n, ctxt)
+	n.Type = t
+}
+
+/*
+ * declare variables from grammar
+ * new_name_list (type | [type] = expr_list)
+ */
+func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
+	var doexpr int
+	var v *Node
+	var e *Node
+	var as2 *Node
+	var init *NodeList
+
+	init = nil
+	doexpr = bool2int(el != nil)
+
+	if count(el) == 1 && count(vl) > 1 {
+		e = el.N
+		as2 = Nod(OAS2, nil, nil)
+		as2.List = vl
+		as2.Rlist = list1(e)
+		for ; vl != nil; vl = vl.Next {
+			v = vl.N
+			v.Op = ONAME
+			declare(v, dclcontext)
+			v.Ntype = t
+			v.Defn = as2
+			if Funcdepth > 0 {
+				init = list(init, Nod(ODCL, v, nil))
+			}
+		}
+
+		return list(init, as2)
+	}
+
+	for ; vl != nil; vl = vl.Next {
+		if doexpr != 0 {
+			if el == nil {
+				Yyerror("missing expression in var declaration")
+				break
+			}
+
+			e = el.N
+			el = el.Next
+		} else {
+			e = nil
+		}
+
+		v = vl.N
+		v.Op = ONAME
+		declare(v, dclcontext)
+		v.Ntype = t
+
+		if e != nil || Funcdepth > 0 || isblank(v) {
+			if Funcdepth > 0 {
+				init = list(init, Nod(ODCL, v, nil))
+			}
+			e = Nod(OAS, v, e)
+			init = list(init, e)
+			if e.Right != nil {
+				v.Defn = e
+			}
+		}
+	}
+
+	if el != nil {
+		Yyerror("extra expression in var declaration")
+	}
+	return init
+}
+
+/*
+ * declare constants from grammar
+ * new_name_list [[type] = expr_list]
+ */
+func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
+	var v *Node
+	var c *Node
+	var vv *NodeList
+
+	vv = nil
+	if cl == nil {
+		if t != nil {
+			Yyerror("const declaration cannot have type without expression")
+		}
+		cl = lastconst
+		t = lasttype
+	} else {
+		lastconst = cl
+		lasttype = t
+	}
+
+	cl = listtreecopy(cl)
+
+	for ; vl != nil; vl = vl.Next {
+		if cl == nil {
+			Yyerror("missing value in const declaration")
+			break
+		}
+
+		c = cl.N
+		cl = cl.Next
+
+		v = vl.N
+		v.Op = OLITERAL
+		declare(v, dclcontext)
+
+		v.Ntype = t
+		v.Defn = c
+
+		vv = list(vv, Nod(ODCLCONST, v, nil))
+	}
+
+	if cl != nil {
+		Yyerror("extra expression in const declaration")
+	}
+	iota_ += 1
+	return vv
+}
+
+/*
+ * this generates a new name node,
+ * typically for labels or other one-off names.
+ */
+func newname(s *Sym) *Node {
+	var n *Node
+
+	if s == nil {
+		Fatal("newname nil")
+	}
+
+	n = Nod(ONAME, nil, nil)
+	n.Sym = s
+	n.Type = nil
+	n.Addable = 1
+	n.Ullman = 1
+	n.Xoffset = 0
+	return n
+}
+
+/*
+ * this generates a new name node for a name
+ * being declared.
+ */
+func dclname(s *Sym) *Node {
+	var n *Node
+
+	n = newname(s)
+	n.Op = ONONAME // caller will correct it
+	return n
+}
+
+func typenod(t *Type) *Node {
+	// if we copied another type with *t = *u
+	// then t->nod might be out of date, so
+	// check t->nod->type too
+	if t.Nod == nil || t.Nod.Type != t {
+		t.Nod = Nod(OTYPE, nil, nil)
+		t.Nod.Type = t
+		t.Nod.Sym = t.Sym
+	}
+
+	return t.Nod
+}
+
+/*
+ * this will return an old name
+ * that has already been pushed on the
+ * declaration list. a diagnostic is
+ * generated if no name has been defined.
+ */
+func oldname(s *Sym) *Node {
+	var n *Node
+	var c *Node
+
+	n = s.Def
+	if n == nil {
+		// maybe a top-level name will come along
+		// to give this a definition later.
+		// walkdef will check s->def again once
+		// all the input source has been processed.
+		n = newname(s)
+
+		n.Op = ONONAME
+		n.Iota = iota_ // save current iota value in const declarations
+	}
+
+	if Curfn != nil && n.Funcdepth > 0 && n.Funcdepth != Funcdepth && n.Op == ONAME {
+		// inner func is referring to var in outer func.
+		//
+		// TODO(rsc): If there is an outer variable x and we
+		// are parsing x := 5 inside the closure, until we get to
+		// the := it looks like a reference to the outer x so we'll
+		// make x a closure variable unnecessarily.
+		if n.Closure == nil || n.Closure.Funcdepth != Funcdepth {
+			// create new closure var.
+			c = Nod(ONAME, nil, nil)
+
+			c.Sym = s
+			c.Class = PPARAMREF
+			c.Isddd = n.Isddd
+			c.Defn = n
+			c.Addable = 0
+			c.Ullman = 2
+			c.Funcdepth = Funcdepth
+			c.Outer = n.Closure
+			n.Closure = c
+			c.Closure = n
+			c.Xoffset = 0
+			Curfn.Cvars = list(Curfn.Cvars, c)
+		}
+
+		// return ref to closure var, not original
+		return n.Closure
+	}
+
+	return n
+}
+
+/*
+ * := declarations
+ */
+func colasname(n *Node) int {
+	switch n.Op {
+	case ONAME,
+		ONONAME,
+		OPACK,
+		OTYPE,
+		OLITERAL:
+		return bool2int(n.Sym != nil)
+	}
+
+	return 0
+}
+
+func colasdefn(left *NodeList, defn *Node) {
+	var nnew int
+	var nerr int
+	var l *NodeList
+	var n *Node
+
+	for l = left; l != nil; l = l.Next {
+		if l.N.Sym != nil {
+			l.N.Sym.Flags |= SymUniq
+		}
+	}
+
+	nnew = 0
+	nerr = 0
+	for l = left; l != nil; l = l.Next {
+		n = l.N
+		if isblank(n) {
+			continue
+		}
+		if !(colasname(n) != 0) {
+			yyerrorl(int(defn.Lineno), "non-name %v on left side of :=", Nconv(n, 0))
+			nerr++
+			continue
+		}
+
+		if n.Sym.Flags&SymUniq == 0 {
+			yyerrorl(int(defn.Lineno), "%v repeated on left side of :=", Sconv(n.Sym, 0))
+			n.Diag++
+			nerr++
+			continue
+		}
+
+		n.Sym.Flags &^= SymUniq
+		if n.Sym.Block == block {
+			continue
+		}
+
+		nnew++
+		n = newname(n.Sym)
+		declare(n, dclcontext)
+		n.Defn = defn
+		defn.Ninit = list(defn.Ninit, Nod(ODCL, n, nil))
+		l.N = n
+	}
+
+	if nnew == 0 && nerr == 0 {
+		yyerrorl(int(defn.Lineno), "no new variables on left side of :=")
+	}
+}
+
+func colas(left *NodeList, right *NodeList, lno int32) *Node {
+	var as *Node
+
+	as = Nod(OAS2, nil, nil)
+	as.List = left
+	as.Rlist = right
+	as.Colas = 1
+	as.Lineno = lno
+	colasdefn(left, as)
+
+	// make the tree prettier; not necessary
+	if count(left) == 1 && count(right) == 1 {
+		as.Left = as.List.N
+		as.Right = as.Rlist.N
+		as.List = nil
+		as.Rlist = nil
+		as.Op = OAS
+	}
+
+	return as
+}
+
+/*
+ * declare the arguments in an
+ * interface field declaration.
+ */
+func ifacedcl(n *Node) {
+	if n.Op != ODCLFIELD || n.Right == nil {
+		Fatal("ifacedcl")
+	}
+
+	if isblank(n.Left) {
+		Yyerror("methods must have a unique non-blank name")
+	}
+
+	dclcontext = PPARAM
+	markdcl()
+	Funcdepth++
+	n.Outer = Curfn
+	Curfn = n
+	funcargs(n.Right)
+
+	// funcbody is normally called after the parser has
+	// seen the body of a function but since an interface
+	// field declaration does not have a body, we must
+	// call it now to pop the current declaration context.
+	dclcontext = PAUTO
+
+	funcbody(n)
+}
+
+/*
+ * declare the function proper
+ * and declare the arguments.
+ * called in extern-declaration context
+ * returns in auto-declaration context.
+ */
+func funchdr(n *Node) {
+	// change the declaration context from extern to auto
+	if Funcdepth == 0 && dclcontext != PEXTERN {
+		Fatal("funchdr: dclcontext")
+	}
+
+	dclcontext = PAUTO
+	markdcl()
+	Funcdepth++
+
+	n.Outer = Curfn
+	Curfn = n
+
+	if n.Nname != nil {
+		funcargs(n.Nname.Ntype)
+	} else if n.Ntype != nil {
+		funcargs(n.Ntype)
+	} else {
+		funcargs2(n.Type)
+	}
+}
+
+func funcargs(nt *Node) {
+	var n *Node
+	var nn *Node
+	var l *NodeList
+	var gen int
+
+	if nt.Op != OTFUNC {
+		Fatal("funcargs %v", Oconv(int(nt.Op), 0))
+	}
+
+	// re-start the variable generation number
+	// we want to use small numbers for the return variables,
+	// so let them have the chunk starting at 1.
+	vargen = count(nt.Rlist)
+
+	// declare the receiver and in arguments.
+	// no n->defn because type checking of func header
+	// will not fill in the types until later
+	if nt.Left != nil {
+		n = nt.Left
+		if n.Op != ODCLFIELD {
+			Fatal("funcargs receiver %v", Oconv(int(n.Op), 0))
+		}
+		if n.Left != nil {
+			n.Left.Op = ONAME
+			n.Left.Ntype = n.Right
+			declare(n.Left, PPARAM)
+			if dclcontext == PAUTO {
+				vargen++
+				n.Left.Vargen = int32(vargen)
+			}
+		}
+	}
+
+	for l = nt.List; l != nil; l = l.Next {
+		n = l.N
+		if n.Op != ODCLFIELD {
+			Fatal("funcargs in %v", Oconv(int(n.Op), 0))
+		}
+		if n.Left != nil {
+			n.Left.Op = ONAME
+			n.Left.Ntype = n.Right
+			declare(n.Left, PPARAM)
+			if dclcontext == PAUTO {
+				vargen++
+				n.Left.Vargen = int32(vargen)
+			}
+		}
+	}
+
+	// declare the out arguments.
+	gen = count(nt.List)
+	var i int = 0
+	for l = nt.Rlist; l != nil; l = l.Next {
+		n = l.N
+
+		if n.Op != ODCLFIELD {
+			Fatal("funcargs out %v", Oconv(int(n.Op), 0))
+		}
+
+		if n.Left == nil {
+			// Name so that escape analysis can track it. ~r stands for 'result'.
+			namebuf = fmt.Sprintf("~r%d", gen)
+			gen++
+
+			n.Left = newname(Lookup(namebuf))
+		}
+
+		// TODO: n->left->missing = 1;
+		n.Left.Op = ONAME
+
+		if isblank(n.Left) {
+			// Give it a name so we can assign to it during return. ~b stands for 'blank'.
+			// The name must be different from ~r above because if you have
+			//	func f() (_ int)
+			//	func g() int
+			// f is allowed to use a plain 'return' with no arguments, while g is not.
+			// So the two cases must be distinguished.
+			// We do not record a pointer to the original node (n->orig).
+			// Having multiple names causes too much confusion in later passes.
+			nn = Nod(OXXX, nil, nil)
+
+			*nn = *n.Left
+			nn.Orig = nn
+			namebuf = fmt.Sprintf("~b%d", gen)
+			gen++
+			nn.Sym = Lookup(namebuf)
+			n.Left = nn
+		}
+
+		n.Left.Ntype = n.Right
+		declare(n.Left, PPARAMOUT)
+		if dclcontext == PAUTO {
+			i++
+			n.Left.Vargen = int32(i)
+		}
+	}
+}
+
+/*
+ * Same as funcargs, except run over an already constructed TFUNC.
+ * This happens during import, where the hidden_fndcl rule has
+ * used functype directly to parse the function's type.
+ */
+func funcargs2(t *Type) {
+	var ft *Type
+	var n *Node
+
+	if t.Etype != TFUNC {
+		Fatal("funcargs2 %v", Tconv(t, 0))
+	}
+
+	if t.Thistuple != 0 {
+		for ft = getthisx(t).Type; ft != nil; ft = ft.Down {
+			if !(ft.Nname != nil) || !(ft.Nname.Sym != nil) {
+				continue
+			}
+			n = ft.Nname // no need for newname(ft->nname->sym)
+			n.Type = ft.Type
+			declare(n, PPARAM)
+		}
+	}
+
+	if t.Intuple != 0 {
+		for ft = getinargx(t).Type; ft != nil; ft = ft.Down {
+			if !(ft.Nname != nil) || !(ft.Nname.Sym != nil) {
+				continue
+			}
+			n = ft.Nname
+			n.Type = ft.Type
+			declare(n, PPARAM)
+		}
+	}
+
+	if t.Outtuple != 0 {
+		for ft = getoutargx(t).Type; ft != nil; ft = ft.Down {
+			if !(ft.Nname != nil) || !(ft.Nname.Sym != nil) {
+				continue
+			}
+			n = ft.Nname
+			n.Type = ft.Type
+			declare(n, PPARAMOUT)
+		}
+	}
+}
+
+/*
+ * finish the body.
+ * called in auto-declaration context.
+ * returns in extern-declaration context.
+ */
+func funcbody(n *Node) {
+	// change the declaration context from auto to extern
+	if dclcontext != PAUTO {
+		Fatal("funcbody: dclcontext")
+	}
+	popdcl()
+	Funcdepth--
+	Curfn = n.Outer
+	n.Outer = nil
+	if Funcdepth == 0 {
+		dclcontext = PEXTERN
+	}
+}
+
+/*
+ * new type being defined with name s.
+ */
+func typedcl0(s *Sym) *Node {
+	var n *Node
+
+	n = newname(s)
+	n.Op = OTYPE
+	declare(n, dclcontext)
+	return n
+}
+
+/*
+ * node n, which was returned by typedcl0
+ * is being declared to have uncompiled type t.
+ * return the ODCLTYPE node to use.
+ */
+func typedcl1(n *Node, t *Node, local int) *Node {
+	n.Ntype = t
+	n.Local = uint8(local)
+	return Nod(ODCLTYPE, n, nil)
+}
+
+/*
+ * structs, functions, and methods.
+ * they don't belong here, but where do they belong?
+ */
+func checkembeddedtype(t *Type) {
+	if t == nil {
+		return
+	}
+
+	if t.Sym == nil && Isptr[t.Etype] != 0 {
+		t = t.Type
+		if t.Etype == TINTER {
+			Yyerror("embedded type cannot be a pointer to interface")
+		}
+	}
+
+	if Isptr[t.Etype] != 0 {
+		Yyerror("embedded type cannot be a pointer")
+	} else if t.Etype == TFORW && t.Embedlineno == 0 {
+		t.Embedlineno = lineno
+	}
+}
+
+func structfield(n *Node) *Type {
+	var f *Type
+	var lno int
+
+	lno = int(lineno)
+	lineno = n.Lineno
+
+	if n.Op != ODCLFIELD {
+		Fatal("structfield: oops %v\n", Nconv(n, 0))
+	}
+
+	f = typ(TFIELD)
+	f.Isddd = n.Isddd
+
+	if n.Right != nil {
+		typecheck(&n.Right, Etype)
+		n.Type = n.Right.Type
+		if n.Left != nil {
+			n.Left.Type = n.Type
+		}
+		if n.Embedded != 0 {
+			checkembeddedtype(n.Type)
+		}
+	}
+
+	n.Right = nil
+
+	f.Type = n.Type
+	if f.Type == nil {
+		f.Broke = 1
+	}
+
+	switch n.Val.Ctype {
+	case CTSTR:
+		f.Note = n.Val.U.Sval
+
+	default:
+		Yyerror("field annotation must be string")
+		fallthrough
+
+		// fallthrough
+	case CTxxx:
+		f.Note = nil
+	}
+
+	if n.Left != nil && n.Left.Op == ONAME {
+		f.Nname = n.Left
+		f.Embedded = n.Embedded
+		f.Sym = f.Nname.Sym
+	}
+
+	lineno = int32(lno)
+	return f
+}
+
+var uniqgen uint32
+
+func checkdupfields(t *Type, what string) {
+	var lno int
+
+	lno = int(lineno)
+
+	for ; t != nil; t = t.Down {
+		if t.Sym != nil && t.Nname != nil && !isblank(t.Nname) {
+			if t.Sym.Uniqgen == uniqgen {
+				lineno = t.Nname.Lineno
+				Yyerror("duplicate %s %s", what, t.Sym.Name)
+			} else {
+				t.Sym.Uniqgen = uniqgen
+			}
+		}
+	}
+
+	lineno = int32(lno)
+}
+
+/*
+ * convert a parsed id/type list into
+ * a type for struct/interface/arglist
+ */
+func tostruct(l *NodeList) *Type {
+	var t *Type
+	var f *Type
+	var tp **Type
+	t = typ(TSTRUCT)
+
+	for tp = &t.Type; l != nil; l = l.Next {
+		f = structfield(l.N)
+
+		*tp = f
+		tp = &f.Down
+	}
+
+	for f = t.Type; f != nil && !(t.Broke != 0); f = f.Down {
+		if f.Broke != 0 {
+			t.Broke = 1
+		}
+	}
+
+	uniqgen++
+	checkdupfields(t.Type, "field")
+
+	if !(t.Broke != 0) {
+		checkwidth(t)
+	}
+
+	return t
+}
+
+func tofunargs(l *NodeList) *Type {
+	var t *Type
+	var f *Type
+	var tp **Type
+
+	t = typ(TSTRUCT)
+	t.Funarg = 1
+
+	for tp = &t.Type; l != nil; l = l.Next {
+		f = structfield(l.N)
+		f.Funarg = 1
+
+		// esc.c needs to find f given a PPARAM to add the tag.
+		if l.N.Left != nil && l.N.Left.Class == PPARAM {
+			l.N.Left.Paramfld = f
+		}
+
+		*tp = f
+		tp = &f.Down
+	}
+
+	for f = t.Type; f != nil && !(t.Broke != 0); f = f.Down {
+		if f.Broke != 0 {
+			t.Broke = 1
+		}
+	}
+
+	return t
+}
+
+func interfacefield(n *Node) *Type {
+	var f *Type
+	var lno int
+
+	lno = int(lineno)
+	lineno = n.Lineno
+
+	if n.Op != ODCLFIELD {
+		Fatal("interfacefield: oops %v\n", Nconv(n, 0))
+	}
+
+	if n.Val.Ctype != CTxxx {
+		Yyerror("interface method cannot have annotation")
+	}
+
+	f = typ(TFIELD)
+	f.Isddd = n.Isddd
+
+	if n.Right != nil {
+		if n.Left != nil {
+			// queue resolution of method type for later.
+			// right now all we need is the name list.
+			// avoids cycles for recursive interface types.
+			n.Type = typ(TINTERMETH)
+
+			n.Type.Nname = n.Right
+			n.Left.Type = n.Type
+			queuemethod(n)
+
+			if n.Left.Op == ONAME {
+				f.Nname = n.Left
+				f.Embedded = n.Embedded
+				f.Sym = f.Nname.Sym
+			}
+		} else {
+			typecheck(&n.Right, Etype)
+			n.Type = n.Right.Type
+
+			if n.Embedded != 0 {
+				checkembeddedtype(n.Type)
+			}
+
+			if n.Type != nil {
+				switch n.Type.Etype {
+				case TINTER:
+					break
+
+				case TFORW:
+					Yyerror("interface type loop involving %v", Tconv(n.Type, 0))
+					f.Broke = 1
+
+				default:
+					Yyerror("interface contains embedded non-interface %v", Tconv(n.Type, 0))
+					f.Broke = 1
+				}
+			}
+		}
+	}
+
+	n.Right = nil
+
+	f.Type = n.Type
+	if f.Type == nil {
+		f.Broke = 1
+	}
+
+	lineno = int32(lno)
+	return f
+}
+
+func tointerface(l *NodeList) *Type {
+	var t *Type
+	var f *Type
+	var tp **Type
+	var t1 *Type
+
+	t = typ(TINTER)
+
+	tp = &t.Type
+	for ; l != nil; l = l.Next {
+		f = interfacefield(l.N)
+
+		if l.N.Left == nil && f.Type.Etype == TINTER {
+			// embedded interface, inline methods
+			for t1 = f.Type.Type; t1 != nil; t1 = t1.Down {
+				f = typ(TFIELD)
+				f.Type = t1.Type
+				f.Broke = t1.Broke
+				f.Sym = t1.Sym
+				if f.Sym != nil {
+					f.Nname = newname(f.Sym)
+				}
+				*tp = f
+				tp = &f.Down
+			}
+		} else {
+			*tp = f
+			tp = &f.Down
+		}
+	}
+
+	for f = t.Type; f != nil && !(t.Broke != 0); f = f.Down {
+		if f.Broke != 0 {
+			t.Broke = 1
+		}
+	}
+
+	uniqgen++
+	checkdupfields(t.Type, "method")
+	t = sortinter(t)
+	checkwidth(t)
+
+	return t
+}
+
+func embedded(s *Sym, pkg *Pkg) *Node {
+	var n *Node
+	var name string
+	const (
+		CenterDot = 0xB7
+	)
+	// Names sometimes have disambiguation junk
+	// appended after a center dot.  Discard it when
+	// making the name for the embedded struct field.
+	name = s.Name
+
+	if i := strings.Index(s.Name, string(CenterDot)); i >= 0 {
+		name = s.Name[:i]
+	}
+
+	if exportname(name) {
+		n = newname(Lookup(name))
+	} else if s.Pkg == builtinpkg {
+		// The name of embedded builtins belongs to pkg.
+		n = newname(Pkglookup(name, pkg))
+	} else {
+		n = newname(Pkglookup(name, s.Pkg))
+	}
+	n = Nod(ODCLFIELD, n, oldname(s))
+	n.Embedded = 1
+	return n
+}
+
+/*
+ * check that the list of declarations is either all anonymous or all named
+ */
+func findtype(l *NodeList) *Node {
+	for ; l != nil; l = l.Next {
+		if l.N.Op == OKEY {
+			return l.N.Right
+		}
+	}
+	return nil
+}
+
+func checkarglist(all *NodeList, input int) *NodeList {
+	var named int
+	var n *Node
+	var t *Node
+	var nextt *Node
+	var l *NodeList
+
+	named = 0
+	for l = all; l != nil; l = l.Next {
+		if l.N.Op == OKEY {
+			named = 1
+			break
+		}
+	}
+
+	if named != 0 {
+		n = nil
+		for l = all; l != nil; l = l.Next {
+			n = l.N
+			if n.Op != OKEY && n.Sym == nil {
+				Yyerror("mixed named and unnamed function parameters")
+				break
+			}
+		}
+
+		if l == nil && n != nil && n.Op != OKEY {
+			Yyerror("final function parameter must have type")
+		}
+	}
+
+	nextt = nil
+	for l = all; l != nil; l = l.Next {
+		// can cache result from findtype to avoid
+		// quadratic behavior here, but unlikely to matter.
+		n = l.N
+
+		if named != 0 {
+			if n.Op == OKEY {
+				t = n.Right
+				n = n.Left
+				nextt = nil
+			} else {
+				if nextt == nil {
+					nextt = findtype(l)
+				}
+				t = nextt
+			}
+		} else {
+			t = n
+			n = nil
+		}
+
+		// during import l->n->op is OKEY, but l->n->left->sym == S
+		// means it was a '?', not that it was
+		// a lone type This doesn't matter for the exported
+		// declarations, which are parsed by rules that don't
+		// use checkargs, but can happen for func literals in
+		// the inline bodies.
+		// TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
+		if importpkg != nil && n.Sym == nil {
+			n = nil
+		}
+
+		if n != nil && n.Sym == nil {
+			t = n
+			n = nil
+		}
+
+		if n != nil {
+			n = newname(n.Sym)
+		}
+		n = Nod(ODCLFIELD, n, t)
+		if n.Right != nil && n.Right.Op == ODDD {
+			if !(input != 0) {
+				Yyerror("cannot use ... in output argument list")
+			} else if l.Next != nil {
+				Yyerror("can only use ... as final argument in list")
+			}
+			n.Right.Op = OTARRAY
+			n.Right.Right = n.Right.Left
+			n.Right.Left = nil
+			n.Isddd = 1
+			if n.Left != nil {
+				n.Left.Isddd = 1
+			}
+		}
+
+		l.N = n
+	}
+
+	return all
+}
+
+func fakethis() *Node {
+	var n *Node
+
+	n = Nod(ODCLFIELD, nil, typenod(Ptrto(typ(TSTRUCT))))
+	return n
+}
+
+/*
+ * Is this field a method on an interface?
+ * Those methods have an anonymous
+ * *struct{} as the receiver.
+ * (See fakethis above.)
+ */
+func isifacemethod(f *Type) int {
+	var rcvr *Type
+	var t *Type
+
+	rcvr = getthisx(f).Type
+	if rcvr.Sym != nil {
+		return 0
+	}
+	t = rcvr.Type
+	if !(Isptr[t.Etype] != 0) {
+		return 0
+	}
+	t = t.Type
+	if t.Sym != nil || t.Etype != TSTRUCT || t.Type != nil {
+		return 0
+	}
+	return 1
+}
+
+/*
+ * turn a parsed function declaration
+ * into a type
+ */
+func functype(this *Node, in *NodeList, out *NodeList) *Type {
+	var t *Type
+	var rcvr *NodeList
+	var s *Sym
+
+	t = typ(TFUNC)
+
+	rcvr = nil
+	if this != nil {
+		rcvr = list1(this)
+	}
+	t.Type = tofunargs(rcvr)
+	t.Type.Down = tofunargs(out)
+	t.Type.Down.Down = tofunargs(in)
+
+	uniqgen++
+	checkdupfields(t.Type.Type, "argument")
+	checkdupfields(t.Type.Down.Type, "argument")
+	checkdupfields(t.Type.Down.Down.Type, "argument")
+
+	if t.Type.Broke != 0 || t.Type.Down.Broke != 0 || t.Type.Down.Down.Broke != 0 {
+		t.Broke = 1
+	}
+
+	if this != nil {
+		t.Thistuple = 1
+	}
+	t.Outtuple = count(out)
+	t.Intuple = count(in)
+	t.Outnamed = 0
+	if t.Outtuple > 0 && out.N.Left != nil && out.N.Left.Orig != nil {
+		s = out.N.Left.Orig.Sym
+		if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result
+			t.Outnamed = 1
+		}
+	}
+
+	return t
+}
+
+var methodsym_toppkg *Pkg
+
+func methodsym(nsym *Sym, t0 *Type, iface int) *Sym {
+	var s *Sym
+	var p string
+	var t *Type
+	var suffix string
+	var spkg *Pkg
+
+	t = t0
+	if t == nil {
+		goto bad
+	}
+	s = t.Sym
+	if s == nil && Isptr[t.Etype] != 0 {
+		t = t.Type
+		if t == nil {
+			goto bad
+		}
+		s = t.Sym
+	}
+
+	spkg = nil
+	if s != nil {
+		spkg = s.Pkg
+	}
+
+	// if t0 == *t and t0 has a sym,
+	// we want to see *t, not t0, in the method name.
+	if t != t0 && t0.Sym != nil {
+		t0 = Ptrto(t)
+	}
+
+	suffix = ""
+	if iface != 0 {
+		dowidth(t0)
+		if t0.Width < Types[Tptr].Width {
+			suffix = "·i"
+		}
+	}
+
+	if (spkg == nil || nsym.Pkg != spkg) && !exportname(nsym.Name) {
+		if t0.Sym == nil && Isptr[t0.Etype] != 0 {
+			p = fmt.Sprintf("(%v).%s.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix)
+		} else {
+			p = fmt.Sprintf("%v.%s.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix)
+		}
+	} else {
+		if t0.Sym == nil && Isptr[t0.Etype] != 0 {
+			p = fmt.Sprintf("(%v).%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Name, suffix)
+		} else {
+			p = fmt.Sprintf("%v.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Name, suffix)
+		}
+	}
+
+	if spkg == nil {
+		if methodsym_toppkg == nil {
+			methodsym_toppkg = mkpkg(newstrlit("go"))
+		}
+		spkg = methodsym_toppkg
+	}
+
+	s = Pkglookup(p, spkg)
+
+	return s
+
+bad:
+	Yyerror("illegal receiver type: %v", Tconv(t0, 0))
+	return nil
+}
+
+func methodname(n *Node, t *Type) *Node {
+	var s *Sym
+
+	s = methodsym(n.Sym, t, 0)
+	if s == nil {
+		return n
+	}
+	return newname(s)
+}
+
+func methodname1(n *Node, t *Node) *Node {
+	var star string
+	var p string
+
+	star = ""
+	if t.Op == OIND {
+		star = "*"
+		t = t.Left
+	}
+
+	if t.Sym == nil || isblank(n) {
+		return newname(n.Sym)
+	}
+
+	if star != "" {
+		p = fmt.Sprintf("(%s%v).%v", star, Sconv(t.Sym, 0), Sconv(n.Sym, 0))
+	} else {
+		p = fmt.Sprintf("%v.%v", Sconv(t.Sym, 0), Sconv(n.Sym, 0))
+	}
+
+	if exportname(t.Sym.Name) {
+		n = newname(Lookup(p))
+	} else {
+		n = newname(Pkglookup(p, t.Sym.Pkg))
+	}
+
+	return n
+}
+
+/*
+ * add a method, declared as a function,
+ * n is fieldname, pa is base type, t is function type
+ */
+func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
+	var f *Type
+	var d *Type
+	var pa *Type
+	var n *Node
+
+	// get field sym
+	if sf == nil {
+		Fatal("no method symbol")
+	}
+
+	// get parent type sym
+	pa = getthisx(t).Type // ptr to this structure
+	if pa == nil {
+		Yyerror("missing receiver")
+		return
+	}
+
+	pa = pa.Type
+	f = methtype(pa, 1)
+	if f == nil {
+		t = pa
+		if t == nil { // rely on typecheck having complained before
+			return
+		}
+		if t != nil {
+			if Isptr[t.Etype] != 0 {
+				if t.Sym != nil {
+					Yyerror("invalid receiver type %v (%v is a pointer type)", Tconv(pa, 0), Tconv(t, 0))
+					return
+				}
+
+				t = t.Type
+			}
+
+			if t.Broke != 0 { // rely on typecheck having complained before
+				return
+			}
+			if t.Sym == nil {
+				Yyerror("invalid receiver type %v (%v is an unnamed type)", Tconv(pa, 0), Tconv(t, 0))
+				return
+			}
+
+			if Isptr[t.Etype] != 0 {
+				Yyerror("invalid receiver type %v (%v is a pointer type)", Tconv(pa, 0), Tconv(t, 0))
+				return
+			}
+
+			if t.Etype == TINTER {
+				Yyerror("invalid receiver type %v (%v is an interface type)", Tconv(pa, 0), Tconv(t, 0))
+				return
+			}
+		}
+
+		// Should have picked off all the reasons above,
+		// but just in case, fall back to generic error.
+		Yyerror("invalid receiver type %v (%v / %v)", Tconv(pa, 0), Tconv(pa, obj.FmtLong), Tconv(t, obj.FmtLong))
+
+		return
+	}
+
+	pa = f
+	if pa.Etype == TSTRUCT {
+		for f = pa.Type; f != nil; f = f.Down {
+			if f.Sym == sf {
+				Yyerror("type %v has both field and method named %v", Tconv(pa, 0), Sconv(sf, 0))
+				return
+			}
+		}
+	}
+
+	if local && !(pa.Local != 0) {
+		// defining method on non-local type.
+		Yyerror("cannot define new methods on non-local type %v", Tconv(pa, 0))
+
+		return
+	}
+
+	n = Nod(ODCLFIELD, newname(sf), nil)
+	n.Type = t
+
+	d = nil // last found
+	for f = pa.Method; f != nil; f = f.Down {
+		d = f
+		if f.Etype != TFIELD {
+			Fatal("addmethod: not TFIELD: %v", Tconv(f, obj.FmtLong))
+		}
+		if sf.Name != f.Sym.Name {
+			continue
+		}
+		if !Eqtype(t, f.Type) {
+			Yyerror("method redeclared: %v.%v\n\t%v\n\t%v", Tconv(pa, 0), Sconv(sf, 0), Tconv(f.Type, 0), Tconv(t, 0))
+		}
+		return
+	}
+
+	f = structfield(n)
+	f.Nointerface = uint8(bool2int(nointerface))
+
+	// during import unexported method names should be in the type's package
+	if importpkg != nil && f.Sym != nil && !exportname(f.Sym.Name) && f.Sym.Pkg != structpkg {
+		Fatal("imported method name %v in wrong package %s\n", Sconv(f.Sym, obj.FmtSign), structpkg.Name)
+	}
+
+	if d == nil {
+		pa.Method = f
+	} else {
+		d.Down = f
+	}
+	return
+}
+
+func funccompile(n *Node) {
+	Stksize = BADWIDTH
+	Maxarg = 0
+
+	if n.Type == nil {
+		if nerrors == 0 {
+			Fatal("funccompile missing type")
+		}
+		return
+	}
+
+	// assign parameter offsets
+	checkwidth(n.Type)
+
+	if Curfn != nil {
+		Fatal("funccompile %v inside %v", Sconv(n.Nname.Sym, 0), Sconv(Curfn.Nname.Sym, 0))
+	}
+
+	Stksize = 0
+	dclcontext = PAUTO
+	Funcdepth = n.Funcdepth + 1
+	compile(n)
+	Curfn = nil
+	Funcdepth = 0
+	dclcontext = PEXTERN
+}
+
+func funcsym(s *Sym) *Sym {
+	var p string
+	var s1 *Sym
+
+	p = fmt.Sprintf("%s·f", s.Name)
+	s1 = Pkglookup(p, s.Pkg)
+
+	if s1.Def == nil {
+		s1.Def = newname(s1)
+		s1.Def.Shortname = newname(s)
+		funcsyms = list(funcsyms, s1.Def)
+	}
+
+	return s1
+}