1
0
mirror of https://github.com/golang/go synced 2024-11-22 21:10:03 -07:00

Make the expression compiler not use the AST visitor. The

statement compiler will be fixed in a later CL.

The input and output of the expression compiler are now
clearly distinguished.  In the process, I made the individual
expression compilers operate on the compiled form of their
children instead of AST nodes.  As a result, there are now
fewer places where I hand-craft intermediate expression nodes.

The diff looks scarier than it is, mostly because exprCompiler
has been split into the input and output types, resulting in
lots of little renames.

R=rsc
APPROVED=rsc
DELTA=774  (204 added, 199 deleted, 371 changed)
OCL=33851
CL=33851
This commit is contained in:
Austin Clements 2009-08-25 17:57:40 -07:00
parent 87f2208bda
commit 36eee6d1e1
3 changed files with 507 additions and 502 deletions

View File

@ -76,15 +76,3 @@ type blockCompiler struct {
// for a function-level block. // for a function-level block.
parent *blockCompiler; parent *blockCompiler;
} }
// An exprContext stores information used throughout the compilation
// of a single expression. It does not embed funcCompiler because
// expressions can appear at top level.
//
// TODO(austin) Rename exprCompiler to exprNodeCompiler and rename
// this to exprCompiler.
type exprContext struct {
*compiler;
block *block;
constant bool;
}

File diff suppressed because it is too large Load Diff

View File

