// 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 (
	"bignum";
	"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 ...) {
	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:len(numVars)];
		}
		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.Value, 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.Value, &pos);
		} else {
			a.diagAt(ident, "variable %s redeclared in this block", ident.Value);
		}
		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.Value, 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.Value, &pos);
			} else {
				a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Value);
			}
		}
		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.Value];
	if ok {
		if l.resolved.IsValid() {
			a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Value, &l.resolved);
		}
	} else {
		pc := badPC;
		l = &label{name: s.Label.Value, 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() *bignum.Integer { return bignum.Int(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.Value]; 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.Value {
			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.Value);
	}
	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.Value];
		if !ok {
			pc := badPC;
			l = &label{name: s.Label.Value, 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:len(clause.Body)] {
					// 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].Value, 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].Value, 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);
}
