]> Cypherpunks repositories - gostls13.git/commitdiff
Gather errors in a go.scanner.ErrorList instead of printing
authorAustin Clements <aclements@csail.mit.edu>
Fri, 17 Jul 2009 23:58:59 +0000 (16:58 -0700)
committerAustin Clements <aclements@csail.mit.edu>
Fri, 17 Jul 2009 23:58:59 +0000 (16:58 -0700)
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

usr/austin/eval/expr.go
usr/austin/eval/type.go

index 752f9de6fdbed602a9500ec98fa007897f5f1306..6ab4ad46e4ca8667a71df4f0cad860e1f296a7b5 100644 (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);
        }
 }
 
index f5e43b6d78be84cd0b848a3d1c62147e2b47c67d..5103ce6d5cc4fbfe8dce4374071faa27be83141f 100644 (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 {