1
0
mirror of https://github.com/golang/go synced 2024-11-25 21:07:56 -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:
Austin Clements 2009-07-17 16:58:59 -07:00
parent b63d40a53e
commit 51c0a84175
2 changed files with 55 additions and 33 deletions

View File

@ -7,9 +7,12 @@ package eval
import (
"bignum";
"eval";
"fmt";
"go/ast";
"go/scanner";
"go/token";
"log";
"os";
"strconv";
"strings";
)
@ -19,7 +22,7 @@ import (
type exprContext struct {
scope *Scope;
constant bool;
// TODO(austin) Error list
errors scanner.ErrorHandler;
}
// 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 ...) {
diag(a.pos, format, args);
a.errors.Error(a.pos, fmt.Sprintf(format, args));
}
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) {
if x.Value[0] != '\'' {
// Shouldn't get past the parser
log.Crashf("unexpected character literal %s at %v", x.Value, x.Pos());
log.Crashf("malformed character literal %s at %v passed parser", x.Value, x.Pos());
}
v, mb, tail, err := strconv.UnquoteChar(string(x.Value[1:len(x.Value)]), '\'');
if err != nil {
a.diag("illegal character literal, %v", err);
return;
}
if tail != "'" {
a.diag("character literal must contain only one character");
return;
if err != nil || tail != "'" {
log.Crashf("malformed character literal %s at %v passed parser", x.Value, x.Pos());
}
a.doIdealInt(bignum.Int(int64(v)));
a.desc = "character literal";
}
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;
f, _, _2 := bignum.RatFromString(string(x.Value), 0);
a.evalIdealFloat = func() *bignum.Rational { return f };
a.desc = "float literal";
}
@ -370,7 +370,7 @@ func (a *exprCompiler) DoUnaryExpr(x *ast.UnaryExpr) {
switch x.Op {
case token.ADD:
// Just compile it out
a = v;
*a = *v;
case token.SUB:
a.genUnaryOpNeg(v);
@ -492,9 +492,9 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
// numeric type and the other operand is an ideal
// number, the ideal number is converted to match the
// 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);
} 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);
}
if l == nil || r == nil {
@ -782,8 +782,8 @@ func (a *exprCompiler) DoChanType(x *ast.ChanType) {
log.Crash("Not implemented");
}
func compileExpr(expr ast.Expr, scope *Scope) *exprCompiler {
ec := newExprCompiler(&exprContext{scope, false}, expr.Pos());
func compileExpr(expr ast.Expr, scope *Scope, errors scanner.ErrorHandler) *exprCompiler {
ec := newExprCompiler(&exprContext{scope, false, errors}, expr.Pos());
expr.Visit(ec);
if ec.t == nil {
return nil;
@ -803,34 +803,36 @@ func (expr *Expr) Eval(f *Frame) Value {
return expr.f(f);
}
func CompileExpr(expr ast.Expr, scope *Scope) *Expr {
ec := compileExpr(expr, scope);
func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) {
errors := scanner.NewErrorVector();
ec := compileExpr(expr, scope, errors);
if ec == nil {
return nil;
return nil, errors.GetError(scanner.Sorted);
}
// TODO(austin) This still uses Value as a generic container
// and is the only user of the 'value' methods on each type.
// Need to figure out a better way to do this.
switch t := ec.t.(type) {
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:
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:
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:
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:
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:
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:
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:
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);
return nil;
panic();
}
/*
@ -859,7 +861,7 @@ func (a *exprCompiler) genIdentOp(t Type, s *Scope, index int) {
func (a *exprCompiler) genStarOp(v *exprCompiler) {
vf := v.asPtr();
switch _ := v.t.literal().(type) {
switch _ := v.t.literal().(*PtrType).Elem().literal().(type) {
case *boolType:
a.evalBool = func(f *Frame) bool { return vf(f).(BoolValue).Get() };
case *uintType:
@ -873,7 +875,7 @@ func (a *exprCompiler) genStarOp(v *exprCompiler) {
case *PtrType:
a.evalPtr = func(f *Frame) Value { return vf(f).(PtrValue).Get() };
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);
}
}

View File

@ -7,6 +7,7 @@ package eval
import (
"bignum";
"eval";
"log";
)
@ -224,12 +225,31 @@ func (t *floatType) String() string {
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 {
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 {
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 {