@ -356,7 +356,10 @@ func (a *stmtCompiler) DoLabeledStmt(s *ast.LabeledStmt) {
} }
func (a *stmtCompiler) DoExprStmt(s *ast.ExprStmt) { func (a *stmtCompiler) DoExprStmt(s *ast.ExprStmt) {
e := a.compileExpr(a.block, s.X, false); bc := a.enterChild();
defer bc.exit();
e := a.compileExpr(bc.block, false, s.X);
if e == nil { if e == nil {
return; return;
} }
@ -378,7 +381,7 @@ func (a *stmtCompiler) DoIncDecStmt(s *ast.IncDecStmt) {
bc := a.enterChild(); bc := a.enterChild();
defer bc.exit(); defer bc.exit();
l := a.compileExpr(bc.block, s.X, false); l := a.compileExpr(bc.block, false, s.X);
if l == nil { if l == nil {
return; return;
} }
@ -405,21 +408,18 @@ func (a *stmtCompiler) DoIncDecStmt(s *ast.IncDecStmt) {
log.Crashf("Unexpected IncDec token %v", s.Tok); log.Crashf("Unexpected IncDec token %v", s.Tok);
} }
effect, l := l.extractEffect(desc); effect, l := l.extractEffect(bc.block, desc);
one := l.copy(); one := l.newExpr(IdealIntType, "constant");
one.pos = s.Pos(); one.pos = s.Pos();
one.t = IdealIntType;
one.evalIdealInt = func() *bignum.Integer { return bignum.Int(1) }; one.evalIdealInt = func() *bignum.Integer { return bignum.Int(1) };
binop := l.copy(); binop := l.compileBinaryExpr(op, l, one);
binop.pos = s.Pos(); if binop == nil {
binop.doBinaryExpr(op, l, one);
if binop.t == nil {
return; return;
} }
assign := a.compileAssign(s.Pos(), l.t, []*exprCompiler{binop}, "", ""); assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "");
if assign == nil { if assign == nil {
log.Crashf("compileAssign type check failed"); log.Crashf("compileAssign type check failed");
} }
@ -438,9 +438,9 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
// Compile right side first so we have the types when // Compile right side first so we have the types when
// compiling the left side and so we don't see definitions // compiling the left side and so we don't see definitions
// made on the left side. // made on the left side.
rs := make([]*exprCompiler, len(rhs)); rs := make([]*expr, len(rhs));
for i, re := range rhs { for i, re := range rhs {
rs[i] = a.compileExpr(a.block, re, false); rs[i] = a.compileExpr(a.block, false, re);
if rs[i] == nil { if rs[i] == nil {
bad = true; bad = true;
} }
@ -474,7 +474,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
} }
// Compile left side // Compile left side
ls := make([]*exprCompiler, len(lhs)); ls := make([]*expr, len(lhs));
nDefs := 0; nDefs := 0;
for i, le := range lhs { for i, le := range lhs {
// If this is a definition, get the identifier and its type // If this is a definition, get the identifier and its type
@ -555,7 +555,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
} }
// Compile LHS // Compile LHS
ls[i] = a.compileExpr(a.block, le, false); ls[i] = a.compileExpr(a.block, false, le);
if ls[i] == nil { if ls[i] == nil {
bad = true; bad = true;
continue; continue;
@ -563,12 +563,13 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
if ls[i].evalMapValue != nil { if ls[i].evalMapValue != nil {
// Map indexes are not generally addressable, // Map indexes are not generally addressable,
// but they are assignable. If function call // but they are assignable.
// compiling took semantic values, this might //
// TODO(austin) Now that the expression
// compiler uses semantic values, this might
// be easier to implement as a function call. // be easier to implement as a function call.
sub := ls[i]; sub := ls[i];
ls[i] = sub.copy(); ls[i] = ls[i].newExpr(sub.t, sub.desc);
ls[i].t, ls[i].desc = sub.t, sub.desc;
ls[i].evalMapValue = sub.evalMapValue; ls[i].evalMapValue = sub.evalMapValue;
mvf := sub.evalMapValue; mvf := sub.evalMapValue;
et := sub.t; et := sub.t;
@ -621,7 +622,9 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
} }
lt = NewMultiType(lts); lt = NewMultiType(lts);
} }
assign := ac.compile(lt); bc := a.enterChild();
defer bc.exit();
assign := ac.compile(bc.block, lt);
if assign == nil { if assign == nil {
return; return;
} }
@ -690,8 +693,8 @@ func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
bc := a.enterChild(); bc := a.enterChild();
defer bc.exit(); defer bc.exit();
l := a.compileExpr(bc.block, s.Lhs[0], false); l := a.compileExpr(bc.block, false, s.Lhs[0]);
r := a.compileExpr(bc.block, s.Rhs[0], false); r := a.compileExpr(bc.block, false, s.Rhs[0]);
if l == nil || r == nil { if l == nil || r == nil {
return; return;
} }
@ -701,16 +704,14 @@ func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
return; return;
} }
effect, l := l.extractEffect("operator-assignment"); effect, l := l.extractEffect(bc.block, "operator-assignment");
binop := r.copy(); binop := r.compileBinaryExpr(assignOpToOp[s.Tok], l, r);
binop.pos = s.TokPos; if binop == nil {
binop.doBinaryExpr(assignOpToOp[s.Tok], l, r);
if binop.t == nil {
return; return;
} }
assign := a.compileAssign(s.Pos(), l.t, []*exprCompiler{binop}, "assignment", "value"); assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "assignment", "value");
if assign == nil { if assign == nil {
log.Crashf("compileAssign type check failed"); log.Crashf("compileAssign type check failed");
} }
@ -755,11 +756,14 @@ func (a *stmtCompiler) DoReturnStmt(s *ast.ReturnStmt) {
return; return;
} }
bc := a.enterChild();
defer bc.exit();
// Compile expressions // Compile expressions
bad := false; bad := false;
rs := make([]*exprCompiler, len(s.Results)); rs := make([]*expr, len(s.Results));
for i, re := range s.Results { for i, re := range s.Results {
rs[i] = a.compileExpr(a.block, re, false); rs[i] = a.compileExpr(bc.block, false, re);
if rs[i] == nil { if rs[i] == nil {
bad = true; bad = true;
} }
@ -774,7 +778,7 @@ func (a *stmtCompiler) DoReturnStmt(s *ast.ReturnStmt) {
// is a single call to a multi-valued function, the values // is a single call to a multi-valued function, the values
// returned from the called function will be returned from // returned from the called function will be returned from
// this one. // this one.
assign := a.compileAssign(s.Pos(), NewMultiType(a.fnType.Out), rs, "return", "value"); assign := a.compileAssign(s.Pos(), bc.block, NewMultiType(a.fnType.Out), rs, "return", "value");
if assign == nil { if assign == nil {
return; return;
} }
@ -896,7 +900,7 @@ func (a *stmtCompiler) DoIfStmt(s *ast.IfStmt) {
// fall through to the body. // fall through to the body.
bad := false; bad := false;
if s.Cond != nil { if s.Cond != nil {
e := bc.compileExpr(bc.block, s.Cond, false); e := bc.compileExpr(bc.block, false, s.Cond);
switch { switch {
case e == nil: case e == nil:
bad = true; bad = true;
@ -953,16 +957,16 @@ func (a *stmtCompiler) DoSwitchStmt(s *ast.SwitchStmt) {
} }
// Compile condition, if any, and extract its effects // Compile condition, if any, and extract its effects
var cond *exprCompiler; var cond *expr;
condbc := bc.enterChild(); condbc := bc.enterChild();
bad := false; bad := false;
if s.Tag != nil { if s.Tag != nil {
e := condbc.compileExpr(condbc.block, s.Tag, false); e := condbc.compileExpr(condbc.block, false, s.Tag);
if e == nil { if e == nil {
bad = true; bad = true;
} else { } else {
var effect func(f *Frame); var effect func(f *Frame);
effect, cond = e.extractEffect("switch"); effect, cond = e.extractEffect(condbc.block, "switch");
if effect == nil { if effect == nil {
bad = true; bad = true;
} }
@ -1000,7 +1004,7 @@ func (a *stmtCompiler) DoSwitchStmt(s *ast.SwitchStmt) {
continue; continue;
} }
for _, v := range clause.Values { for _, v := range clause.Values {
e := condbc.compileExpr(condbc.block, v, false); e := condbc.compileExpr(condbc.block, false, v);
switch { switch {
case e == nil: case e == nil:
bad = true; bad = true;
@ -1011,10 +1015,9 @@ func (a *stmtCompiler) DoSwitchStmt(s *ast.SwitchStmt) {
cases[i] = e.asBool(); cases[i] = e.asBool();
case cond != nil: case cond != nil:
// Create comparison // Create comparison
compare := e.copy();
// TOOD(austin) This produces bad error messages // TOOD(austin) This produces bad error messages
compare.doBinaryExpr(token.EQL, cond, e); compare := e.compileBinaryExpr(token.EQL, cond, e);
if compare.t == nil { if compare == nil {
bad = true; bad = true;
} else { } else {
cases[i] = compare.asBool(); cases[i] = compare.asBool();
@ -1170,7 +1173,7 @@ func (a *stmtCompiler) DoForStmt(s *ast.ForStmt) {
a.flow.put1(false, &bodyPC); a.flow.put1(false, &bodyPC);
a.push(func(v *vm) { v.pc = bodyPC }); a.push(func(v *vm) { v.pc = bodyPC });
} else { } else {
e := bc.compileExpr(bc.block, s.Cond, false); e := bc.compileExpr(bc.block, false, s.Cond);
switch { switch {
case e == nil: case e == nil:
bad = true; bad = true;