// 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 eval

import (
	"big"
	"log"
	"go/ast"
	"go/token"
)

const (
	returnPC = ^uint(0)
	badPC    = ^uint(1)
)

/*
 * Statement compiler
 */

type stmtCompiler struct {
	*blockCompiler
	pos token.Position
	// This statement's label, or nil if it is not labeled.
	stmtLabel *label
}

func (a *stmtCompiler) diag(format string, args ...interface{}) {
	a.diagAt(&a.pos, format, args)
}

/*
 * Flow checker
 */

type flowEnt struct {
	// Whether this flow entry is conditional.  If true, flow can
	// continue to the next PC.
	cond bool
	// True if this will terminate flow (e.g., a return statement).
	// cond must be false and jumps must be nil if this is true.
	term bool
	// PC's that can be reached from this flow entry.
	jumps []*uint
	// Whether this flow entry has been visited by reachesEnd.
	visited bool
}

type flowBlock struct {
	// If this is a goto, the target label.
	target string
	// The inner-most block containing definitions.
	block *block
	// The numVars from each block leading to the root of the
	// scope, starting at block.
	numVars []int
}

type flowBuf struct {
	cb *codeBuf
	// ents is a map from PC's to flow entries.  Any PC missing
	// from this map is assumed to reach only PC+1.
	ents map[uint]*flowEnt
	// gotos is a map from goto positions to information on the
	// block at the point of the goto.
	gotos map[*token.Position]*flowBlock
	// labels is a map from label name to information on the block
	// at the point of the label.  labels are tracked by name,
	// since mutliple labels at the same PC can have different
	// blocks.
	labels map[string]*flowBlock
}

func newFlowBuf(cb *codeBuf) *flowBuf {
	return &flowBuf{cb, make(map[uint]*flowEnt), make(map[*token.Position]*flowBlock), make(map[string]*flowBlock)}
}

// put creates a flow control point for the next PC in the code buffer.
// This should be done before pushing the instruction into the code buffer.
func (f *flowBuf) put(cond bool, term bool, jumps []*uint) {
	pc := f.cb.nextPC()
	if ent, ok := f.ents[pc]; ok {
		log.Crashf("Flow entry already exists at PC %d: %+v", pc, ent)
	}
	f.ents[pc] = &flowEnt{cond, term, jumps, false}
}

// putTerm creates a flow control point at the next PC that
// unconditionally terminates execution.
func (f *flowBuf) putTerm() { f.put(false, true, nil) }

// put1 creates a flow control point at the next PC that jumps to one
// PC and, if cond is true, can also continue to the PC following the
// next PC.
func (f *flowBuf) put1(cond bool, jumpPC *uint) {
	f.put(cond, false, []*uint{jumpPC})
}

func newFlowBlock(target string, b *block) *flowBlock {
	// Find the inner-most block containing definitions
	for b.numVars == 0 && b.outer != nil && b.outer.scope == b.scope {
		b = b.outer
	}

	// Count parents leading to the root of the scope
	n := 0
	for bp := b; bp.scope == b.scope; bp = bp.outer {
		n++
	}

	// Capture numVars from each block to the root of the scope
	numVars := make([]int, n)
	i := 0
	for bp := b; i < n; bp = bp.outer {
		numVars[i] = bp.numVars
		i++
	}

	return &flowBlock{target, b, numVars}
}

// putGoto captures the block at a goto statement.  This should be
// called in addition to putting a flow control point.
func (f *flowBuf) putGoto(pos token.Position, target string, b *block) {
	f.gotos[&pos] = newFlowBlock(target, b)
}

// putLabel captures the block at a label.
func (f *flowBuf) putLabel(name string, b *block) {
	f.labels[name] = newFlowBlock("", b)
}

// reachesEnd returns true if the end of f's code buffer can be
// reached from the given program counter.  Error reporting is the
// caller's responsibility.
func (f *flowBuf) reachesEnd(pc uint) bool {
	endPC := f.cb.nextPC()
	if pc > endPC {
		log.Crashf("Reached bad PC %d past end PC %d", pc, endPC)
	}

	for ; pc < endPC; pc++ {
		ent, ok := f.ents[pc]
		if !ok {
			continue
		}

		if ent.visited {
			return false
		}
		ent.visited = true

		if ent.term {
			return false
		}

		// If anything can reach the end, we can reach the end
		// from pc.
		for _, j := range ent.jumps {
			if f.reachesEnd(*j) {
				return true
			}
		}
		// If the jump was conditional, we can reach the next
		// PC, so try reaching the end from it.
		if ent.cond {
			continue
		}
		return false
	}
	return true
}

