mirror of
https://github.com/golang/go
synced 2024-11-26 02:17:58 -07:00
Gather errors in a go.scanner.ErrorList instead of printing
them as we go. Lots of bug fixes. Let the parser toss illegal character and string literals. Compile unary + correctly. Allow float OP ideal. Compile unary * correctly. Implement min and max float values. R=rsc APPROVED=rsc DELTA=64 (29 added, 7 deleted, 28 changed) OCL=31811 CL=31814
This commit is contained in:
parent
b63d40a53e
commit
51c0a84175
@ -7,9 +7,12 @@ package eval
|
|||||||
import (
|
import (
|
||||||
"bignum";
|
"bignum";
|
||||||
"eval";
|
"eval";
|
||||||
|
"fmt";
|
||||||
"go/ast";
|
"go/ast";
|
||||||
|
"go/scanner";
|
||||||
"go/token";
|
"go/token";
|
||||||
"log";
|
"log";
|
||||||
|
"os";
|
||||||
"strconv";
|
"strconv";
|
||||||
"strings";
|
"strings";
|
||||||
)
|
)
|
||||||
@ -19,7 +22,7 @@ import (
|
|||||||
type exprContext struct {
|
type exprContext struct {
|
||||||
scope *Scope;
|
scope *Scope;
|
||||||
constant bool;
|
constant bool;
|
||||||
// TODO(austin) Error list
|
errors scanner.ErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// An exprCompiler compiles a single node in an expression. It stores
|
// An exprCompiler compiles a single node in an expression. It stores
|
||||||
@ -82,7 +85,7 @@ func (a *exprCompiler) fork(x ast.Expr) *exprCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *exprCompiler) diag(format string, args ...) {
|
func (a *exprCompiler) diag(format string, args ...) {
|
||||||
diag(a.pos, format, args);
|
a.errors.Error(a.pos, fmt.Sprintf(format, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *exprCompiler) diagOpType(op token.Token, vt Type) {
|
func (a *exprCompiler) diagOpType(op token.Token, vt Type) {
|
||||||
@ -205,25 +208,22 @@ func (a *exprCompiler) DoIntLit(x *ast.IntLit) {
|
|||||||
|
|
||||||
func (a *exprCompiler) DoCharLit(x *ast.CharLit) {
|
func (a *exprCompiler) DoCharLit(x *ast.CharLit) {
|
||||||
if x.Value[0] != '\'' {
|
if x.Value[0] != '\'' {
|
||||||
// Shouldn't get past the parser
|
log.Crashf("malformed character literal %s at %v passed parser", x.Value, x.Pos());
|
||||||
log.Crashf("unexpected character literal %s at %v", x.Value, x.Pos());
|
|
||||||
}
|
}
|
||||||
v, mb, tail, err := strconv.UnquoteChar(string(x.Value[1:len(x.Value)]), '\'');
|
v, mb, tail, err := strconv.UnquoteChar(string(x.Value[1:len(x.Value)]), '\'');
|
||||||
if err != nil {
|
if err != nil || tail != "'" {
|
||||||
a.diag("illegal character literal, %v", err);
|
log.Crashf("malformed character literal %s at %v passed parser", x.Value, x.Pos());
|
||||||
return;
|
|
||||||
}
|
|
||||||
if tail != "'" {
|
|
||||||
a.diag("character literal must contain only one character");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
a.doIdealInt(bignum.Int(int64(v)));
|
a.doIdealInt(bignum.Int(int64(v)));
|
||||||
a.desc = "character literal";
|
a.desc = "character literal";
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *exprCompiler) DoFloatLit(x *ast.FloatLit) {
|
func (a *exprCompiler) DoFloatLit(x *ast.FloatLit) {
|
||||||
|
f, _, n := bignum.RatFromString(string(x.Value), 0);
|
||||||
|
if n != len(x.Value) {
|
||||||
|
log.Crashf("malformed float literal %s at %v passed parser", x.Value, x.Pos());
|
||||||
|
}
|
||||||
a.t = IdealFloatType;
|
a.t = IdealFloatType;
|
||||||
f, _, _2 := bignum.RatFromString(string(x.Value), 0);
|
|
||||||
a.evalIdealFloat = func() *bignum.Rational { return f };
|
a.evalIdealFloat = func() *bignum.Rational { return f };
|
||||||
a.desc = "float literal";
|
a.desc = "float literal";
|
||||||
}
|
}
|
||||||
@ -370,7 +370,7 @@ func (a *exprCompiler) DoUnaryExpr(x *ast.UnaryExpr) {
|
|||||||
switch x.Op {
|
switch x.Op {
|
||||||
case token.ADD:
|
case token.ADD:
|
||||||
// Just compile it out
|
// Just compile it out
|
||||||
a = v;
|
*a = *v;
|
||||||
|
|
||||||
case token.SUB:
|
case token.SUB:
|
||||||
a.genUnaryOpNeg(v);
|
a.genUnaryOpNeg(v);
|
||||||
@ -492,9 +492,9 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
|
|||||||
// numeric type and the other operand is an ideal
|
// numeric type and the other operand is an ideal
|
||||||
// number, the ideal number is converted to match the
|
// number, the ideal number is converted to match the
|
||||||
// type of the other operand.
|
// type of the other operand.
|
||||||
if l.t.isInteger() && !l.t.isIdeal() && r.t.isIdeal() {
|
if (l.t.isInteger() || l.t.isFloat()) && !l.t.isIdeal() && r.t.isIdeal() {
|
||||||
r = r.convertTo(l.t);
|
r = r.convertTo(l.t);
|
||||||
} else if r.t.isInteger() && !r.t.isIdeal() && l.t.isIdeal() {
|
} else if (r.t.isInteger() || r.t.isFloat()) && !r.t.isIdeal() && l.t.isIdeal() {
|
||||||
l = l.convertTo(r.t);
|
l = l.convertTo(r.t);
|
||||||
}
|
}
|
||||||
if l == nil || r == nil {
|
if l == nil || r == nil {
|
||||||
@ -782,8 +782,8 @@ func (a *exprCompiler) DoChanType(x *ast.ChanType) {
|
|||||||
log.Crash("Not implemented");
|
log.Crash("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileExpr(expr ast.Expr, scope *Scope) *exprCompiler {
|
func compileExpr(expr ast.Expr, scope *Scope, errors scanner.ErrorHandler) *exprCompiler {
|
||||||
ec := newExprCompiler(&exprContext{scope, false}, expr.Pos());
|
ec := newExprCompiler(&exprContext{scope, false, errors}, expr.Pos());
|
||||||
expr.Visit(ec);
|
expr.Visit(ec);
|
||||||
if ec.t == nil {
|
if ec.t == nil {
|
||||||
return nil;
|
return nil;
|
||||||
@ -803,34 +803,36 @@ func (expr *Expr) Eval(f *Frame) Value {
|
|||||||
return expr.f(f);
|
return expr.f(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
func CompileExpr(expr ast.Expr, scope *Scope) *Expr {
|
func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) {
|
||||||
ec := compileExpr(expr, scope);
|
errors := scanner.NewErrorVector();
|
||||||
|
|
||||||
|
ec := compileExpr(expr, scope, errors);
|
||||||
if ec == nil {
|
if ec == nil {
|
||||||
return nil;
|
return nil, errors.GetError(scanner.Sorted);
|
||||||
}
|
}
|
||||||
// TODO(austin) This still uses Value as a generic container
|
// TODO(austin) This still uses Value as a generic container
|
||||||
// and is the only user of the 'value' methods on each type.
|
// and is the only user of the 'value' methods on each type.
|
||||||
// Need to figure out a better way to do this.
|
// Need to figure out a better way to do this.
|
||||||
switch t := ec.t.(type) {
|
switch t := ec.t.(type) {
|
||||||
case *boolType:
|
case *boolType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalBool(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalBool(f)) }}, nil;
|
||||||
case *uintType:
|
case *uintType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalUint(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalUint(f)) }}, nil;
|
||||||
case *intType:
|
case *intType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalInt(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalInt(f)) }}, nil;
|
||||||
case *idealIntType:
|
case *idealIntType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealInt()) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealInt()) }}, nil;
|
||||||
case *floatType:
|
case *floatType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalFloat(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalFloat(f)) }}, nil;
|
||||||
case *idealFloatType:
|
case *idealFloatType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealFloat()) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealFloat()) }}, nil;
|
||||||
case *stringType:
|
case *stringType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalString(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalString(f)) }}, nil;
|
||||||
case *PtrType:
|
case *PtrType:
|
||||||
return &Expr{func(f *Frame) Value { return t.value(ec.evalPtr(f)) }};
|
return &Expr{func(f *Frame) Value { return t.value(ec.evalPtr(f)) }}, nil;
|
||||||
}
|
}
|
||||||
log.Crashf("unexpected type %v", ec.t);
|
log.Crashf("unexpected type %v", ec.t);
|
||||||
return nil;
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -859,7 +861,7 @@ func (a *exprCompiler) genIdentOp(t Type, s *Scope, index int) {
|
|||||||
|
|
||||||
func (a *exprCompiler) genStarOp(v *exprCompiler) {
|
func (a *exprCompiler) genStarOp(v *exprCompiler) {
|
||||||
vf := v.asPtr();
|
vf := v.asPtr();
|
||||||
switch _ := v.t.literal().(type) {
|
switch _ := v.t.literal().(*PtrType).Elem().literal().(type) {
|
||||||
case *boolType:
|
case *boolType:
|
||||||
a.evalBool = func(f *Frame) bool { return vf(f).(BoolValue).Get() };
|
a.evalBool = func(f *Frame) bool { return vf(f).(BoolValue).Get() };
|
||||||
case *uintType:
|
case *uintType:
|
||||||
@ -873,7 +875,7 @@ func (a *exprCompiler) genStarOp(v *exprCompiler) {
|
|||||||
case *PtrType:
|
case *PtrType:
|
||||||
a.evalPtr = func(f *Frame) Value { return vf(f).(PtrValue).Get() };
|
a.evalPtr = func(f *Frame) Value { return vf(f).(PtrValue).Get() };
|
||||||
default:
|
default:
|
||||||
log.Crashf("unexpected operand type %v at %v", v.t.literal(), a.pos);
|
log.Crashf("unexpected operand type %v at %v", v.t.literal().(*PtrType).Elem().literal(), a.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ package eval
|
|||||||
import (
|
import (
|
||||||
"bignum";
|
"bignum";
|
||||||
"eval";
|
"eval";
|
||||||
|
"log";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -224,12 +225,31 @@ func (t *floatType) String() string {
|
|||||||
|
|
||||||
func (t *floatType) value(v float64) FloatValue
|
func (t *floatType) value(v float64) FloatValue
|
||||||
|
|
||||||
|
var maxFloat32Val = bignum.MakeRat(bignum.Int(0xffffff).Shl(127-23), bignum.Nat(1));
|
||||||
|
var maxFloat64Val = bignum.MakeRat(bignum.Int(0x1fffffffffffff).Shl(1023-52), bignum.Nat(1));
|
||||||
|
var minFloat32Val = maxFloat32Val.Neg();
|
||||||
|
var minFloat64Val = maxFloat64Val.Neg();
|
||||||
|
|
||||||
func (t *floatType) minVal() *bignum.Rational {
|
func (t *floatType) minVal() *bignum.Rational {
|
||||||
panic("Not implemented");
|
switch t.Bits {
|
||||||
|
case 32:
|
||||||
|
return minFloat32Val;
|
||||||
|
case 64:
|
||||||
|
return minFloat64Val;
|
||||||
|
}
|
||||||
|
log.Crashf("unexpected number of floating point bits: %d", t.Bits);
|
||||||
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *floatType) maxVal() *bignum.Rational {
|
func (t *floatType) maxVal() *bignum.Rational {
|
||||||
panic("Not implemented");
|
switch t.Bits {
|
||||||
|
case 32:
|
||||||
|
return maxFloat32Val;
|
||||||
|
case 64:
|
||||||
|
return maxFloat64Val;
|
||||||
|
}
|
||||||
|
log.Crashf("unexpected number of floating point bits: %d", t.Bits);
|
||||||
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
type idealFloatType struct {
|
type idealFloatType struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user