]> Cypherpunks repositories - gostls13.git/commitdiff
exp/ssa: cross off a few remaining TODO issues.
authorAlan Donovan <adonovan@google.com>
Fri, 22 Feb 2013 05:09:21 +0000 (00:09 -0500)
committerAlan Donovan <adonovan@google.com>
Fri, 22 Feb 2013 05:09:21 +0000 (00:09 -0500)
- append: nothing to do (nonsemantic change).
- delete: now performs correct conversion (+ test).
- emitCompare: nothing to do.
- emitArith (shifts): nothing to do (+ test).
- "banish untyped types": give up on that.
- real, imag: now do correct conversions.
- added comment to interp.go re zero-size values.

R=gri
CC=golang-dev
https://golang.org/cl/7391046

src/pkg/exp/ssa/builder.go
src/pkg/exp/ssa/emit.go
src/pkg/exp/ssa/interp/interp.go
src/pkg/exp/ssa/interp/testdata/coverage.go

index d8c17be50019ce8c7deb33e0e179c67915d2e676..a00a9e3443db2fb6d65f3d2bb09868165752adbb 100644 (file)
@@ -31,15 +31,10 @@ package ssa
 //   It uses a mutex so that access from multiple threads is serialized.
 
 // TODO(adonovan): fix the following:
-// - append, delete details.
 // - support f(g()) where g has multiple result parameters.
-// - finish emitCompare, emitArith.
-// - banish "untyped" types everywhere except package/universal constants?
 // - concurrent SSA code generation of multiple packages.
 // - consider function-local NamedTypes.
 //   They can have nonempty method-sets due to promotion.  Test.
-// - polish.
-// - tests.
 
 import (
        "fmt"
@@ -58,6 +53,8 @@ var (
        tByte       = types.Typ[types.Byte]
        tFloat32    = types.Typ[types.Float32]
        tFloat64    = types.Typ[types.Float64]
+       tComplex64  = types.Typ[types.Complex64]
+       tComplex128 = types.Typ[types.Complex128]
        tInt        = types.Typ[types.Int]
        tInvalid    = types.Typ[types.Invalid]
        tUntypedNil = types.Typ[types.UntypedNil]
@@ -1128,17 +1125,21 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
                var bptypes []types.Type // formal parameter types of builtins
                switch builtin := e.Fun.(*ast.Ident).Name; builtin {
                case "append":
-                       // append([]T, ...T) []T
-                       // append([]byte, string...) []byte  // TODO(adonovan): fix: support.
                        // Infer arg types from result type:
                        rt := b.exprType(e)
-                       vt = underlyingType(rt).(*types.Slice).Elt // variadic
-                       if !c.HasEllipsis {
+                       bptypes = append(bptypes, rt)
+                       if c.HasEllipsis {
+                               // 2-arg '...' call form.  No conversions.
+                               // append([]T, []T) []T
+                               // append([]byte, string) []byte
+                       } else {
+                               // variadic call form.
+                               // append([]T, ...T) []T
                                args, varargs = args[:1], args[1:]
+                               vt = underlyingType(rt).(*types.Slice).Elt
                        }
-                       bptypes = append(bptypes, rt)
                case "close":
-                       bptypes = append(bptypes, nil) // no conv
+                       // no conv
                case "copy":
                        // copy([]T, []T) int
                        // Infer arg types from each other.  Sleazy.
@@ -1151,22 +1152,33 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
                        }
                case "delete":
                        // delete(map[K]V, K)
-                       // TODO(adonovan): fix: this is incorrect.
-                       bptypes = append(bptypes, nil) // map
-                       bptypes = append(bptypes, nil) // key
+                       tkey := underlyingType(b.exprType(args[0])).(*types.Map).Key
+                       bptypes = append(bptypes, nil)  // map: no conv
+                       bptypes = append(bptypes, tkey) // key
                case "print", "println": // print{,ln}(any, ...any)
                        vt = tEface // variadic
                        if !c.HasEllipsis {
                                args, varargs = args[:1], args[1:]
                        }
                case "len":
-                       bptypes = append(bptypes, nil) // no conv
+                       // no conv
                case "cap":
-                       bptypes = append(bptypes, nil) // no conv
+                       // no conv
                case "real", "imag":
-                       // TODO(adonovan): fix: apply reverse conversion
-                       // to "complex" case below.
-                       bptypes = append(bptypes, nil)
+                       // Reverse conversion to "complex" case below.
+                       // Typechecker, help us out. :(
+                       var argType types.Type
+                       switch b.exprType(e).(*types.Basic).Kind {
+                       case types.UntypedFloat:
+                               argType = types.Typ[types.UntypedComplex]
+                       case types.Float64:
+                               argType = tComplex128
+                       case types.Float32:
+                               argType = tComplex64
+                       default:
+                               unreachable()
+                       }
+                       bptypes = append(bptypes, argType, argType)
                case "complex":
                        // Typechecker, help us out. :(
                        var argType types.Type
index d361463d9809d83ae7e806e81b7726bed5d6a4d5..7070c18b42f37eac6ab04b2e2749cad61ac68aa2 100644 (file)
@@ -34,7 +34,6 @@ func emitLoad(f *Function, addr Value) Value {
 func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
        switch op {
        case token.SHL, token.SHR:
-               // TODO(adonovan): fix: is this correct?
                x = emitConv(f, x, t)
                y = emitConv(f, y, types.Typ[types.Uint64])
 
@@ -59,7 +58,6 @@ func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
 // comparison comparison 'x op y'.
 //
 func emitCompare(f *Function, op token.Token, x, y Value) Value {
-       // TODO(adonovan): fix: this is incomplete.
        xt := underlyingType(x.Type())
        yt := underlyingType(y.Type())
 
index 0fa4316bf020a2686269da89a2640cf4c65eb21c..c20ddb96224ef640bd59cc13050d472d88d15ff4 100644 (file)
 // program are assumed to be the same as those of the interpreter
 // itself.
 //
+// * all values occupy space, even those of types defined by the spec
+// to have zero size, e.g. struct{}.  This can cause asymptotic
+// performance degradation.
+//
 // * os.Exit is implemented using panic, causing deferred functions to
 // run.
 package interp
index 7573e0f69e37aaea7e4dbb4fcd301bf69990c49d..1ef82e9cf880f2fd0719f9d5ed0781fb6b453509 100644 (file)
@@ -292,3 +292,31 @@ func init() {
                panic(c)
        }
 }
+
+// Shifts.
+func init() {
+       var i int64 = 1
+       var u uint64 = 1 << 32
+       if x := i << uint32(u); x != 1 {
+               panic(x)
+       }
+       if x := i << uint64(u); x != 0 {
+               panic(x)
+       }
+}
+
+// Implicit conversion of delete() key operand.
+func init() {
+       type I interface{}
+       m := make(map[I]bool)
+       m[1] = true
+       m[I(2)] = true
+       if len(m) != 2 {
+               panic(m)
+       }
+       delete(m, I(1))
+       delete(m, 2)
+       if len(m) != 0 {
+               panic(m)
+       }
+}