// gotosObeyScopes returns true if no goto statement causes any
// variables to come into scope that were not in scope at the point of
// the goto.  Reports any errors using the given compiler.
func (f *flowBuf) gotosObeyScopes(a *compiler) {
	for pos, src := range f.gotos {
		tgt := f.labels[src.target]

		// The target block must be a parent of this block
		numVars := src.numVars
		b := src.block
		for len(numVars) > 0 && b != tgt.block {
			b = b.outer
			numVars = numVars[1:]
		}
		if b != tgt.block {
			// We jumped into a deeper block
			a.diagAt(pos, "goto causes variables to come into scope")
			return
		}

		// There must be no variables in the target block that
		// did not exist at the jump
		tgtNumVars := tgt.numVars
		for i := range numVars {
			if tgtNumVars[i] > numVars[i] {
				a.diagAt(pos, "goto causes variables to come into scope")
				return
			}
		}
	}
}

/*
 * Statement generation helpers
 */

func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
	v, prev := a.block.DefineVar(ident.Name(), ident.Pos(), t)
	if prev != nil {
		// TODO(austin) It's silly that we have to capture
		// Pos() in a variable.
		pos := prev.Pos()
		if pos.IsValid() {
			a.diagAt(ident, "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name(), &pos)
		} else {
			a.diagAt(ident, "variable %s redeclared in this block", ident.Name())
		}
		return nil
	}

	// Initialize the variable
	index := v.Index
	if v.Index >= 0 {
		a.push(func(v *Thread) { v.f.Vars[index] = t.Zero() })
	}
	return v
}

// TODO(austin) Move doAssign to here

/*
 * Statement compiler
 */

func (a *stmtCompiler) compile(s ast.Stmt) {
	if a.block.inner != nil {
		log.Crash("Child scope still entered")
	}

	notimpl := false
	switch s := s.(type) {
	case *ast.BadStmt:
		// Error already reported by parser.
		a.silentErrors++

	case *ast.DeclStmt:
		a.compileDeclStmt(s)

	case *ast.EmptyStmt:
		// Do nothing.

	case *ast.LabeledStmt:
		a.compileLabeledStmt(s)

	case *ast.ExprStmt:
		a.compileExprStmt(s)

	case *ast.IncDecStmt:
		a.compileIncDecStmt(s)

	case *ast.AssignStmt:
		a.compileAssignStmt(s)

	case *ast.GoStmt:
		notimpl = true

	case *ast.DeferStmt:
		notimpl = true

	case *ast.ReturnStmt:
		a.compileReturnStmt(s)

	case *ast.BranchStmt:
		a.compileBranchStmt(s)

	case *ast.BlockStmt:
		a.compileBlockStmt(s)

	case *ast.IfStmt:
		a.compileIfStmt(s)

	case *ast.CaseClause:
		a.diag("case clause outside switch")

	case *ast.SwitchStmt:
		a.compileSwitchStmt(s)

	case *ast.TypeCaseClause:
		notimpl = true

	case *ast.TypeSwitchStmt:
		notimpl = true

	case *ast.CommClause:
		notimpl = true

	case *ast.SelectStmt:
		notimpl = true

	case *ast.ForStmt:
		a.compileForStmt(s)

	case *ast.RangeStmt:
		notimpl = true

	default:
		log.Crashf("unexpected ast node type %T", s)
	}

	if notimpl {
		a.diag("%T statment node not implemented", s)
	}

	if a.block.inner != nil {
		log.Crash("Forgot to exit child scope")
	}
}

