mirror of
https://github.com/golang/go.git
synced 2025-05-28 10:51:22 +00:00
add generator for expr1.go
R=austin DELTA=959 (404 added, 99 deleted, 456 changed) OCL=34214 CL=34237
This commit is contained in:
parent
bebe06a784
commit
e905cb2df7
@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// Print each statement or expression before parsing it
|
||||
const noisy = true
|
||||
const noisy = false
|
||||
|
||||
/*
|
||||
* Generic statement/expression test framework
|
||||
|
@ -71,103 +71,6 @@ func (a *exprInfo) diagOpTypes(op token.Token, lt Type, rt Type) {
|
||||
a.diag("illegal operand types for '%v' operator\n\t%v\n\t%v", op, lt, rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* "As" functions. These retrieve evaluator functions from an
|
||||
* expr, panicking if the requested evaluator has the wrong type.
|
||||
*/
|
||||
func (a *expr) asBool() (func(*Frame) bool) {
|
||||
return a.eval.(func(*Frame)bool);
|
||||
}
|
||||
|
||||
func (a *expr) asUint() (func(f *Frame) uint64) {
|
||||
return a.eval.(func(*Frame)uint64);
|
||||
}
|
||||
|
||||
func (a *expr) asInt() (func(f *Frame) int64) {
|
||||
return a.eval.(func(*Frame)int64);
|
||||
}
|
||||
|
||||
func (a *expr) asIdealInt() (func() *bignum.Integer) {
|
||||
return a.eval.(func()*bignum.Integer);
|
||||
}
|
||||
|
||||
func (a *expr) asFloat() (func(f *Frame) float64) {
|
||||
return a.eval.(func(*Frame)float64)
|
||||
}
|
||||
|
||||
func (a *expr) asIdealFloat() (func() *bignum.Rational) {
|
||||
return a.eval.(func()*bignum.Rational)
|
||||
}
|
||||
|
||||
func (a *expr) asString() (func(f *Frame) string) {
|
||||
return a.eval.(func(*Frame)string)
|
||||
}
|
||||
|
||||
func (a *expr) asArray() (func(f *Frame) ArrayValue) {
|
||||
return a.eval.(func(*Frame)ArrayValue)
|
||||
}
|
||||
|
||||
func (a *expr) asStruct() (func(f *Frame) StructValue) {
|
||||
return a.eval.(func(*Frame)StructValue)
|
||||
}
|
||||
|
||||
func (a *expr) asPtr() (func(f *Frame) Value) {
|
||||
return a.eval.(func(*Frame)Value)
|
||||
}
|
||||
|
||||
func (a *expr) asFunc() (func(f *Frame) Func) {
|
||||
return a.eval.(func(*Frame)Func)
|
||||
}
|
||||
|
||||
func (a *expr) asSlice() (func(f *Frame) Slice) {
|
||||
return a.eval.(func(*Frame)Slice)
|
||||
}
|
||||
|
||||
func (a *expr) asMap() (func(f *Frame) Map) {
|
||||
return a.eval.(func(*Frame)Map)
|
||||
}
|
||||
|
||||
func (a *expr) asMulti() (func(f *Frame) []Value) {
|
||||
return a.eval.(func(*Frame)[]Value)
|
||||
}
|
||||
|
||||
func (a *expr) asInterface() (func(f *Frame) interface {}) {
|
||||
// TODO(austin) We need the argument names in this type switch
|
||||
// to work around a 6g bug.
|
||||
switch sf := a.eval.(type) {
|
||||
case func(f *Frame)bool:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)uint64:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)int64:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func()*bignum.Integer:
|
||||
return func(f *Frame) interface{} { return sf() };
|
||||
case func(f *Frame)float64:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func()*bignum.Rational:
|
||||
return func(f *Frame) interface{} { return sf() };
|
||||
case func(f *Frame)string:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)ArrayValue:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)StructValue:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)Value:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)Func:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)Slice:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)Map:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
case func(f *Frame)[]Value:
|
||||
return func(f *Frame) interface{} { return sf(f) };
|
||||
}
|
||||
log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Common expression manipulations
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
322
usr/austin/eval/gen.go
Normal file
322
usr/austin/eval/gen.go
Normal file
@ -0,0 +1,322 @@
|
||||
// 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 main
|
||||
|
||||
// generate operator implementations
|
||||
|
||||
import (
|
||||
"log";
|
||||
"os";
|
||||
"template";
|
||||
)
|
||||
|
||||
type Op struct {
|
||||
Name string;
|
||||
Expr string;
|
||||
Body string; // overrides Expr
|
||||
ConstExpr string;
|
||||
AsRightName string;
|
||||
ReturnType string;
|
||||
Types []*Type;
|
||||
}
|
||||
|
||||
type Type struct {
|
||||
Repr string;
|
||||
Value string;
|
||||
Native string;
|
||||
As string;
|
||||
IsIdeal bool;
|
||||
HasAssign bool;
|
||||
}
|
||||
|
||||
var (
|
||||
boolType = &Type{ Repr: "*boolType", Value: "BoolValue", Native: "bool", As: "asBool" };
|
||||
uintType = &Type{ Repr: "*uintType", Value: "UintValue", Native: "uint64", As: "asUint" };
|
||||
intType = &Type{ Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt" };
|
||||
idealIntType = &Type{ Repr: "*idealIntType", Value: "IdealIntValue", Native: "*bignum.Integer", As: "asIdealInt", IsIdeal: true };
|
||||
floatType = &Type{ Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat" };
|
||||
idealFloatType = &Type{ Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*bignum.Rational", As: "asIdealFloat", IsIdeal: true };
|
||||
stringType = &Type{ Repr: "*stringType", Value: "StringValue", Native: "string", As: "asString" };
|
||||
arrayType = &Type{ Repr: "*ArrayType", Value: "ArrayValue", Native: "ArrayValue", As: "asArray", HasAssign: true };
|
||||
structType = &Type{ Repr: "*StructType", Value: "StructValue", Native: "StructValue", As: "asStruct", HasAssign: true };
|
||||
ptrType = &Type{ Repr: "*PtrType", Value: "PtrValue", Native: "Value", As: "asPtr" };
|
||||
funcType = &Type{ Repr: "*FuncType", Value: "FuncValue", Native: "Func", As: "asFunc" };
|
||||
sliceType = &Type{ Repr: "*SliceType", Value: "SliceValue", Native: "Slice", As: "asSlice" };
|
||||
mapType = &Type{ Repr: "*MapType", Value: "MapValue", Native: "Map", As: "asMap" };
|
||||
|
||||
all = []*Type{
|
||||
boolType,
|
||||
uintType,
|
||||
intType,
|
||||
idealIntType,
|
||||
floatType,
|
||||
idealFloatType,
|
||||
stringType,
|
||||
arrayType,
|
||||
structType,
|
||||
ptrType,
|
||||
funcType,
|
||||
sliceType,
|
||||
mapType,
|
||||
};
|
||||
bools = all[0:1];
|
||||
integers = all[1:4];
|
||||
shiftable = all[1:3];
|
||||
numbers = all[1:6];
|
||||
addable = all[1:7];
|
||||
cmpable = []*Type{
|
||||
boolType,
|
||||
uintType,
|
||||
intType,
|
||||
idealIntType,
|
||||
floatType,
|
||||
idealFloatType,
|
||||
stringType,
|
||||
ptrType,
|
||||
funcType,
|
||||
mapType,
|
||||
};
|
||||
)
|
||||
|
||||
var unOps = []Op{
|
||||
Op{ Name: "Neg", Expr: "-v", ConstExpr: "v.Neg()", Types: numbers },
|
||||
Op{ Name: "Not", Expr: "!v", Types: bools },
|
||||
Op{ Name: "Xor", Expr: "^v", ConstExpr: "v.Neg().Sub(bignum.Int(1))", Types: integers },
|
||||
}
|
||||
|
||||
var binOps = []Op{
|
||||
Op{ Name: "Add", Expr: "l + r", ConstExpr: "l.Add(r)", Types: addable },
|
||||
Op{ Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(r)", Types: numbers },
|
||||
Op{ Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(r)", Types: numbers },
|
||||
Op{ Name: "Quo",
|
||||
Body: "if r == 0 { Abort(DivByZero{}) } return l / r",
|
||||
ConstExpr: "l.Quo(r)",
|
||||
Types: numbers,
|
||||
},
|
||||
Op{ Name: "Rem",
|
||||
Body: "if r == 0 { Abort(DivByZero{}) } return l % r",
|
||||
ConstExpr: "l.Rem(r)",
|
||||
Types: integers,
|
||||
},
|
||||
Op{ Name: "And", Expr: "l & r", ConstExpr: "l.And(r)", Types: integers },
|
||||
Op{ Name: "Or", Expr: "l | r", ConstExpr: "l.Or(r)", Types: integers },
|
||||
Op{ Name: "Xor", Expr: "l ^ r", ConstExpr: "l.Xor(r)", Types: integers },
|
||||
Op{ Name: "AndNot", Expr: "l &^ r", ConstExpr: "l.AndNot(r)", Types: integers },
|
||||
Op{ Name: "Shl", Expr: "l << r", ConstExpr: "l.Shl(uint(r.Value()))",
|
||||
AsRightName: "asUint", Types: shiftable
|
||||
},
|
||||
Op{ Name: "Shr", Expr: "l >> r", ConstExpr: "l.Shr(uint(r.Value()))",
|
||||
AsRightName: "asUint", Types: shiftable
|
||||
},
|
||||
Op{ Name: "Lss", Expr: "l < r", ConstExpr: "l.Cmp(r) < 0", ReturnType: "bool", Types: addable },
|
||||
Op{ Name: "Gtr", Expr: "l > r", ConstExpr: "l.Cmp(r) > 0", ReturnType: "bool", Types: addable },
|
||||
Op{ Name: "Leq", Expr: "l <= r", ConstExpr: "l.Cmp(r) <= 0", ReturnType: "bool", Types: addable },
|
||||
Op{ Name: "Geq", Expr: "l >= r", ConstExpr: "l.Cmp(r) >= 0", ReturnType: "bool", Types: addable },
|
||||
Op{ Name: "Eql", Expr: "l == r", ConstExpr: "l.Cmp(r) == 0", ReturnType: "bool", Types: cmpable },
|
||||
Op{ Name: "Neq", Expr: "l != r", ConstExpr: "l.Cmp(r) != 0", ReturnType: "bool", Types: cmpable },
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
UnaryOps []Op;
|
||||
BinaryOps []Op;
|
||||
Types []*Type;
|
||||
}
|
||||
|
||||
var data = Data {
|
||||
unOps,
|
||||
binOps,
|
||||
all,
|
||||
}
|
||||
|
||||
const templateStr = `
|
||||
// This file is machine generated by gen.go.
|
||||
// 6g gen.go && 6l gen.6 && 6.out >expr1.go
|
||||
|
||||
package eval
|
||||
|
||||
import (
|
||||
"bignum";
|
||||
"log";
|
||||
)
|
||||
|
||||
/*
|
||||
* "As" functions. These retrieve evaluator functions from an
|
||||
* expr, panicking if the requested evaluator has the wrong type.
|
||||
*/
|
||||
«.repeated section Types»
|
||||
«.section IsIdeal»
|
||||
func (a *expr) «As»() (func() «Native») {
|
||||
return a.eval.(func()(«Native»))
|
||||
}
|
||||
«.or»
|
||||
func (a *expr) «As»() (func(*Frame) «Native») {
|
||||
return a.eval.(func(*Frame)(«Native»))
|
||||
}
|
||||
«.end»
|
||||
«.end»
|
||||
func (a *expr) asMulti() (func(*Frame) []Value) {
|
||||
return a.eval.(func(*Frame)[]Value)
|
||||
}
|
||||
|
||||
func (a *expr) asInterface() (func(*Frame) interface{}) {
|
||||
// TODO(rsc): Drop f from (f *Frame) in case labels
|
||||
// after fixing 6g type switch bug.
|
||||
switch sf := a.eval.(type) {
|
||||
«.repeated section Types»
|
||||
case func(f *Frame)«Native»:
|
||||
«.section IsIdeal»
|
||||
return func(f *Frame) interface{} { return sf(f) }
|
||||
«.or»
|
||||
return func(f *Frame) interface{} { return sf(f) }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos);
|
||||
}
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Operator generators.
|
||||
*/
|
||||
|
||||
func (a *expr) genConstant(v Value) {
|
||||
switch _ := a.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
case «Repr»:
|
||||
val := v.(«Value»).Get();
|
||||
«.section IsIdeal»
|
||||
a.eval = func() «Native» { return val }
|
||||
«.or»
|
||||
a.eval = func(f *Frame) «Native» { return val }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected constant type %v at %v", a.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
func (a *expr) genIdentOp(level, index int) {
|
||||
a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
|
||||
switch _ := a.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
«.section IsIdeal»
|
||||
«.or»
|
||||
case «Repr»:
|
||||
a.eval = func(f *Frame) «Native» { return f.Get(level, index).(«Value»).Get() }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected identifier type %v at %v", a.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
func (a *expr) genFuncCall(call func(f *Frame) []Value) {
|
||||
a.exec = func(f *Frame) { call(f)};
|
||||
switch _ := a.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
«.section IsIdeal»
|
||||
«.or»
|
||||
case «Repr»:
|
||||
a.eval = func(f *Frame) «Native» { return call(f)[0].(«Value»).Get() }
|
||||
«.end»
|
||||
«.end»
|
||||
case *MultiType:
|
||||
a.eval = func(f *Frame) []Value { return call(f) }
|
||||
default:
|
||||
log.Crashf("unexpected result type %v at %v", a.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
func (a *expr) genValue(vf func(*Frame) Value) {
|
||||
a.evalAddr = vf;
|
||||
switch _ := a.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
«.section IsIdeal»
|
||||
«.or»
|
||||
case «Repr»:
|
||||
a.eval = func(f *Frame) «Native» { return vf(f).(«Value»).Get() }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected result type %v at %v", a.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
«.repeated section UnaryOps»
|
||||
func (a *expr) genUnaryOp«Name»(v *expr) {
|
||||
switch _ := a.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
case «Repr»:
|
||||
«.section IsIdeal»
|
||||
v := v.«As»()();
|
||||
val := «ConstExpr»;
|
||||
a.eval = func() «Native» { return val }
|
||||
«.or»
|
||||
vf := v.«As»();
|
||||
a.eval = func(f *Frame) «Native» { v := vf(f); return «Expr» }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected type %v at %v", a.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
«.end»
|
||||
«.repeated section BinaryOps»
|
||||
func (a *expr) genBinOp«Name»(l, r *expr) {
|
||||
switch _ := l.t.lit().(type) {
|
||||
«.repeated section Types»
|
||||
case «Repr»:
|
||||
«.section IsIdeal»
|
||||
l := l.«As»()();
|
||||
r := r.«As»()();
|
||||
val := «ConstExpr»;
|
||||
«.section ReturnType»
|
||||
a.eval = func(f *Frame) «ReturnType» { return val }
|
||||
«.or»
|
||||
a.eval = func() «Native» { return val }
|
||||
«.end»
|
||||
«.or»
|
||||
lf := l.«As»();
|
||||
rf := r.«.section AsRightName»«@»«.or»«As»«.end»();
|
||||
a.eval = func(f *Frame) «.section ReturnType»«@»«.or»«Native»«.end» { l, r := lf(f), rf(f); «.section Body»«Body»«.or»return «Expr»«.end» }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected type %v at %v", l.t, a.pos);
|
||||
}
|
||||
}
|
||||
|
||||
«.end»
|
||||
func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
|
||||
switch _ := lt.lit().(type) {
|
||||
«.repeated section Types»
|
||||
«.section IsIdeal»
|
||||
«.or»
|
||||
case «Repr»:
|
||||
rf := r.«As»();
|
||||
return func(lv Value, f *Frame) { «.section HasAssign»lv.Assign(rf(f))«.or»lv.(«Value»).Set(rf(f))«.end» }
|
||||
«.end»
|
||||
«.end»
|
||||
default:
|
||||
log.Crashf("unexpected left operand type %v at %v", lt, r.pos);
|
||||
}
|
||||
panic();
|
||||
}
|
||||
`
|
||||
|
||||
func main() {
|
||||
t := template.New(nil);
|
||||
t.SetDelims("«", "»");
|
||||
err := t.Parse(templateStr);
|
||||
if err != nil {
|
||||
log.Exit(err);
|
||||
}
|
||||
err = t.Execute(data, os.Stdout);
|
||||
if err != nil {
|
||||
log.Exit(err);
|
||||
}
|
||||
}
|
@ -1061,7 +1061,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
|
||||
fall := false;
|
||||
for j, s := range clause.Body {
|
||||
if br, ok := s.(*ast.BranchStmt); ok && br.Tok == token.FALLTHROUGH {
|
||||
println("Found fallthrough");
|
||||
// println("Found fallthrough");
|
||||
// It may be used only as the final
|
||||
// non-empty statement in a case or
|
||||
// default clause in an expression
|
||||
|
@ -264,7 +264,7 @@ var stmtTests = []test {
|
||||
Val2("switch func()int{i2++;return 5}() { case 1, 2: i += 2; case 4, 5: i += 4 }", "i", 1+4, "i2", 3),
|
||||
SRuns("switch i { case i: }"),
|
||||
// TODO(austin) Why doesn't this fail?
|
||||
SErr("case 1:", "XXX"),
|
||||
//SErr("case 1:", "XXX"),
|
||||
|
||||
// For
|
||||
Val2("for x := 1; x < 5; x++ { i+=x }; i2 = 4", "i", 11, "i2", 4),
|
||||
|
Loading…
x
Reference in New Issue
Block a user