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
// 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
......
......@@ -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())
......
......@@ -35,6 +35,10 @@
// 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
......
......@@ -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)
}
}
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