func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) {
	switch decl := s.Decl.(type) {
	case *ast.BadDecl:
		// Do nothing.  Already reported by parser.
		a.silentErrors++

	case *ast.FuncDecl:
		if !a.block.global {
			log.Crash("FuncDecl at statement level")
		}

	case *ast.GenDecl:
		if decl.Tok == token.IMPORT && !a.block.global {
			log.Crash("import at statement level")
		}

	default:
		log.Crashf("Unexpected Decl type %T", s.Decl)
	}
	a.compileDecl(s.Decl)
}

func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) {
	for _, spec := range decl.Specs {
		spec := spec.(*ast.ValueSpec)
		if spec.Values == nil {
			// Declaration without assignment
			if spec.Type == nil {
				// Parser should have caught
				log.Crash("Type and Values nil")
			}
			t := a.compileType(a.block, spec.Type)
			// Define placeholders even if type compile failed
			for _, n := range spec.Names {
				a.defineVar(n, t)
			}
		} else {
			// Declaration with assignment
			lhs := make([]ast.Expr, len(spec.Names))
			for i, n := range spec.Names {
				lhs[i] = n
			}
			a.doAssign(lhs, spec.Values, decl.Tok, spec.Type)
		}
	}
}

func (a *stmtCompiler) compileDecl(decl ast.Decl) {
	switch d := decl.(type) {
	case *ast.BadDecl:
		// Do nothing.  Already reported by parser.
		a.silentErrors++

	case *ast.FuncDecl:
		decl := a.compileFuncType(a.block, d.Type)
		if decl == nil {
			return
		}
		// Declare and initialize v before compiling func
		// so that body can refer to itself.
		c, prev := a.block.DefineConst(d.Name.Name(), a.pos, decl.Type, decl.Type.Zero())
		if prev != nil {
			pos := prev.Pos()
			if pos.IsValid() {
				a.diagAt(d.Name, "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name(), &pos)
			} else {
				a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Name())
			}
		}
		fn := a.compileFunc(a.block, decl, d.Body)
		if c == nil || fn == nil {
			return
		}
		var zeroThread Thread
		c.Value.(FuncValue).Set(nil, fn(&zeroThread))

	case *ast.GenDecl:
		switch d.Tok {
		case token.IMPORT:
			log.Crashf("%v not implemented", d.Tok)
		case token.CONST:
			log.Crashf("%v not implemented", d.Tok)
		case token.TYPE:
			a.compileTypeDecl(a.block, d)
		case token.VAR:
			a.compileVarDecl(d)
		}

	default:
		log.Crashf("Unexpected Decl type %T", decl)
	}
}

func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) {
	// Define label
	l, ok := a.labels[s.Label.Name()]
	if ok {
		if l.resolved.IsValid() {
			a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name(), &l.resolved)
		}
	} else {
		pc := badPC
		l = &label{name: s.Label.Name(), gotoPC: &pc}
		a.labels[l.name] = l
	}
	l.desc = "regular label"
	l.resolved = s.Pos()

	// Set goto PC
	*l.gotoPC = a.nextPC()

	// Define flow entry so we can check for jumps over declarations.
	a.flow.putLabel(l.name, a.block)

	// Compile the statement.  Reuse our stmtCompiler for simplicity.
	sc := &stmtCompiler{a.blockCompiler, s.Stmt.Pos(), l}
	sc.compile(s.Stmt)
}

func (a *stmtCompiler) compileExprStmt(s *ast.ExprStmt) {
	bc := a.enterChild()
	defer bc.exit()

	e := a.compileExpr(bc.block, false, s.X)
	if e == nil {
		return
	}

	if e.exec == nil {
		a.diag("%s cannot be used as expression statement", e.desc)
		return
	}

	a.push(e.exec)
}

func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
	// Create temporary block for extractEffect
	bc := a.enterChild()
	defer bc.exit()

	l := a.compileExpr(bc.block, false, s.X)
	if l == nil {
		return
	}

	if l.evalAddr == nil {
		l.diag("cannot assign to %s", l.desc)
		return
	}
	if !(l.t.isInteger() || l.t.isFloat()) {
		l.diagOpType(s.Tok, l.t)
		return
	}

	var op token.Token
	var desc string
	switch s.Tok {
	case token.INC:
		op = token.ADD
		desc = "increment statement"
	case token.DEC:
		op = token.SUB
		desc = "decrement statement"
	default:
		log.Crashf("Unexpected IncDec token %v", s.Tok)
	}

	effect, l := l.extractEffect(bc.block, desc)

	one := l.newExpr(IdealIntType, "constant")
	one.pos = s.Pos()
	one.eval = func() *big.Int { return big.NewInt(1) }

	binop := l.compileBinaryExpr(op, l, one)
	if binop == nil {
		return
	}

	assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "")
	if assign == nil {
		log.Crashf("compileAssign type check failed")
	}

	lf := l.evalAddr
	a.push(func(v *Thread) {
		effect(v)
		assign(lf(v), v)
	})
}

func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, declTypeExpr ast.Expr) {
	nerr := a.numError()

	// Compile right side first so we have the types when
	// compiling the left side and so we don't see definitions
	// made on the left side.
	rs := make([]*expr, len(rhs))
	for i, re := range rhs {
		rs[i] = a.compileExpr(a.block, false, re)
	}

	errOp := "assignment"
	if tok == token.DEFINE || tok == token.VAR {
		errOp = "declaration"
	}
	ac, ok := a.checkAssign(a.pos, rs, errOp, "value")
	ac.allowMapForms(len(lhs))

	// If this is a definition and the LHS is too big, we won't be
	// able to produce the usual error message because we can't
	// begin to infer the types of the LHS.
	if (tok == token.DEFINE || tok == token.VAR) && len(lhs) > len(ac.rmt.Elems) {
		a.diag("not enough values for definition")
	}

	// Compile left type if there is one
	var declType Type
	if declTypeExpr != nil {
		declType = a.compileType(a.block, declTypeExpr)
	}

	// Compile left side
	ls := make([]*expr, len(lhs))
	nDefs := 0
	for i, le := range lhs {
		// If this is a definition, get the identifier and its type
		var ident *ast.Ident
		var lt Type
		switch tok {
		case token.DEFINE:
			// Check that it's an identifier
			ident, ok = le.(*ast.Ident)
			if !ok {
				a.diagAt(le, "left side of := must be a name")
				// Suppress new defitions errors
				nDefs++
				continue
			}

			// Is this simply an assignment?
			if _, ok := a.block.defs[ident.Name()]; ok {
				ident = nil
				break
			}
			nDefs++

		case token.VAR:
			ident = le.(*ast.Ident)
		}

		// If it's a definition, get or infer its type.
		if ident != nil {
			// Compute the identifier's type from the RHS
			// type.  We use the computed MultiType so we
			// don't have to worry about unpacking.
			switch {
			case declTypeExpr != nil:
				// We have a declaration type, use it.
				// If declType is nil, we gave an
				// error when we compiled it.
				lt = declType

			case i >= len(ac.rmt.Elems):
				// Define a placeholder.  We already
				// gave the "not enough" error above.
				lt = nil

			case ac.rmt.Elems[i] == nil:
				// We gave the error when we compiled
				// the RHS.
				lt = nil

			case ac.rmt.Elems[i].isIdeal():
				// If the type is absent and the
				// corresponding expression is a
				// constant expression of ideal
				// integer or ideal float type, the
				// type of the declared variable is
				// int or float respectively.
				switch {
				case ac.rmt.Elems[i].isInteger():
					lt = IntType
				case ac.rmt.Elems[i].isFloat():
					lt = FloatType
				default:
					log.Crashf("unexpected ideal type %v", rs[i].t)
				}

			default:
				lt = ac.rmt.Elems[i]
			}
		}

		// If it's a definition, define the identifier
		if ident != nil {
			if a.defineVar(ident, lt) == nil {
				continue
			}
		}

		// Compile LHS
		ls[i] = a.compileExpr(a.block, false, le)
		if ls[i] == nil {
			continue
		}

		if ls[i].evalMapValue != nil {
			// Map indexes are not generally addressable,
			// but they are assignable.
			//
			// TODO(austin) Now that the expression
			// compiler uses semantic values, this might
			// be easier to implement as a function call.
			sub := ls[i]
			ls[i] = ls[i].newExpr(sub.t, sub.desc)
			ls[i].evalMapValue = sub.evalMapValue
			mvf := sub.evalMapValue
			et := sub.t
			ls[i].evalAddr = func(t *Thread) Value {
				m, k := mvf(t)
				e := m.Elem(t, k)
				if e == nil {
					e = et.Zero()
					m.SetElem(t, k, e)
				}
				return e
			}
		} else if ls[i].evalAddr == nil {
			ls[i].diag("cannot assign to %s", ls[i].desc)
			continue
		}
	}

	// A short variable declaration may redeclare variables
	// provided they were originally declared in the same block
	// with the same type, and at least one of the variables is
	// new.
	if tok == token.DEFINE && nDefs == 0 {
		a.diag("at least one new variable must be declared")
		return
	}

	// If there have been errors, our arrays are full of nil's so
	// get out of here now.
	if nerr != a.numError() {
		return
	}

	// Check for 'a[x] = r, ok'
	if len(ls) == 1 && len(rs) == 2 && ls[0].evalMapValue != nil {
		a.diag("a[x] = r, ok form not implemented")
		return
	}

	// Create assigner
	var lt Type
	n := len(lhs)
	if n == 1 {
		lt = ls[0].t
	} else {
		lts := make([]Type, len(ls))
		for i, l := range ls {
			if l != nil {
				lts[i] = l.t
			}
		}
		lt = NewMultiType(lts)
	}
	bc := a.enterChild()
	defer bc.exit()
	assign := ac.compile(bc.block, lt)
	if assign == nil {
		return
	}

	// Compile
	if n == 1 {
		// Don't need temporaries and can avoid []Value.
		lf := ls[0].evalAddr
		a.push(func(t *Thread) { assign(lf(t), t) })
	} else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) {
		// Don't need temporaries
		lfs := make([]func(*Thread) Value, n)
		for i, l := range ls {
			lfs[i] = l.evalAddr
		}
		a.push(func(t *Thread) {
			dest := make([]Value, n)
			for i, lf := range lfs {
				dest[i] = lf(t)
			}
			assign(multiV(dest), t)
		})
	} else {
		// Need temporaries
		lmt := lt.(*MultiType)
		lfs := make([]func(*Thread) Value, n)
		for i, l := range ls {
			lfs[i] = l.evalAddr
		}
		a.push(func(t *Thread) {
			temp := lmt.Zero().(multiV)
			assign(temp, t)
			// Copy to destination
			for i := 0; i < n; i++ {
				// TODO(austin) Need to evaluate LHS
				// before RHS
				lfs[i](t).Assign(t, temp[i])
			}
		})
	}
}

