Commit d9001ef0 authored by Alan Donovan's avatar Alan Donovan

exp/ssa: cross off a few remaining TODO issues.

- 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
parent ed1ac056
...@@ -31,15 +31,10 @@ package ssa ...@@ -31,15 +31,10 @@ package ssa
// It uses a mutex so that access from multiple threads is serialized. // It uses a mutex so that access from multiple threads is serialized.
// TODO(adonovan): fix the following: // TODO(adonovan): fix the following:
// - append, delete details.
// - support f(g()) where g has multiple result parameters. // - 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. // - concurrent SSA code generation of multiple packages.
// - consider function-local NamedTypes. // - consider function-local NamedTypes.
// They can have nonempty method-sets due to promotion. Test. // They can have nonempty method-sets due to promotion. Test.
// - polish.
// - tests.
import ( import (
"fmt" "fmt"
...@@ -58,6 +53,8 @@ var ( ...@@ -58,6 +53,8 @@ var (
tByte = types.Typ[types.Byte] tByte = types.Typ[types.Byte]
tFloat32 = types.Typ[types.Float32] tFloat32 = types.Typ[types.Float32]
tFloat64 = types.Typ[types.Float64] tFloat64 = types.Typ[types.Float64]
tComplex64 = types.Typ[types.Complex64]
tComplex128 = types.Typ[types.Complex128]
tInt = types.Typ[types.Int] tInt = types.Typ[types.Int]
tInvalid = types.Typ[types.Invalid] tInvalid = types.Typ[types.Invalid]
tUntypedNil = types.Typ[types.UntypedNil] tUntypedNil = types.Typ[types.UntypedNil]
...@@ -1128,17 +1125,21 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) { ...@@ -1128,17 +1125,21 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
var bptypes []types.Type // formal parameter types of builtins var bptypes []types.Type // formal parameter types of builtins
switch builtin := e.Fun.(*ast.Ident).Name; builtin { switch builtin := e.Fun.(*ast.Ident).Name; builtin {
case "append": case "append":
// append([]T, ...T) []T
// append([]byte, string...) []byte // TODO(adonovan): fix: support.
// Infer arg types from result type: // Infer arg types from result type:
rt := b.exprType(e) rt := b.exprType(e)
vt = underlyingType(rt).(*types.Slice).Elt // variadic bptypes = append(bptypes, rt)
if !c.HasEllipsis { 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:] args, varargs = args[:1], args[1:]
vt = underlyingType(rt).(*types.Slice).Elt
} }
bptypes = append(bptypes, rt)
case "close": case "close":
bptypes = append(bptypes, nil) // no conv // no conv
case "copy": case "copy":
// copy([]T, []T) int // copy([]T, []T) int
// Infer arg types from each other. Sleazy. // Infer arg types from each other. Sleazy.
...@@ -1151,22 +1152,33 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) { ...@@ -1151,22 +1152,33 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
} }
case "delete": case "delete":
// delete(map[K]V, K) // delete(map[K]V, K)
// TODO(adonovan): fix: this is incorrect. tkey := underlyingType(b.exprType(args[0])).(*types.Map).Key
bptypes = append(bptypes, nil) // map bptypes = append(bptypes, nil) // map: no conv
bptypes = append(bptypes, nil) // key bptypes = append(bptypes, tkey) // key
case "print", "println": // print{,ln}(any, ...any) case "print", "println": // print{,ln}(any, ...any)
vt = tEface // variadic vt = tEface // variadic
if !c.HasEllipsis { if !c.HasEllipsis {
args, varargs = args[:1], args[1:] args, varargs = args[:1], args[1:]
} }
case "len": case "len":
bptypes = append(bptypes, nil) // no conv // no conv
case "cap": case "cap":
bptypes = append(bptypes, nil) // no conv // no conv
case "real", "imag": case "real", "imag":
// TODO(adonovan): fix: apply reverse conversion // Reverse conversion to "complex" case below.
// to "complex" case below. // Typechecker, help us out. :(
bptypes = append(bptypes, nil) 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": case "complex":
// Typechecker, help us out. :( // Typechecker, help us out. :(
var argType types.Type var argType types.Type
......
...@@ -34,7 +34,6 @@ func emitLoad(f *Function, addr Value) Value { ...@@ -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 { func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
switch op { switch op {
case token.SHL, token.SHR: case token.SHL, token.SHR:
// TODO(adonovan): fix: is this correct?
x = emitConv(f, x, t) x = emitConv(f, x, t)
y = emitConv(f, y, types.Typ[types.Uint64]) 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 { ...@@ -59,7 +58,6 @@ func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
// comparison comparison 'x op y'. // comparison comparison 'x op y'.
// //
func emitCompare(f *Function, op token.Token, x, y Value) Value { func emitCompare(f *Function, op token.Token, x, y Value) Value {
// TODO(adonovan): fix: this is incomplete.
xt := underlyingType(x.Type()) xt := underlyingType(x.Type())
yt := underlyingType(y.Type()) yt := underlyingType(y.Type())
......
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
// program are assumed to be the same as those of the interpreter // program are assumed to be the same as those of the interpreter
// itself. // 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 // * os.Exit is implemented using panic, causing deferred functions to
// run. // run.
package interp package interp
......
...@@ -292,3 +292,31 @@ func init() { ...@@ -292,3 +292,31 @@ func init() {
panic(c) 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)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment