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