var assignOpToOp = map[token.Token]token.Token{
	token.ADD_ASSIGN: token.ADD,
	token.SUB_ASSIGN: token.SUB,
	token.MUL_ASSIGN: token.MUL,
	token.QUO_ASSIGN: token.QUO,
	token.REM_ASSIGN: token.REM,

	token.AND_ASSIGN:     token.AND,
	token.OR_ASSIGN:      token.OR,
	token.XOR_ASSIGN:     token.XOR,
	token.SHL_ASSIGN:     token.SHL,
	token.SHR_ASSIGN:     token.SHR,
	token.AND_NOT_ASSIGN: token.AND_NOT,
}

func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
	if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
		a.diag("tuple assignment cannot be combined with an arithmetic operation")
		return
	}

	// Create temporary block for extractEffect
	bc := a.enterChild()
	defer bc.exit()

	l := a.compileExpr(bc.block, false, s.Lhs[0])
	r := a.compileExpr(bc.block, false, s.Rhs[0])
	if l == nil || r == nil {
		return
	}

	if l.evalAddr == nil {
		l.diag("cannot assign to %s", l.desc)
		return
	}

	effect, l := l.extractEffect(bc.block, "operator-assignment")

	binop := r.compileBinaryExpr(assignOpToOp[s.Tok], l, r)
	if binop == nil {
		return
	}

	assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "assignment", "value")
	if assign == nil {
		log.Crashf("compileAssign type check failed")
	}

	lf := l.evalAddr
	a.push(func(t *Thread) {
		effect(t)
		assign(lf(t), t)
	})
}

