diff options
Diffstat (limited to 'src/pkg/exp/eval/stmt.go')
| -rw-r--r-- | src/pkg/exp/eval/stmt.go | 618 |
1 files changed, 309 insertions, 309 deletions
diff --git a/src/pkg/exp/eval/stmt.go b/src/pkg/exp/eval/stmt.go index 60c6b9ee6..53757f7de 100644 --- a/src/pkg/exp/eval/stmt.go +++ b/src/pkg/exp/eval/stmt.go @@ -5,15 +5,15 @@ package eval import ( - "bignum"; - "log"; - "go/ast"; - "go/token"; + "bignum" + "log" + "go/ast" + "go/token" ) const ( - returnPC = ^uint(0); - badPC = ^uint(1); + returnPC = ^uint(0) + badPC = ^uint(1) ) /* @@ -21,10 +21,10 @@ const ( */ type stmtCompiler struct { - *blockCompiler; - pos token.Position; + *blockCompiler + pos token.Position // This statement's label, or nil if it is not labeled. - stmtLabel *label; + stmtLabel *label } func (a *stmtCompiler) diag(format string, args ...) { @@ -38,39 +38,39 @@ func (a *stmtCompiler) diag(format string, args ...) { type flowEnt struct { // Whether this flow entry is conditional. If true, flow can // continue to the next PC. - cond bool; + 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; + term bool // PC's that can be reached from this flow entry. - jumps []*uint; + jumps []*uint // Whether this flow entry has been visited by reachesEnd. - visited bool; + visited bool } type flowBlock struct { // If this is a goto, the target label. - target string; + target string // The inner-most block containing definitions. - block *block; + block *block // The numVars from each block leading to the root of the // scope, starting at block. - numVars []int; + numVars []int } type flowBuf struct { - cb *codeBuf; + 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; + 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; + 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; + labels map[string]*flowBlock } func newFlowBuf(cb *codeBuf) *flowBuf { @@ -80,16 +80,16 @@ func newFlowBuf(cb *codeBuf) *flowBuf { // 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(); + 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}; + 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) } +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 @@ -105,20 +105,20 @@ func newFlowBlock(target string, b *block) *flowBlock { } // Count parents leading to the root of the scope - n := 0; + 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; + numVars := make([]int, n) + i := 0 for bp := b; i < n; bp = bp.outer { - numVars[i] = bp.numVars; - i++; + numVars[i] = bp.numVars + i++ } - return &flowBlock{target, b, numVars}; + return &flowBlock{target, b, numVars} } // putGoto captures the block at a goto statement. This should be @@ -136,13 +136,13 @@ func (f *flowBuf) putLabel(name string, b *block) { // reached from the given program counter. Error reporting is the // caller's responsibility. func (f *flowBuf) reachesEnd(pc uint) bool { - endPC := f.cb.nextPC(); + 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]; + ent, ok := f.ents[pc] if !ok { continue } @@ -150,7 +150,7 @@ func (f *flowBuf) reachesEnd(pc uint) bool { if ent.visited { return false } - ent.visited = true; + ent.visited = true if ent.term { return false @@ -168,9 +168,9 @@ func (f *flowBuf) reachesEnd(pc uint) bool { if ent.cond { continue } - return false; + return false } - return true; + return true } // gotosObeyScopes returns true if no goto statement causes any @@ -178,28 +178,28 @@ func (f *flowBuf) reachesEnd(pc uint) bool { // 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]; + tgt := f.labels[src.target] // The target block must be a parent of this block - numVars := src.numVars; - b := src.block; + numVars := src.numVars + b := src.block for len(numVars) > 0 && b != tgt.block { - b = b.outer; - numVars = numVars[1:]; + 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; + 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; + tgtNumVars := tgt.numVars for i := range numVars { if tgtNumVars[i] > numVars[i] { - a.diagAt(pos, "goto causes variables to come into scope"); - return; + a.diagAt(pos, "goto causes variables to come into scope") + return } } } @@ -210,25 +210,25 @@ func (f *flowBuf) gotosObeyScopes(a *compiler) { */ func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable { - v, prev := a.block.DefineVar(ident.Value, ident.Pos(), t); + 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(); + 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; + return nil } // Initialize the variable - index := v.Index; + index := v.Index if v.Index >= 0 { a.push(func(v *Thread) { v.f.Vars[index] = t.Zero() }) } - return v; + return v } // TODO(austin) Move doAssign to here @@ -242,7 +242,7 @@ func (a *stmtCompiler) compile(s ast.Stmt) { log.Crash("Child scope still entered") } - notimpl := false; + notimpl := false switch s := s.(type) { case *ast.BadStmt: // Error already reported by parser. @@ -340,30 +340,30 @@ func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) { default: log.Crashf("Unexpected Decl type %T", s.Decl) } - a.compileDecl(s.Decl); + a.compileDecl(s.Decl) } func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) { for _, spec := range decl.Specs { - spec := spec.(*ast.ValueSpec); + 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); + 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)); + 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); + a.doAssign(lhs, spec.Values, decl.Tok, spec.Type) } } } @@ -375,27 +375,27 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) { a.silentErrors++ case *ast.FuncDecl: - decl := a.compileFuncType(a.block, d.Type); + 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()); + c, prev := a.block.DefineConst(d.Name.Value, a.pos, decl.Type, decl.Type.Zero()) if prev != nil { - pos := prev.Pos(); + 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); + fn := a.compileFunc(a.block, decl, d.Body) if c == nil || fn == nil { return } - var zeroThread Thread; - c.Value.(FuncValue).Set(nil, fn(&zeroThread)); + var zeroThread Thread + c.Value.(FuncValue).Set(nil, fn(&zeroThread)) case *ast.GenDecl: switch d.Tok { @@ -416,119 +416,119 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) { func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) { // Define label - l, ok := a.labels[s.Label.Value]; + 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; + pc := badPC + l = &label{name: s.Label.Value, gotoPC: &pc} + a.labels[l.name] = l } - l.desc = "regular label"; - l.resolved = s.Pos(); + l.desc = "regular label" + l.resolved = s.Pos() // Set goto PC - *l.gotoPC = a.nextPC(); + *l.gotoPC = a.nextPC() // Define flow entry so we can check for jumps over declarations. - a.flow.putLabel(l.name, a.block); + 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); + 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(); + bc := a.enterChild() + defer bc.exit() - e := a.compileExpr(bc.block, false, s.X); + 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.diag("%s cannot be used as expression statement", e.desc) + return } - a.push(e.exec); + a.push(e.exec) } func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) { // Create temporary block for extractEffect - bc := a.enterChild(); - defer bc.exit(); + bc := a.enterChild() + defer bc.exit() - l := a.compileExpr(bc.block, false, s.X); + 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; + l.diag("cannot assign to %s", l.desc) + return } if !(l.t.isInteger() || l.t.isFloat()) { - l.diagOpType(s.Tok, l.t); - return; + l.diagOpType(s.Tok, l.t) + return } - var op token.Token; - var desc string; + var op token.Token + var desc string switch s.Tok { case token.INC: - op = token.ADD; - desc = "increment statement"; + op = token.ADD + desc = "increment statement" case token.DEC: - op = token.SUB; - desc = "decrement statement"; + op = token.SUB + desc = "decrement statement" default: log.Crashf("Unexpected IncDec token %v", s.Tok) } - effect, l := l.extractEffect(bc.block, desc); + 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) }; + one := l.newExpr(IdealIntType, "constant") + one.pos = s.Pos() + one.eval = func() *bignum.Integer { return bignum.Int(1) } - binop := l.compileBinaryExpr(op, l, one); + binop := l.compileBinaryExpr(op, l, one) if binop == nil { return } - assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", ""); + assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "") if assign == nil { log.Crashf("compileAssign type check failed") } - lf := l.evalAddr; + lf := l.evalAddr a.push(func(v *Thread) { - effect(v); - assign(lf(v), v); - }); + 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(); + 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)); + rs := make([]*expr, len(rhs)) for i, re := range rhs { rs[i] = a.compileExpr(a.block, false, re) } - errOp := "assignment"; + errOp := "assignment" if tok == token.DEFINE || tok == token.VAR { errOp = "declaration" } - ac, ok := a.checkAssign(a.pos, rs, errOp, "value"); - ac.allowMapForms(len(lhs)); + 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 @@ -538,35 +538,35 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, } // Compile left type if there is one - var declType Type; + var declType Type if declTypeExpr != nil { declType = a.compileType(a.block, declTypeExpr) } // Compile left side - ls := make([]*expr, len(lhs)); - nDefs := 0; + 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; + var ident *ast.Ident + var lt Type switch tok { case token.DEFINE: // Check that it's an identifier - ident, ok = le.(*ast.Ident); + ident, ok = le.(*ast.Ident) if !ok { - a.diagAt(le, "left side of := must be a name"); + a.diagAt(le, "left side of := must be a name") // Suppress new defitions errors - nDefs++; - continue; + nDefs++ + continue } // Is this simply an assignment? if _, ok := a.block.defs[ident.Value]; ok { - ident = nil; - break; + ident = nil + break } - nDefs++; + nDefs++ case token.VAR: ident = le.(*ast.Ident) @@ -623,7 +623,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, } // Compile LHS - ls[i] = a.compileExpr(a.block, false, le); + ls[i] = a.compileExpr(a.block, false, le) if ls[i] == nil { continue } @@ -635,23 +635,23 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, // 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; + 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); + m, k := mvf(t) + e := m.Elem(t, k) if e == nil { - e = et.Zero(); - m.SetElem(t, k, e); + e = et.Zero() + m.SetElem(t, k, e) } - return e; - }; + return e + } } else if ls[i].evalAddr == nil { - ls[i].diag("cannot assign to %s", ls[i].desc); - continue; + ls[i].diag("cannot assign to %s", ls[i].desc) + continue } } @@ -660,8 +660,8 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, // 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; + a.diag("at least one new variable must be declared") + return } // If there have been errors, our arrays are full of nil's so @@ -672,27 +672,27 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, // 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; + a.diag("a[x] = r, ok form not implemented") + return } // Create assigner - var lt Type; - n := len(lhs); + var lt Type + n := len(lhs) if n == 1 { lt = ls[0].t } else { - lts := make([]Type, len(ls)); + lts := make([]Type, len(ls)) for i, l := range ls { if l != nil { lts[i] = l.t } } - lt = NewMultiType(lts); + lt = NewMultiType(lts) } - bc := a.enterChild(); - defer bc.exit(); - assign := ac.compile(bc.block, lt); + bc := a.enterChild() + defer bc.exit() + assign := ac.compile(bc.block, lt) if assign == nil { return } @@ -700,38 +700,38 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, // 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) }); + 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); + lfs := make([]func(*Thread) Value, n) for i, l := range ls { lfs[i] = l.evalAddr } a.push(func(t *Thread) { - dest := make([]Value, n); + dest := make([]Value, n) for i, lf := range lfs { dest[i] = lf(t) } - assign(multiV(dest), t); - }); + assign(multiV(dest), t) + }) } else { // Need temporaries - lmt := lt.(*MultiType); - lfs := make([]func(*Thread) Value, n); + 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); + 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]) } - }); + }) } } @@ -752,42 +752,42 @@ var assignOpToOp = map[token.Token]token.Token{ 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; + a.diag("tuple assignment cannot be combined with an arithmetic operation") + return } // Create temporary block for extractEffect - bc := a.enterChild(); - defer bc.exit(); + bc := a.enterChild() + defer bc.exit() - l := a.compileExpr(bc.block, false, s.Lhs[0]); - r := a.compileExpr(bc.block, false, s.Rhs[0]); + 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; + l.diag("cannot assign to %s", l.desc) + return } - effect, l := l.extractEffect(bc.block, "operator-assignment"); + effect, l := l.extractEffect(bc.block, "operator-assignment") - binop := r.compileBinaryExpr(assignOpToOp[s.Tok], l, r); + 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"); + 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; + lf := l.evalAddr a.push(func(t *Thread) { - effect(t); - assign(lf(t), t); - }); + effect(t) + assign(lf(t), t) + }) } func (a *stmtCompiler) compileAssignStmt(s *ast.AssignStmt) { @@ -802,25 +802,25 @@ func (a *stmtCompiler) compileAssignStmt(s *ast.AssignStmt) { func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) { if a.fnType == nil { - a.diag("cannot return at the top level"); - return; + 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; + a.flow.putTerm() + a.push(func(v *Thread) { v.pc = returnPC }) + return } - bc := a.enterChild(); - defer bc.exit(); + bc := a.enterChild() + defer bc.exit() // Compile expressions - bad := false; - rs := make([]*expr, len(s.Results)); + bad := false + rs := make([]*expr, len(s.Results)) for i, re := range s.Results { - rs[i] = a.compileExpr(bc.block, false, re); + rs[i] = a.compileExpr(bc.block, false, re) if rs[i] == nil { bad = true } @@ -835,38 +835,38 @@ func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) { // 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"); + 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(); + 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; - }); + 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; + bc := a.blockCompiler for ; bc != nil; bc = bc.parent { if bc.label == nil { continue } - l := bc.label; + 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; + a.diag("cannot %s to %s %s", errOp, l.desc, l.name) + return nil } - return l; + return l } } if name == nil { @@ -874,54 +874,54 @@ func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool, } else { a.diag("%s label %s not defined", errOp, name.Value) } - return nil; + return nil } func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) { - var pc *uint; + 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"); + 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; + pc = l.breakPC case token.CONTINUE: - l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop"); + l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop") if l == nil { return } - pc = l.continuePC; + pc = l.continuePC case token.GOTO: - l, ok := a.labels[s.Label.Value]; + 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 := 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); + pc = l.gotoPC + a.flow.putGoto(s.Pos(), l.name, a.block) case token.FALLTHROUGH: - a.diag("fallthrough outside switch"); - return; + 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 }); + 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(); + bc := a.enterChild() + bc.compileStmts(s) + bc.exit() } func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) { @@ -935,59 +935,59 @@ func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) { // 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(); + bc := a.enterChild() + defer bc.exit() // Compile init statement, if any if s.Init != nil { bc.compileStmt(s.Init) } - elsePC := badPC; - endPC := badPC; + 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); + 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); + 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(); + 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); + 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(); + endPC = a.nextPC() } func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { // Create implicit scope around switch - bc := a.enterChild(); - defer bc.exit(); + bc := a.enterChild() + defer bc.exit() // Compile init statement, if any if s.Init != nil { @@ -995,46 +995,46 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { } // Compile condition, if any, and extract its effects - var cond *expr; - condbc := bc.enterChild(); + var cond *expr + condbc := bc.enterChild() if s.Tag != nil { - e := condbc.compileExpr(condbc.block, false, s.Tag); + 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); + var effect func(*Thread) + effect, cond = e.extractEffect(condbc.block, "switch") + a.push(effect) } } // Count cases - ncases := 0; - hasDefault := false; + ncases := 0 + hasDefault := false for _, c := range s.Body.List { - clause, ok := c.(*ast.CaseClause); + clause, ok := c.(*ast.CaseClause) if !ok { - a.diagAt(clause, "switch statement must contain case clauses"); - continue; + 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; + hasDefault = true } else { ncases += len(clause.Values) } } // Compile case expressions - cases := make([]func(*Thread) bool, ncases); - i := 0; + cases := make([]func(*Thread) bool, ncases) + i := 0 for _, c := range s.Body.List { - clause, ok := c.(*ast.CaseClause); + clause, ok := c.(*ast.CaseClause) if !ok { continue } for _, v := range clause.Values { - e := condbc.compileExpr(condbc.block, false, v); + e := condbc.compileExpr(condbc.block, false, v) switch { case e == nil: // Error reported by compileExpr @@ -1045,45 +1045,45 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { case cond != nil: // Create comparison // TOOD(austin) This produces bad error messages - compare := e.compileBinaryExpr(token.EQL, cond, e); + compare := e.compileBinaryExpr(token.EQL, cond, e) if compare != nil { cases[i] = compare.asBool() } } - i++; + i++ } } // Emit condition - casePCs := make([]*uint, ncases+1); - endPC := badPC; + casePCs := make([]*uint, ncases+1) + endPC := badPC - a.flow.put(false, false, casePCs); + 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[i] + return } } - t.pc = *casePCs[ncases]; - }); - condbc.exit(); + t.pc = *casePCs[ncases] + }) + condbc.exit() // Compile cases - i = 0; + i = 0 for _, c := range s.Body.List { - clause, ok := c.(*ast.CaseClause); + clause, ok := c.(*ast.CaseClause) if !ok { continue } // Save jump PC's - pc := a.nextPC(); + pc := a.nextPC() if clause.Values != nil { for _ = range clause.Values { - casePCs[i] = &pc; - i++; + casePCs[i] = &pc + i++ } } else { // Default clause @@ -1091,7 +1091,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { } // Compile body - fall := false; + fall := false for j, s := range clause.Body { if br, ok := s.(*ast.BranchStmt); ok && br.Tok == token.FALLTHROUGH { // println("Found fallthrough"); @@ -1104,24 +1104,24 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { // empty blocks to be empty // statements. if _, ok := s2.(*ast.EmptyStmt); !ok { - a.diagAt(s, "fallthrough statement must be final statement in case"); - break; + a.diagAt(s, "fallthrough statement must be final statement in case") + break } } - fall = true; + 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 }); + a.flow.put1(false, &endPC) + a.push(func(v *Thread) { v.pc = endPC }) } } // Get end PC - endPC = a.nextPC(); + endPC = a.nextPC() if !hasDefault { casePCs[ncases] = &endPC } @@ -1129,40 +1129,40 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) { // Wrap the entire for in a block. - bc := a.enterChild(); - defer bc.exit(); + 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; + 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 }); + a.flow.put1(false, &checkPC) + a.push(func(v *Thread) { v.pc = checkPC }) // Compile body - bodyPC = a.nextPC(); - body := bc.enterChild(); + 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(); + 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(); + postPC = a.nextPC() if s.Post != nil { // TODO(austin) Does the parser disallow short // declarations in s.Post? @@ -1170,30 +1170,30 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) { } // Compile condition check, if any - checkPC = a.nextPC(); + 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 }); + a.flow.put1(false, &bodyPC) + a.push(func(v *Thread) { v.pc = bodyPC }) } else { - e := bc.compileExpr(bc.block, false, s.Cond); + 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); + eval := e.asBool() + a.flow.put1(true, &bodyPC) a.push(func(t *Thread) { if eval(t) { t.pc = bodyPC } - }); + }) } } - endPC = a.nextPC(); + endPC = a.nextPC() } /* @@ -1201,8 +1201,8 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) { */ func (a *blockCompiler) compileStmt(s ast.Stmt) { - sc := &stmtCompiler{a, s.Pos(), nil}; - sc.compile(s); + sc := &stmtCompiler{a, s.Pos(), nil} + sc.compile(s) } func (a *blockCompiler) compileStmts(block *ast.BlockStmt) { @@ -1212,15 +1212,15 @@ func (a *blockCompiler) compileStmts(block *ast.BlockStmt) { } func (a *blockCompiler) enterChild() *blockCompiler { - block := a.block.enterChild(); + block := a.block.enterChild() return &blockCompiler{ funcCompiler: a.funcCompiler, block: block, parent: a, - }; + } } -func (a *blockCompiler) exit() { a.block.exit() } +func (a *blockCompiler) exit() { a.block.exit() } /* * Function compiler @@ -1231,8 +1231,8 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f // // The scope of a parameter or result is the body of the // corresponding function. - bodyScope := b.ChildScope(); - defer bodyScope.exit(); + 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) @@ -1249,7 +1249,7 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f } // Create block context - cb := newCodeBuf(); + cb := newCodeBuf() fc := &funcCompiler{ compiler: a, fnType: decl.Type, @@ -1257,16 +1257,16 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f 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(); + nerr := a.numError() + bc.compileStmts(body) + fc.checkLabels() if nerr != a.numError() { return nil } @@ -1275,19 +1275,19 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f // 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; + 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} }; + 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(); + nerr := a.numError() for _, l := range a.labels { if !l.resolved.IsValid() { a.diagAt(&l.used, "label %s not defined", l.name) @@ -1301,5 +1301,5 @@ func (a *funcCompiler) checkLabels() { // 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); + a.flow.gotosObeyScopes(a.compiler) } |
