mirror of
https://github.com/golang/go
synced 2024-11-23 00:30:07 -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:
parent
87f2208bda
commit
36eee6d1e1
@ -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
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user