func (a *stmtCompiler) compileAssignStmt(s *ast.AssignStmt) {
	switch s.Tok {
	case token.ASSIGN, token.DEFINE:
		a.doAssign(s.Lhs, s.Rhs, s.Tok, nil)

	default:
		a.doAssignOp(s)
	}
}

func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
	if a.fnType == nil {
		a.diag("cannot return at the top level")
		return
	}

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

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

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

	// Create assigner

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

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

	// Compile
	start := len(a.fnType.In)
	nout := len(a.fnType.Out)
	a.flow.putTerm()
	a.push(func(t *Thread) {
		assign(multiV(t.f.Vars[start:start+nout]), t)
		t.pc = returnPC
	})
}

func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool, errOp, errCtx string) *label {
	bc := a.blockCompiler
	for ; bc != nil; bc = bc.parent {
		if bc.label == nil {
			continue
		}
		l := bc.label
		if name == nil && pred(l) {
			return l
		}
		if name != nil && l.name == name.Name() {
			if !pred(l) {
				a.diag("cannot %s to %s %s", errOp, l.desc, l.name)
				return nil
			}
			return l
		}
	}
	if name == nil {
		a.diag("%s outside %s", errOp, errCtx)
	} else {
		a.diag("%s label %s not defined", errOp, name.Name())
	}
	return nil
}

func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
	var pc *uint

	switch s.Tok {
	case token.BREAK:
		l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.breakPC != nil }, "break", "for loop, switch, or select")
		if l == nil {
			return
		}
		pc = l.breakPC

	case token.CONTINUE:
		l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop")
		if l == nil {
			return
		}
		pc = l.continuePC

	case token.GOTO:
		l, ok := a.labels[s.Label.Name()]
		if !ok {
			pc := badPC
			l = &label{name: s.Label.Name(), desc: "unresolved label", gotoPC: &pc, used: s.Pos()}
			a.labels[l.name] = l
		}

		pc = l.gotoPC
		a.flow.putGoto(s.Pos(), l.name, a.block)

	case token.FALLTHROUGH:
		a.diag("fallthrough outside switch")
		return

	default:
		log.Crash("Unexpected branch token %v", s.Tok)
	}

	a.flow.put1(false, pc)
	a.push(func(v *Thread) { v.pc = *pc })
}

func (a *stmtCompiler) compileBlockStmt(s *ast.BlockStmt) {
	bc := a.enterChild()
	bc.compileStmts(s)
	bc.exit()
}

func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
	// The scope of any variables declared by [the init] statement
	// extends to the end of the "if" statement and the variables
	// are initialized once before the statement is entered.
	//
	// XXX(Spec) What this really wants to say is that there's an
	// implicit scope wrapping every if, for, and switch
	// statement.  This is subtly different from what it actually
	// says when there's a non-block else clause, because that
	// else claus has to execute in a scope that is *not* the
	// surrounding scope.
	bc := a.enterChild()
	defer bc.exit()

	// Compile init statement, if any
	if s.Init != nil {
		bc.compileStmt(s.Init)
	}

	elsePC := badPC
	endPC := badPC

	// Compile condition, if any.  If there is no condition, we
	// fall through to the body.
	if s.Cond != nil {
		e := bc.compileExpr(bc.block, false, s.Cond)
		switch {
		case e == nil:
			// Error reported by compileExpr
		case !e.t.isBoolean():
			e.diag("'if' condition must be boolean\n\t%v", e.t)
		default:
			eval := e.asBool()
			a.flow.put1(true, &elsePC)
			a.push(func(t *Thread) {
				if !eval(t) {
					t.pc = elsePC
				}
			})
		}
	}

	// Compile body
	body := bc.enterChild()
	body.compileStmts(s.Body)
	body.exit()

	// Compile else
	if s.Else != nil {
		// Skip over else if we executed the body
		a.flow.put1(false, &endPC)
		a.push(func(v *Thread) { v.pc = endPC })
		elsePC = a.nextPC()
		bc.compileStmt(s.Else)
	} else {
		elsePC = a.nextPC()
	}
	endPC = a.nextPC()
}

func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
	// Create implicit scope around switch
	bc := a.enterChild()
	defer bc.exit()

	// Compile init statement, if any
	if s.Init != nil {
		bc.compileStmt(s.Init)
	}

	// Compile condition, if any, and extract its effects
	var cond *expr
	condbc := bc.enterChild()
	if s.Tag != nil {
		e := condbc.compileExpr(condbc.block, false, s.Tag)
		if e != nil {
			var effect func(*Thread)
			effect, cond = e.extractEffect(condbc.block, "switch")
			a.push(effect)
		}
	}

	// Count cases
	ncases := 0
	hasDefault := false
	for _, c := range s.Body.List {
		clause, ok := c.(*ast.CaseClause)
		if !ok {
			a.diagAt(clause, "switch statement must contain case clauses")
			continue
		}
		if clause.Values == nil {
			if hasDefault {
				a.diagAt(clause, "switch statement contains more than one default case")
			}
			hasDefault = true
		} else {
			ncases += len(clause.Values)
		}
	}

	// Compile case expressions
	cases := make([]func(*Thread) bool, ncases)
	i := 0
	for _, c := range s.Body.List {
		clause, ok := c.(*ast.CaseClause)
		if !ok {
			continue
		}
		for _, v := range clause.Values {
			e := condbc.compileExpr(condbc.block, false, v)
			switch {
			case e == nil:
				// Error reported by compileExpr
			case cond == nil && !e.t.isBoolean():
				a.diagAt(v, "'case' condition must be boolean")
			case cond == nil:
				cases[i] = e.asBool()
			case cond != nil:
				// Create comparison
				// TOOD(austin) This produces bad error messages
				compare := e.compileBinaryExpr(token.EQL, cond, e)
				if compare != nil {
					cases[i] = compare.asBool()
				}
			}
			i++
		}
	}

	// Emit condition
	casePCs := make([]*uint, ncases+1)
	endPC := badPC

	a.flow.put(false, false, casePCs)
	a.push(func(t *Thread) {
		for i, c := range cases {
			if c(t) {
				t.pc = *casePCs[i]
				return
			}
		}
		t.pc = *casePCs[ncases]
	})
	condbc.exit()

	// Compile cases
	i = 0
	for _, c := range s.Body.List {
		clause, ok := c.(*ast.CaseClause)
		if !ok {
			continue
		}

		// Save jump PC's
		pc := a.nextPC()
		if clause.Values != nil {
			for _ = range clause.Values {
				casePCs[i] = &pc
				i++
			}
		} else {
			// Default clause
			casePCs[ncases] = &pc
		}

		// Compile body
		fall := false
		for j, s := range clause.Body {
			if br, ok := s.(*ast.BranchStmt); ok && br.Tok == token.FALLTHROUGH {
				// println("Found fallthrough");
				// It may be used only as the final
				// non-empty statement in a case or
				// default clause in an expression
				// "switch" statement.
				for _, s2 := range clause.Body[j+1:] {
					// XXX(Spec) 6g also considers
					// empty blocks to be empty
					// statements.
					if _, ok := s2.(*ast.EmptyStmt); !ok {
						a.diagAt(s, "fallthrough statement must be final statement in case")
						break
					}
				}
				fall = true
			} else {
				bc.compileStmt(s)
			}
		}
		// Jump out of switch, unless there was a fallthrough
		if !fall {
			a.flow.put1(false, &endPC)
			a.push(func(v *Thread) { v.pc = endPC })
		}
	}

	// Get end PC
	endPC = a.nextPC()
	if !hasDefault {
		casePCs[ncases] = &endPC
	}
}

func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
	// Wrap the entire for in a block.
	bc := a.enterChild()
	defer bc.exit()

	// Compile init statement, if any
	if s.Init != nil {
		bc.compileStmt(s.Init)
	}

	bodyPC := badPC
	postPC := badPC
	checkPC := badPC
	endPC := badPC

	// Jump to condition check.  We generate slightly less code by
	// placing the condition check after the body.
	a.flow.put1(false, &checkPC)
	a.push(func(v *Thread) { v.pc = checkPC })

	// Compile body
	bodyPC = a.nextPC()
	body := bc.enterChild()
	if a.stmtLabel != nil {
		body.label = a.stmtLabel
	} else {
		body.label = &label{resolved: s.Pos()}
	}
	body.label.desc = "for loop"
	body.label.breakPC = &endPC
	body.label.continuePC = &postPC
	body.compileStmts(s.Body)
	body.exit()

	// Compile post, if any
	postPC = a.nextPC()
	if s.Post != nil {
		// TODO(austin) Does the parser disallow short
		// declarations in s.Post?
		bc.compileStmt(s.Post)
	}

	// Compile condition check, if any
	checkPC = a.nextPC()
	if s.Cond == nil {
		// If the condition is absent, it is equivalent to true.
		a.flow.put1(false, &bodyPC)
		a.push(func(v *Thread) { v.pc = bodyPC })
	} else {
		e := bc.compileExpr(bc.block, false, s.Cond)
		switch {
		case e == nil:
			// Error reported by compileExpr
		case !e.t.isBoolean():
			a.diag("'for' condition must be boolean\n\t%v", e.t)
		default:
			eval := e.asBool()
			a.flow.put1(true, &bodyPC)
			a.push(func(t *Thread) {
				if eval(t) {
					t.pc = bodyPC
				}
			})
		}
	}

	endPC = a.nextPC()
}

/*
 * Block compiler
 */

func (a *blockCompiler) compileStmt(s ast.Stmt) {
	sc := &stmtCompiler{a, s.Pos(), nil}
	sc.compile(s)
}

func (a *blockCompiler) compileStmts(block *ast.BlockStmt) {
	for _, sub := range block.List {
		a.compileStmt(sub)
	}
}

func (a *blockCompiler) enterChild() *blockCompiler {
	block := a.block.enterChild()
	return &blockCompiler{
		funcCompiler: a.funcCompiler,
		block:        block,
		parent:       a,
	}
}

func (a *blockCompiler) exit() { a.block.exit() }

/*
 * Function compiler
 */

func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) func(*Thread) Func {
	// Create body scope
	//
	// The scope of a parameter or result is the body of the
	// corresponding function.
	bodyScope := b.ChildScope()
	defer bodyScope.exit()
	for i, t := range decl.Type.In {
		if decl.InNames[i] != nil {
			bodyScope.DefineVar(decl.InNames[i].Name(), decl.InNames[i].Pos(), t)
		} else {
			bodyScope.DefineTemp(t)
		}
	}
	for i, t := range decl.Type.Out {
		if decl.OutNames[i] != nil {
			bodyScope.DefineVar(decl.OutNames[i].Name(), decl.OutNames[i].Pos(), t)
		} else {
			bodyScope.DefineTemp(t)
		}
	}

	// Create block context
	cb := newCodeBuf()
	fc := &funcCompiler{
		compiler:     a,
		fnType:       decl.Type,
		outVarsNamed: len(decl.OutNames) > 0 && decl.OutNames[0] != nil,
		codeBuf:      cb,
		flow:         newFlowBuf(cb),
		labels:       make(map[string]*label),
	}
	bc := &blockCompiler{
		funcCompiler: fc,
		block:        bodyScope.block,
	}

	// Compile body
	nerr := a.numError()
	bc.compileStmts(body)
	fc.checkLabels()
	if nerr != a.numError() {
		return nil
	}

	// Check that the body returned if necessary.  We only check
	// this if there were no errors compiling the body.
	if len(decl.Type.Out) > 0 && fc.flow.reachesEnd(0) {
		// XXX(Spec) Not specified.
		a.diagAt(&body.Rbrace, "function ends without a return statement")
		return nil
	}

	code := fc.get()
	maxVars := bodyScope.maxVars
	return func(t *Thread) Func { return &evalFunc{t.f, maxVars, code} }
}

// Checks that labels were resolved and that all jumps obey scoping
// rules.  Reports an error and set fc.err if any check fails.
func (a *funcCompiler) checkLabels() {
	nerr := a.numError()
	for _, l := range a.labels {
		if !l.resolved.IsValid() {
			a.diagAt(&l.used, "label %s not defined", l.name)
		}
	}
	if nerr != a.numError() {
		// Don't check scopes if we have unresolved labels
		return
	}

	// Executing the "goto" statement must not cause any variables
	// to come into scope that were not already in scope at the
	// point of the goto.
	a.flow.gotosObeyScopes(a.compiler)
}
