]> Cypherpunks repositories - gostls13.git/commitdiff
exp/eval, exp/ogle: remove packages eval and ogle
authorRobert Griesemer <gri@golang.org>
Wed, 13 Jul 2011 16:40:53 +0000 (09:40 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 13 Jul 2011 16:40:53 +0000 (09:40 -0700)
An externally maintained version of exp/eval can
be found at: https://bitbucket.org/binet/go-eval/ .

R=golang-dev, r, rsc
CC=golang-dev
https://golang.org/cl/4695047

34 files changed:
src/pkg/Makefile
src/pkg/exp/eval/Makefile [deleted file]
src/pkg/exp/eval/abort.go [deleted file]
src/pkg/exp/eval/bridge.go [deleted file]
src/pkg/exp/eval/compiler.go [deleted file]
src/pkg/exp/eval/eval_test.go [deleted file]
src/pkg/exp/eval/expr.go [deleted file]
src/pkg/exp/eval/expr1.go [deleted file]
src/pkg/exp/eval/expr_test.go [deleted file]
src/pkg/exp/eval/func.go [deleted file]
src/pkg/exp/eval/gen.go [deleted file]
src/pkg/exp/eval/main.go [deleted file]
src/pkg/exp/eval/scope.go [deleted file]
src/pkg/exp/eval/stmt.go [deleted file]
src/pkg/exp/eval/stmt_test.go [deleted file]
src/pkg/exp/eval/test.bash [deleted file]
src/pkg/exp/eval/type.go [deleted file]
src/pkg/exp/eval/typec.go [deleted file]
src/pkg/exp/eval/value.go [deleted file]
src/pkg/exp/eval/world.go [deleted file]
src/pkg/exp/ogle/Makefile [deleted file]
src/pkg/exp/ogle/abort.go [deleted file]
src/pkg/exp/ogle/arch.go [deleted file]
src/pkg/exp/ogle/cmd.go [deleted file]
src/pkg/exp/ogle/event.go [deleted file]
src/pkg/exp/ogle/frame.go [deleted file]
src/pkg/exp/ogle/goroutine.go [deleted file]
src/pkg/exp/ogle/main.go [deleted file]
src/pkg/exp/ogle/process.go [deleted file]
src/pkg/exp/ogle/rruntime.go [deleted file]
src/pkg/exp/ogle/rtype.go [deleted file]
src/pkg/exp/ogle/rvalue.go [deleted file]
src/pkg/exp/ogle/vars.go [deleted file]
src/run.bash

index 7338399c2c490d71f3050332b16d3c7bdadb2427..8a99d79063805d284a9575dbb55771b498559075 100644 (file)
@@ -79,7 +79,6 @@ DIRS=\
        encoding/pem\
        exec\
        exp/datafmt\
-       exp/eval\
        exp/gui\
        exp/gui/x11\
        exp/regexp/syntax\
diff --git a/src/pkg/exp/eval/Makefile b/src/pkg/exp/eval/Makefile
deleted file mode 100644 (file)
index 872316c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/eval
-GOFILES=\
-       abort.go\
-       bridge.go\
-       compiler.go\
-       expr.go\
-       expr1.go\
-       func.go\
-       scope.go\
-       stmt.go\
-       type.go\
-       typec.go\
-       value.go\
-       world.go\
-
-include ../../../Make.pkg
-
-main.$O: main.go $(pkgdir)/$(TARG).a
-       $(GC) $<
-
-eval: main.$O
-       $(LD) -o $@ $<
-
-gen.$O: gen.go
-       $(GC) $<
-
-generate: gen.$O
-       $(LD) -o $@ $<;\
-       ./generate > expr1.go;\
-       gofmt -w expr1.go
-
diff --git a/src/pkg/exp/eval/abort.go b/src/pkg/exp/eval/abort.go
deleted file mode 100644 (file)
index 22e17ce..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "fmt"
-       "os"
-       "runtime"
-)
-
-// Abort aborts the thread's current computation,
-// causing the innermost Try to return err.
-func (t *Thread) Abort(err os.Error) {
-       if t.abort == nil {
-               panic("abort: " + err.String())
-       }
-       t.abort <- err
-       runtime.Goexit()
-}
-
-// Try executes a computation; if the computation
-// Aborts, Try returns the error passed to abort.
-func (t *Thread) Try(f func(t *Thread)) os.Error {
-       oc := t.abort
-       c := make(chan os.Error)
-       t.abort = c
-       go func() {
-               f(t)
-               c <- nil
-       }()
-       err := <-c
-       t.abort = oc
-       return err
-}
-
-type DivByZeroError struct{}
-
-func (DivByZeroError) String() string { return "divide by zero" }
-
-type NilPointerError struct{}
-
-func (NilPointerError) String() string { return "nil pointer dereference" }
-
-type IndexError struct {
-       Idx, Len int64
-}
-
-func (e IndexError) String() string {
-       if e.Idx < 0 {
-               return fmt.Sprintf("negative index: %d", e.Idx)
-       }
-       return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len)
-}
-
-type SliceError struct {
-       Lo, Hi, Cap int64
-}
-
-func (e SliceError) String() string {
-       return fmt.Sprintf("slice [%d:%d]; cap %d", e.Lo, e.Hi, e.Cap)
-}
-
-type KeyError struct {
-       Key interface{}
-}
-
-func (e KeyError) String() string { return fmt.Sprintf("key '%v' not found in map", e.Key) }
-
-type NegativeLengthError struct {
-       Len int64
-}
-
-func (e NegativeLengthError) String() string {
-       return fmt.Sprintf("negative length: %d", e.Len)
-}
-
-type NegativeCapacityError struct {
-       Len int64
-}
-
-func (e NegativeCapacityError) String() string {
-       return fmt.Sprintf("negative capacity: %d", e.Len)
-}
diff --git a/src/pkg/exp/eval/bridge.go b/src/pkg/exp/eval/bridge.go
deleted file mode 100644 (file)
index f31d9ab..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "log"
-       "go/token"
-       "reflect"
-)
-
-/*
- * Type bridging
- */
-
-var (
-       evalTypes   = make(map[reflect.Type]Type)
-       nativeTypes = make(map[Type]reflect.Type)
-)
-
-// TypeFromNative converts a regular Go type into a the corresponding
-// interpreter Type.
-func TypeFromNative(t reflect.Type) Type {
-       if et, ok := evalTypes[t]; ok {
-               return et
-       }
-
-       var nt *NamedType
-       if t.Name() != "" {
-               name := t.PkgPath() + "ยท" + t.Name()
-               nt = &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
-               evalTypes[t] = nt
-       }
-
-       var et Type
-       switch t.Kind() {
-       case reflect.Bool:
-               et = BoolType
-
-       case reflect.Float32:
-               et = Float32Type
-       case reflect.Float64:
-               et = Float64Type
-
-       case reflect.Int16:
-               et = Int16Type
-       case reflect.Int32:
-               et = Int32Type
-       case reflect.Int64:
-               et = Int64Type
-       case reflect.Int8:
-               et = Int8Type
-       case reflect.Int:
-               et = IntType
-
-       case reflect.Uint16:
-               et = Uint16Type
-       case reflect.Uint32:
-               et = Uint32Type
-       case reflect.Uint64:
-               et = Uint64Type
-       case reflect.Uint8:
-               et = Uint8Type
-       case reflect.Uint:
-               et = UintType
-       case reflect.Uintptr:
-               et = UintptrType
-
-       case reflect.String:
-               et = StringType
-       case reflect.Array:
-               et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem()))
-       case reflect.Chan:
-               log.Panicf("%T not implemented", t)
-       case reflect.Func:
-               nin := t.NumIn()
-               // Variadic functions have DotDotDotType at the end
-               variadic := t.IsVariadic()
-               if variadic {
-                       nin--
-               }
-               in := make([]Type, nin)
-               for i := range in {
-                       in[i] = TypeFromNative(t.In(i))
-               }
-               out := make([]Type, t.NumOut())
-               for i := range out {
-                       out[i] = TypeFromNative(t.Out(i))
-               }
-               et = NewFuncType(in, variadic, out)
-       case reflect.Interface:
-               log.Panicf("%T not implemented", t)
-       case reflect.Map:
-               log.Panicf("%T not implemented", t)
-       case reflect.Ptr:
-               et = NewPtrType(TypeFromNative(t.Elem()))
-       case reflect.Slice:
-               et = NewSliceType(TypeFromNative(t.Elem()))
-       case reflect.Struct:
-               n := t.NumField()
-               fields := make([]StructField, n)
-               for i := 0; i < n; i++ {
-                       sf := t.Field(i)
-                       // TODO(austin) What to do about private fields?
-                       fields[i].Name = sf.Name
-                       fields[i].Type = TypeFromNative(sf.Type)
-                       fields[i].Anonymous = sf.Anonymous
-               }
-               et = NewStructType(fields)
-       case reflect.UnsafePointer:
-               log.Panicf("%T not implemented", t)
-       default:
-               log.Panicf("unexpected reflect.Type: %T", t)
-       }
-
-       if nt != nil {
-               if _, ok := et.(*NamedType); !ok {
-                       nt.Complete(et)
-                       et = nt
-               }
-       }
-
-       nativeTypes[et] = t
-       evalTypes[t] = et
-
-       return et
-}
-
-// TypeOfNative returns the interpreter Type of a regular Go value.
-func TypeOfNative(v interface{}) Type { return TypeFromNative(reflect.TypeOf(v)) }
-
-/*
- * Function bridging
- */
-
-type nativeFunc struct {
-       fn      func(*Thread, []Value, []Value)
-       in, out int
-}
-
-func (f *nativeFunc) NewFrame() *Frame {
-       vars := make([]Value, f.in+f.out)
-       return &Frame{nil, vars}
-}
-
-func (f *nativeFunc) Call(t *Thread) { f.fn(t, t.f.Vars[0:f.in], t.f.Vars[f.in:f.in+f.out]) }
-
-// FuncFromNative creates an interpreter function from a native
-// function that takes its in and out arguments as slices of
-// interpreter Value's.  While somewhat inconvenient, this avoids
-// value marshalling.
-func FuncFromNative(fn func(*Thread, []Value, []Value), t *FuncType) FuncValue {
-       return &funcV{&nativeFunc{fn, len(t.In), len(t.Out)}}
-}
-
-// FuncFromNativeTyped is like FuncFromNative, but constructs the
-// function type from a function pointer using reflection.  Typically,
-// the type will be given as a nil pointer to a function with the
-// desired signature.
-func FuncFromNativeTyped(fn func(*Thread, []Value, []Value), t interface{}) (*FuncType, FuncValue) {
-       ft := TypeOfNative(t).(*FuncType)
-       return ft, FuncFromNative(fn, ft)
-}
diff --git a/src/pkg/exp/eval/compiler.go b/src/pkg/exp/eval/compiler.go
deleted file mode 100644 (file)
index 9d2923b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "fmt"
-       "go/scanner"
-       "go/token"
-)
-
-
-// A compiler captures information used throughout an entire
-// compilation.  Currently it includes only the error handler.
-//
-// TODO(austin) This might actually represent package level, in which
-// case it should be package compiler.
-type compiler struct {
-       fset         *token.FileSet
-       errors       scanner.ErrorHandler
-       numErrors    int
-       silentErrors int
-}
-
-func (a *compiler) diagAt(pos token.Pos, format string, args ...interface{}) {
-       a.errors.Error(a.fset.Position(pos), fmt.Sprintf(format, args...))
-       a.numErrors++
-}
-
-func (a *compiler) numError() int { return a.numErrors + a.silentErrors }
-
-// The universal scope
-func newUniverse() *Scope {
-       sc := &Scope{nil, 0}
-       sc.block = &block{
-               offset: 0,
-               scope:  sc,
-               global: true,
-               defs:   make(map[string]Def),
-       }
-       return sc
-}
-
-var universe *Scope = newUniverse()
-
-
-// TODO(austin) These can all go in stmt.go now
-type label struct {
-       name string
-       desc string
-       // The PC goto statements should jump to, or nil if this label
-       // cannot be goto'd (such as an anonymous for loop label).
-       gotoPC *uint
-       // The PC break statements should jump to, or nil if a break
-       // statement is invalid.
-       breakPC *uint
-       // The PC continue statements should jump to, or nil if a
-       // continue statement is invalid.
-       continuePC *uint
-       // The position where this label was resolved.  If it has not
-       // been resolved yet, an invalid position.
-       resolved token.Pos
-       // The position where this label was first jumped to.
-       used token.Pos
-}
-
-// A funcCompiler captures information used throughout the compilation
-// of a single function body.
-type funcCompiler struct {
-       *compiler
-       fnType *FuncType
-       // Whether the out variables are named.  This affects what
-       // kinds of return statements are legal.
-       outVarsNamed bool
-       *codeBuf
-       flow   *flowBuf
-       labels map[string]*label
-}
-
-// A blockCompiler captures information used throughout the compilation
-// of a single block within a function.
-type blockCompiler struct {
-       *funcCompiler
-       block *block
-       // The label of this block, used for finding break and
-       // continue labels.
-       label *label
-       // The blockCompiler for the block enclosing this one, or nil
-       // for a function-level block.
-       parent *blockCompiler
-}
diff --git a/src/pkg/exp/eval/eval_test.go b/src/pkg/exp/eval/eval_test.go
deleted file mode 100644 (file)
index 541d3fe..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "flag"
-       "fmt"
-       "go/token"
-       "log"
-       "os"
-       "reflect"
-       "regexp"
-       "testing"
-)
-
-// All tests are done using the same file set.
-var fset = token.NewFileSet()
-
-// Print each statement or expression before parsing it
-var noisy = false
-
-func init() { flag.BoolVar(&noisy, "noisy", false, "chatter during eval tests") }
-
-/*
- * Generic statement/expression test framework
- */
-
-type test []job
-
-type job struct {
-       code  string
-       cerr  string
-       rterr string
-       val   Value
-       noval bool
-}
-
-func runTests(t *testing.T, baseName string, tests []test) {
-       delta := 1
-       if testing.Short() {
-               delta = 16
-       }
-       for i := 0; i < len(tests); i += delta {
-               name := fmt.Sprintf("%s[%d]", baseName, i)
-               tests[i].run(t, name)
-       }
-}
-
-func (a test) run(t *testing.T, name string) {
-       w := newTestWorld()
-       for _, j := range a {
-               src := j.code + ";" // trailing semicolon to finish statement
-               if noisy {
-                       println("code:", src)
-               }
-
-               code, err := w.Compile(fset, src)
-               if err != nil {
-                       if j.cerr == "" {
-                               t.Errorf("%s: Compile %s: %v", name, src, err)
-                               break
-                       }
-                       if !match(t, err, j.cerr) {
-                               t.Errorf("%s: Compile %s = error %s; want %v", name, src, err, j.cerr)
-                               break
-                       }
-                       continue
-               }
-               if j.cerr != "" {
-                       t.Errorf("%s: Compile %s succeeded; want %s", name, src, j.cerr)
-                       break
-               }
-
-               val, err := code.Run()
-               if err != nil {
-                       if j.rterr == "" {
-                               t.Errorf("%s: Run %s: %v", name, src, err)
-                               break
-                       }
-                       if !match(t, err, j.rterr) {
-                               t.Errorf("%s: Run %s = error %s; want %v", name, src, err, j.rterr)
-                               break
-                       }
-                       continue
-               }
-               if j.rterr != "" {
-                       t.Errorf("%s: Run %s succeeded; want %s", name, src, j.rterr)
-                       break
-               }
-
-               if !j.noval && !reflect.DeepEqual(val, j.val) {
-                       t.Errorf("%s: Run %s = %T(%v) want %T(%v)", name, src, val, val, j.val, j.val)
-               }
-       }
-}
-
-func match(t *testing.T, err os.Error, pat string) bool {
-       ok, err1 := regexp.MatchString(pat, err.String())
-       if err1 != nil {
-               t.Fatalf("compile regexp %s: %v", pat, err1)
-       }
-       return ok
-}
-
-
-/*
- * Test constructors
- */
-
-// Expression compile error
-func CErr(expr string, cerr string) test { return test([]job{{code: expr, cerr: cerr}}) }
-
-// Expression runtime error
-func RErr(expr string, rterr string) test { return test([]job{{code: expr, rterr: rterr}}) }
-
-// Expression value
-func Val(expr string, val interface{}) test {
-       return test([]job{{code: expr, val: toValue(val)}})
-}
-
-// Statement runs without error
-func Run(stmts string) test { return test([]job{{code: stmts, noval: true}}) }
-
-// Two statements without error.
-// TODO(rsc): Should be possible with Run but the parser
-// won't let us do both top-level and non-top-level statements.
-func Run2(stmt1, stmt2 string) test {
-       return test([]job{{code: stmt1, noval: true}, {code: stmt2, noval: true}})
-}
-
-// Statement runs and test one expression's value
-func Val1(stmts string, expr1 string, val1 interface{}) test {
-       return test([]job{
-               {code: stmts, noval: true},
-               {code: expr1, val: toValue(val1)},
-       })
-}
-
-// Statement runs and test two expressions' values
-func Val2(stmts string, expr1 string, val1 interface{}, expr2 string, val2 interface{}) test {
-       return test([]job{
-               {code: stmts, noval: true},
-               {code: expr1, val: toValue(val1)},
-               {code: expr2, val: toValue(val2)},
-       })
-}
-
-/*
- * Value constructors
- */
-
-type vstruct []interface{}
-
-type varray []interface{}
-
-type vslice struct {
-       arr      varray
-       len, cap int
-}
-
-func toValue(val interface{}) Value {
-       switch val := val.(type) {
-       case bool:
-               r := boolV(val)
-               return &r
-       case uint8:
-               r := uint8V(val)
-               return &r
-       case uint:
-               r := uintV(val)
-               return &r
-       case int:
-               r := intV(val)
-               return &r
-       case *big.Int:
-               return &idealIntV{val}
-       case float64:
-               r := float64V(val)
-               return &r
-       case *big.Rat:
-               return &idealFloatV{val}
-       case string:
-               r := stringV(val)
-               return &r
-       case vstruct:
-               elems := make([]Value, len(val))
-               for i, e := range val {
-                       elems[i] = toValue(e)
-               }
-               r := structV(elems)
-               return &r
-       case varray:
-               elems := make([]Value, len(val))
-               for i, e := range val {
-                       elems[i] = toValue(e)
-               }
-               r := arrayV(elems)
-               return &r
-       case vslice:
-               return &sliceV{Slice{toValue(val.arr).(ArrayValue), int64(val.len), int64(val.cap)}}
-       case Func:
-               return &funcV{val}
-       }
-       log.Panicf("toValue(%T) not implemented", val)
-       panic("unreachable")
-}
-
-/*
- * Default test scope
- */
-
-type testFunc struct{}
-
-func (*testFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} }
-
-func (*testFunc) Call(t *Thread) {
-       n := t.f.Vars[0].(IntValue).Get(t)
-
-       res := n + 1
-
-       t.f.Vars[1].(IntValue).Set(t, res)
-}
-
-type oneTwoFunc struct{}
-
-func (*oneTwoFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} }
-
-func (*oneTwoFunc) Call(t *Thread) {
-       t.f.Vars[0].(IntValue).Set(t, 1)
-       t.f.Vars[1].(IntValue).Set(t, 2)
-}
-
-type voidFunc struct{}
-
-func (*voidFunc) NewFrame() *Frame { return &Frame{nil, []Value{}} }
-
-func (*voidFunc) Call(t *Thread) {}
-
-func newTestWorld() *World {
-       w := NewWorld()
-
-       def := func(name string, t Type, val interface{}) { w.DefineVar(name, t, toValue(val)) }
-
-       w.DefineConst("c", IdealIntType, toValue(big.NewInt(1)))
-       def("i", IntType, 1)
-       def("i2", IntType, 2)
-       def("u", UintType, uint(1))
-       def("f", Float64Type, 1.0)
-       def("s", StringType, "abc")
-       def("t", NewStructType([]StructField{{"a", IntType, false}}), vstruct{1})
-       def("ai", NewArrayType(2, IntType), varray{1, 2})
-       def("aai", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{1, 2}, varray{3, 4}})
-       def("aai2", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{5, 6}, varray{7, 8}})
-       def("fn", NewFuncType([]Type{IntType}, false, []Type{IntType}), &testFunc{})
-       def("oneTwo", NewFuncType([]Type{}, false, []Type{IntType, IntType}), &oneTwoFunc{})
-       def("void", NewFuncType([]Type{}, false, []Type{}), &voidFunc{})
-       def("sli", NewSliceType(IntType), vslice{varray{1, 2, 3}, 2, 3})
-
-       return w
-}
diff --git a/src/pkg/exp/eval/expr.go b/src/pkg/exp/eval/expr.go
deleted file mode 100644 (file)
index 14a0659..0000000
+++ /dev/null
@@ -1,2015 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "fmt"
-       "go/ast"
-       "go/token"
-       "log"
-       "strconv"
-       "strings"
-       "os"
-)
-
-var (
-       idealZero = big.NewInt(0)
-       idealOne  = big.NewInt(1)
-)
-
-// An expr is the result of compiling an expression.  It stores the
-// type of the expression and its evaluator function.
-type expr struct {
-       *exprInfo
-       t Type
-
-       // Evaluate this node as the given type.
-       eval interface{}
-
-       // Map index expressions permit special forms of assignment,
-       // for which we need to know the Map and key.
-       evalMapValue func(t *Thread) (Map, interface{})
-
-       // Evaluate to the "address of" this value; that is, the
-       // settable Value object.  nil for expressions whose address
-       // cannot be taken.
-       evalAddr func(t *Thread) Value
-
-       // Execute this expression as a statement.  Only expressions
-       // that are valid expression statements should set this.
-       exec func(t *Thread)
-
-       // If this expression is a type, this is its compiled type.
-       // This is only permitted in the function position of a call
-       // expression.  In this case, t should be nil.
-       valType Type
-
-       // A short string describing this expression for error
-       // messages.
-       desc string
-}
-
-// exprInfo stores information needed to compile any expression node.
-// Each expr also stores its exprInfo so further expressions can be
-// compiled from it.
-type exprInfo struct {
-       *compiler
-       pos token.Pos
-}
-
-func (a *exprInfo) newExpr(t Type, desc string) *expr {
-       return &expr{exprInfo: a, t: t, desc: desc}
-}
-
-func (a *exprInfo) diag(format string, args ...interface{}) {
-       a.diagAt(a.pos, format, args...)
-}
-
-func (a *exprInfo) diagOpType(op token.Token, vt Type) {
-       a.diag("illegal operand type for '%v' operator\n\t%v", op, vt)
-}
-
-func (a *exprInfo) diagOpTypes(op token.Token, lt Type, rt Type) {
-       a.diag("illegal operand types for '%v' operator\n\t%v\n\t%v", op, lt, rt)
-}
-
-/*
- * Common expression manipulations
- */
-
-// a.convertTo(t) converts the value of the analyzed expression a,
-// which must be a constant, ideal number, to a new analyzed
-// expression with a constant value of type t.
-//
-// TODO(austin) Rename to resolveIdeal or something?
-func (a *expr) convertTo(t Type) *expr {
-       if !a.t.isIdeal() {
-               log.Panicf("attempted to convert from %v, expected ideal", a.t)
-       }
-
-       var rat *big.Rat
-
-       // XXX(Spec)  The spec says "It is erroneous".
-       //
-       // It is an error to assign a value with a non-zero fractional
-       // part to an integer, or if the assignment would overflow or
-       // underflow, or in general if the value cannot be represented
-       // by the type of the variable.
-       switch a.t {
-       case IdealFloatType:
-               rat = a.asIdealFloat()()
-               if t.isInteger() && !rat.IsInt() {
-                       a.diag("constant %v truncated to integer", rat.FloatString(6))
-                       return nil
-               }
-       case IdealIntType:
-               i := a.asIdealInt()()
-               rat = new(big.Rat).SetInt(i)
-       default:
-               log.Panicf("unexpected ideal type %v", a.t)
-       }
-
-       // Check bounds
-       if t, ok := t.lit().(BoundedType); ok {
-               if rat.Cmp(t.minVal()) < 0 {
-                       a.diag("constant %v underflows %v", rat.FloatString(6), t)
-                       return nil
-               }
-               if rat.Cmp(t.maxVal()) > 0 {
-                       a.diag("constant %v overflows %v", rat.FloatString(6), t)
-                       return nil
-               }
-       }
-
-       // Convert rat to type t.
-       res := a.newExpr(t, a.desc)
-       switch t := t.lit().(type) {
-       case *uintType:
-               n, d := rat.Num(), rat.Denom()
-               f := new(big.Int).Quo(n, d)
-               f = f.Abs(f)
-               v := uint64(f.Int64())
-               res.eval = func(*Thread) uint64 { return v }
-       case *intType:
-               n, d := rat.Num(), rat.Denom()
-               f := new(big.Int).Quo(n, d)
-               v := f.Int64()
-               res.eval = func(*Thread) int64 { return v }
-       case *idealIntType:
-               n, d := rat.Num(), rat.Denom()
-               f := new(big.Int).Quo(n, d)
-               res.eval = func() *big.Int { return f }
-       case *floatType:
-               n, d := rat.Num(), rat.Denom()
-               v := float64(n.Int64()) / float64(d.Int64())
-               res.eval = func(*Thread) float64 { return v }
-       case *idealFloatType:
-               res.eval = func() *big.Rat { return rat }
-       default:
-               log.Panicf("cannot convert to type %T", t)
-       }
-
-       return res
-}
-
-// convertToInt converts this expression to an integer, if possible,
-// or produces an error if not.  This accepts ideal ints, uints, and
-// ints.  If max is not -1, produces an error if possible if the value
-// exceeds max.  If negErr is not "", produces an error if possible if
-// the value is negative.
-func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
-       switch a.t.lit().(type) {
-       case *idealIntType:
-               val := a.asIdealInt()()
-               if negErr != "" && val.Sign() < 0 {
-                       a.diag("negative %s: %s", negErr, val)
-                       return nil
-               }
-               bound := max
-               if negErr == "slice" {
-                       bound++
-               }
-               if max != -1 && val.Cmp(big.NewInt(bound)) >= 0 {
-                       a.diag("index %s exceeds length %d", val, max)
-                       return nil
-               }
-               return a.convertTo(IntType)
-
-       case *uintType:
-               // Convert to int
-               na := a.newExpr(IntType, a.desc)
-               af := a.asUint()
-               na.eval = func(t *Thread) int64 { return int64(af(t)) }
-               return na
-
-       case *intType:
-               // Good as is
-               return a
-       }
-
-       a.diag("illegal operand type for %s\n\t%v", errOp, a.t)
-       return nil
-}
-
-// derefArray returns an expression of array type if the given
-// expression is a *array type.  Otherwise, returns the given
-// expression.
-func (a *expr) derefArray() *expr {
-       if pt, ok := a.t.lit().(*PtrType); ok {
-               if _, ok := pt.Elem.lit().(*ArrayType); ok {
-                       deref := a.compileStarExpr(a)
-                       if deref == nil {
-                               log.Panicf("failed to dereference *array")
-                       }
-                       return deref
-               }
-       }
-       return a
-}
-
-/*
- * Assignments
- */
-
-// An assignCompiler compiles assignment operations.  Anything other
-// than short declarations should use the compileAssign wrapper.
-//
-// There are three valid types of assignment:
-// 1) T = T
-//    Assigning a single expression with single-valued type to a
-//    single-valued type.
-// 2) MT = T, T, ...
-//    Assigning multiple expressions with single-valued types to a
-//    multi-valued type.
-// 3) MT = MT
-//    Assigning a single expression with multi-valued type to a
-//    multi-valued type.
-type assignCompiler struct {
-       *compiler
-       pos token.Pos
-       // The RHS expressions.  This may include nil's for
-       // expressions that failed to compile.
-       rs []*expr
-       // The (possibly unary) MultiType of the RHS.
-       rmt *MultiType
-       // Whether this is an unpack assignment (case 3).
-       isUnpack bool
-       // Whether map special assignment forms are allowed.
-       allowMap bool
-       // Whether this is a "r, ok = a[x]" assignment.
-       isMapUnpack bool
-       // The operation name to use in error messages, such as
-       // "assignment" or "function call".
-       errOp string
-       // The name to use for positions in error messages, such as
-       // "argument".
-       errPosName string
-}
-
-// Type check the RHS of an assignment, returning a new assignCompiler
-// and indicating if the type check succeeded.  This always returns an
-// assignCompiler with rmt set, but if type checking fails, slots in
-// the MultiType may be nil.  If rs contains nil's, type checking will
-// fail and these expressions given a nil type.
-func (a *compiler) checkAssign(pos token.Pos, rs []*expr, errOp, errPosName string) (*assignCompiler, bool) {
-       c := &assignCompiler{
-               compiler:   a,
-               pos:        pos,
-               rs:         rs,
-               errOp:      errOp,
-               errPosName: errPosName,
-       }
-
-       // Is this an unpack?
-       if len(rs) == 1 && rs[0] != nil {
-               if rmt, isUnpack := rs[0].t.(*MultiType); isUnpack {
-                       c.rmt = rmt
-                       c.isUnpack = true
-                       return c, true
-               }
-       }
-
-       // Create MultiType for RHS and check that all RHS expressions
-       // are single-valued.
-       rts := make([]Type, len(rs))
-       ok := true
-       for i, r := range rs {
-               if r == nil {
-                       ok = false
-                       continue
-               }
-
-               if _, isMT := r.t.(*MultiType); isMT {
-                       r.diag("multi-valued expression not allowed in %s", errOp)
-                       ok = false
-                       continue
-               }
-
-               rts[i] = r.t
-       }
-
-       c.rmt = NewMultiType(rts)
-       return c, ok
-}
-
-func (a *assignCompiler) allowMapForms(nls int) {
-       a.allowMap = true
-
-       // Update unpacking info if this is r, ok = a[x]
-       if nls == 2 && len(a.rs) == 1 && a.rs[0] != nil && a.rs[0].evalMapValue != nil {
-               a.isUnpack = true
-               a.rmt = NewMultiType([]Type{a.rs[0].t, BoolType})
-               a.isMapUnpack = true
-       }
-}
-
-// compile type checks and compiles an assignment operation, returning
-// a function that expects an l-value and the frame in which to
-// evaluate the RHS expressions.  The l-value must have exactly the
-// type given by lt.  Returns nil if type checking fails.
-func (a *assignCompiler) compile(b *block, lt Type) func(Value, *Thread) {
-       lmt, isMT := lt.(*MultiType)
-       rmt, isUnpack := a.rmt, a.isUnpack
-
-       // Create unary MultiType for single LHS
-       if !isMT {
-               lmt = NewMultiType([]Type{lt})
-       }
-
-       // Check that the assignment count matches
-       lcount := len(lmt.Elems)
-       rcount := len(rmt.Elems)
-       if lcount != rcount {
-               msg := "not enough"
-               pos := a.pos
-               if rcount > lcount {
-                       msg = "too many"
-                       if lcount > 0 {
-                               pos = a.rs[lcount-1].pos
-                       }
-               }
-               a.diagAt(pos, "%s %ss for %s\n\t%s\n\t%s", msg, a.errPosName, a.errOp, lt, rmt)
-               return nil
-       }
-
-       bad := false
-
-       // If this is an unpack, create a temporary to store the
-       // multi-value and replace the RHS with expressions to pull
-       // out values from the temporary.  Technically, this is only
-       // necessary when we need to perform assignment conversions.
-       var effect func(*Thread)
-       if isUnpack {
-               // This leaks a slot, but is definitely safe.
-               temp := b.DefineTemp(a.rmt)
-               tempIdx := temp.Index
-               if tempIdx < 0 {
-                       panic(fmt.Sprintln("tempidx", tempIdx))
-               }
-               if a.isMapUnpack {
-                       rf := a.rs[0].evalMapValue
-                       vt := a.rmt.Elems[0]
-                       effect = func(t *Thread) {
-                               m, k := rf(t)
-                               v := m.Elem(t, k)
-                               found := boolV(true)
-                               if v == nil {
-                                       found = boolV(false)
-                                       v = vt.Zero()
-                               }
-                               t.f.Vars[tempIdx] = multiV([]Value{v, &found})
-                       }
-               } else {
-                       rf := a.rs[0].asMulti()
-                       effect = func(t *Thread) { t.f.Vars[tempIdx] = multiV(rf(t)) }
-               }
-               orig := a.rs[0]
-               a.rs = make([]*expr, len(a.rmt.Elems))
-               for i, t := range a.rmt.Elems {
-                       if t.isIdeal() {
-                               log.Panicf("Right side of unpack contains ideal: %s", rmt)
-                       }
-                       a.rs[i] = orig.newExpr(t, orig.desc)
-                       index := i
-                       a.rs[i].genValue(func(t *Thread) Value { return t.f.Vars[tempIdx].(multiV)[index] })
-               }
-       }
-       // Now len(a.rs) == len(a.rmt) and we've reduced any unpacking
-       // to multi-assignment.
-
-       // TODO(austin) Deal with assignment special cases.
-
-       // Values of any type may always be assigned to variables of
-       // compatible static type.
-       for i, lt := range lmt.Elems {
-               rt := rmt.Elems[i]
-
-               // When [an ideal is] (used in an expression) assigned
-               // to a variable or typed constant, the destination
-               // must be able to represent the assigned value.
-               if rt.isIdeal() {
-                       a.rs[i] = a.rs[i].convertTo(lmt.Elems[i])
-                       if a.rs[i] == nil {
-                               bad = true
-                               continue
-                       }
-                       rt = a.rs[i].t
-               }
-
-               // A pointer p to an array can be assigned to a slice
-               // variable v with compatible element type if the type
-               // of p or v is unnamed.
-               if rpt, ok := rt.lit().(*PtrType); ok {
-                       if at, ok := rpt.Elem.lit().(*ArrayType); ok {
-                               if lst, ok := lt.lit().(*SliceType); ok {
-                                       if lst.Elem.compat(at.Elem, false) && (rt.lit() == Type(rt) || lt.lit() == Type(lt)) {
-                                               rf := a.rs[i].asPtr()
-                                               a.rs[i] = a.rs[i].newExpr(lt, a.rs[i].desc)
-                                               len := at.Len
-                                               a.rs[i].eval = func(t *Thread) Slice { return Slice{rf(t).(ArrayValue), len, len} }
-                                               rt = a.rs[i].t
-                                       }
-                               }
-                       }
-               }
-
-               if !lt.compat(rt, false) {
-                       if len(a.rs) == 1 {
-                               a.rs[0].diag("illegal operand types for %s\n\t%v\n\t%v", a.errOp, lt, rt)
-                       } else {
-                               a.rs[i].diag("illegal operand types in %s %d of %s\n\t%v\n\t%v", a.errPosName, i+1, a.errOp, lt, rt)
-                       }
-                       bad = true
-               }
-       }
-       if bad {
-               return nil
-       }
-
-       // Compile
-       if !isMT {
-               // Case 1
-               return genAssign(lt, a.rs[0])
-       }
-       // Case 2 or 3
-       as := make([]func(lv Value, t *Thread), len(a.rs))
-       for i, r := range a.rs {
-               as[i] = genAssign(lmt.Elems[i], r)
-       }
-       return func(lv Value, t *Thread) {
-               if effect != nil {
-                       effect(t)
-               }
-               lmv := lv.(multiV)
-               for i, a := range as {
-                       a(lmv[i], t)
-               }
-       }
-}
-
-// compileAssign compiles an assignment operation without the full
-// generality of an assignCompiler.  See assignCompiler for a
-// description of the arguments.
-func (a *compiler) compileAssign(pos token.Pos, b *block, lt Type, rs []*expr, errOp, errPosName string) func(Value, *Thread) {
-       ac, ok := a.checkAssign(pos, rs, errOp, errPosName)
-       if !ok {
-               return nil
-       }
-       return ac.compile(b, lt)
-}
-
-/*
- * Expression compiler
- */
-
-// An exprCompiler stores information used throughout the compilation
-// of a single expression.  It does not embed funcCompiler because
-// expressions can appear at top level.
-type exprCompiler struct {
-       *compiler
-       // The block this expression is being compiled in.
-       block *block
-       // Whether this expression is used in a constant context.
-       constant bool
-}
-
-// compile compiles an expression AST.  callCtx should be true if this
-// AST is in the function position of a function call node; it allows
-// the returned expression to be a type or a built-in function (which
-// otherwise result in errors).
-func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
-       ei := &exprInfo{a.compiler, x.Pos()}
-
-       switch x := x.(type) {
-       // Literals
-       case *ast.BasicLit:
-               switch x.Kind {
-               case token.INT:
-                       return ei.compileIntLit(string(x.Value))
-               case token.FLOAT:
-                       return ei.compileFloatLit(string(x.Value))
-               case token.CHAR:
-                       return ei.compileCharLit(string(x.Value))
-               case token.STRING:
-                       return ei.compileStringLit(string(x.Value))
-               default:
-                       log.Panicf("unexpected basic literal type %v", x.Kind)
-               }
-
-       case *ast.CompositeLit:
-               goto notimpl
-
-       case *ast.FuncLit:
-               decl := ei.compileFuncType(a.block, x.Type)
-               if decl == nil {
-                       // TODO(austin) Try compiling the body,
-                       // perhaps with dummy argument definitions
-                       return nil
-               }
-               fn := ei.compileFunc(a.block, decl, x.Body)
-               if fn == nil {
-                       return nil
-               }
-               if a.constant {
-                       a.diagAt(x.Pos(), "function literal used in constant expression")
-                       return nil
-               }
-               return ei.compileFuncLit(decl, fn)
-
-       // Types
-       case *ast.ArrayType:
-               // TODO(austin) Use a multi-type case
-               goto typeexpr
-
-       case *ast.ChanType:
-               goto typeexpr
-
-       case *ast.Ellipsis:
-               goto typeexpr
-
-       case *ast.FuncType:
-               goto typeexpr
-
-       case *ast.InterfaceType:
-               goto typeexpr
-
-       case *ast.MapType:
-               goto typeexpr
-
-       // Remaining expressions
-       case *ast.BadExpr:
-               // Error already reported by parser
-               a.silentErrors++
-               return nil
-
-       case *ast.BinaryExpr:
-               l, r := a.compile(x.X, false), a.compile(x.Y, false)
-               if l == nil || r == nil {
-                       return nil
-               }
-               return ei.compileBinaryExpr(x.Op, l, r)
-
-       case *ast.CallExpr:
-               l := a.compile(x.Fun, true)
-               args := make([]*expr, len(x.Args))
-               bad := false
-               for i, arg := range x.Args {
-                       if i == 0 && l != nil && (l.t == Type(makeType) || l.t == Type(newType)) {
-                               argei := &exprInfo{a.compiler, arg.Pos()}
-                               args[i] = argei.exprFromType(a.compileType(a.block, arg))
-                       } else {
-                               args[i] = a.compile(arg, false)
-                       }
-                       if args[i] == nil {
-                               bad = true
-                       }
-               }
-               if bad || l == nil {
-                       return nil
-               }
-               if a.constant {
-                       a.diagAt(x.Pos(), "function call in constant context")
-                       return nil
-               }
-
-               if l.valType != nil {
-                       a.diagAt(x.Pos(), "type conversions not implemented")
-                       return nil
-               } else if ft, ok := l.t.(*FuncType); ok && ft.builtin != "" {
-                       return ei.compileBuiltinCallExpr(a.block, ft, args)
-               } else {
-                       return ei.compileCallExpr(a.block, l, args)
-               }
-
-       case *ast.Ident:
-               return ei.compileIdent(a.block, a.constant, callCtx, x.Name)
-
-       case *ast.IndexExpr:
-               l, r := a.compile(x.X, false), a.compile(x.Index, false)
-               if l == nil || r == nil {
-                       return nil
-               }
-               return ei.compileIndexExpr(l, r)
-
-       case *ast.SliceExpr:
-               var lo, hi *expr
-               arr := a.compile(x.X, false)
-               if x.Low == nil {
-                       // beginning was omitted, so we need to provide it
-                       ei := &exprInfo{a.compiler, x.Pos()}
-                       lo = ei.compileIntLit("0")
-               } else {
-                       lo = a.compile(x.Low, false)
-               }
-               if x.High == nil {
-                       // End was omitted, so we need to compute len(x.X)
-                       ei := &exprInfo{a.compiler, x.Pos()}
-                       hi = ei.compileBuiltinCallExpr(a.block, lenType, []*expr{arr})
-               } else {
-                       hi = a.compile(x.High, false)
-               }
-               if arr == nil || lo == nil || hi == nil {
-                       return nil
-               }
-               return ei.compileSliceExpr(arr, lo, hi)
-
-       case *ast.KeyValueExpr:
-               goto notimpl
-
-       case *ast.ParenExpr:
-               return a.compile(x.X, callCtx)
-
-       case *ast.SelectorExpr:
-               v := a.compile(x.X, false)
-               if v == nil {
-                       return nil
-               }
-               return ei.compileSelectorExpr(v, x.Sel.Name)
-
-       case *ast.StarExpr:
-               // We pass down our call context because this could be
-               // a pointer type (and thus a type conversion)
-               v := a.compile(x.X, callCtx)
-               if v == nil {
-                       return nil
-               }
-               if v.valType != nil {
-                       // Turns out this was a pointer type, not a dereference
-                       return ei.exprFromType(NewPtrType(v.valType))
-               }
-               return ei.compileStarExpr(v)
-
-       case *ast.StructType:
-               goto notimpl
-
-       case *ast.TypeAssertExpr:
-               goto notimpl
-
-       case *ast.UnaryExpr:
-               v := a.compile(x.X, false)
-               if v == nil {
-                       return nil
-               }
-               return ei.compileUnaryExpr(x.Op, v)
-       }
-       log.Panicf("unexpected ast node type %T", x)
-       panic("unreachable")
-
-typeexpr:
-       if !callCtx {
-               a.diagAt(x.Pos(), "type used as expression")
-               return nil
-       }
-       return ei.exprFromType(a.compileType(a.block, x))
-
-notimpl:
-       a.diagAt(x.Pos(), "%T expression node not implemented", x)
-       return nil
-}
-
-func (a *exprInfo) exprFromType(t Type) *expr {
-       if t == nil {
-               return nil
-       }
-       expr := a.newExpr(nil, "type")
-       expr.valType = t
-       return expr
-}
-
-func (a *exprInfo) compileIdent(b *block, constant bool, callCtx bool, name string) *expr {
-       bl, level, def := b.Lookup(name)
-       if def == nil {
-               a.diag("%s: undefined", name)
-               return nil
-       }
-       switch def := def.(type) {
-       case *Constant:
-               expr := a.newExpr(def.Type, "constant")
-               if ft, ok := def.Type.(*FuncType); ok && ft.builtin != "" {
-                       // XXX(Spec) I don't think anything says that
-                       // built-in functions can't be used as values.
-                       if !callCtx {
-                               a.diag("built-in function %s cannot be used as a value", ft.builtin)
-                               return nil
-                       }
-                       // Otherwise, we leave the evaluators empty
-                       // because this is handled specially
-               } else {
-                       expr.genConstant(def.Value)
-               }
-               return expr
-       case *Variable:
-               if constant {
-                       a.diag("variable %s used in constant expression", name)
-                       return nil
-               }
-               if bl.global {
-                       return a.compileGlobalVariable(def)
-               }
-               return a.compileVariable(level, def)
-       case Type:
-               if callCtx {
-                       return a.exprFromType(def)
-               }
-               a.diag("type %v used as expression", name)
-               return nil
-       }
-       log.Panicf("name %s has unknown type %T", name, def)
-       panic("unreachable")
-}
-
-func (a *exprInfo) compileVariable(level int, v *Variable) *expr {
-       if v.Type == nil {
-               // Placeholder definition from an earlier error
-               a.silentErrors++
-               return nil
-       }
-       expr := a.newExpr(v.Type, "variable")
-       expr.genIdentOp(level, v.Index)
-       return expr
-}
-
-func (a *exprInfo) compileGlobalVariable(v *Variable) *expr {
-       if v.Type == nil {
-               // Placeholder definition from an earlier error
-               a.silentErrors++
-               return nil
-       }
-       if v.Init == nil {
-               v.Init = v.Type.Zero()
-       }
-       expr := a.newExpr(v.Type, "variable")
-       val := v.Init
-       expr.genValue(func(t *Thread) Value { return val })
-       return expr
-}
-
-func (a *exprInfo) compileIdealInt(i *big.Int, desc string) *expr {
-       expr := a.newExpr(IdealIntType, desc)
-       expr.eval = func() *big.Int { return i }
-       return expr
-}
-
-func (a *exprInfo) compileIntLit(lit string) *expr {
-       i, _ := new(big.Int).SetString(lit, 0)
-       return a.compileIdealInt(i, "integer literal")
-}
-
-func (a *exprInfo) compileCharLit(lit string) *expr {
-       if lit[0] != '\'' {
-               // Caught by parser
-               a.silentErrors++
-               return nil
-       }
-       v, _, tail, err := strconv.UnquoteChar(lit[1:], '\'')
-       if err != nil || tail != "'" {
-               // Caught by parser
-               a.silentErrors++
-               return nil
-       }
-       return a.compileIdealInt(big.NewInt(int64(v)), "character literal")
-}
-
-func (a *exprInfo) compileFloatLit(lit string) *expr {
-       f, ok := new(big.Rat).SetString(lit)
-       if !ok {
-               log.Panicf("malformed float literal %s at %v passed parser", lit, a.pos)
-       }
-       expr := a.newExpr(IdealFloatType, "float literal")
-       expr.eval = func() *big.Rat { return f }
-       return expr
-}
-
-func (a *exprInfo) compileString(s string) *expr {
-       // Ideal strings don't have a named type but they are
-       // compatible with type string.
-
-       // TODO(austin) Use unnamed string type.
-       expr := a.newExpr(StringType, "string literal")
-       expr.eval = func(*Thread) string { return s }
-       return expr
-}
-
-func (a *exprInfo) compileStringLit(lit string) *expr {
-       s, err := strconv.Unquote(lit)
-       if err != nil {
-               a.diag("illegal string literal, %v", err)
-               return nil
-       }
-       return a.compileString(s)
-}
-
-func (a *exprInfo) compileStringList(list []*expr) *expr {
-       ss := make([]string, len(list))
-       for i, s := range list {
-               ss[i] = s.asString()(nil)
-       }
-       return a.compileString(strings.Join(ss, ""))
-}
-
-func (a *exprInfo) compileFuncLit(decl *FuncDecl, fn func(*Thread) Func) *expr {
-       expr := a.newExpr(decl.Type, "function literal")
-       expr.eval = fn
-       return expr
-}
-
-func (a *exprInfo) compileSelectorExpr(v *expr, name string) *expr {
-       // mark marks a field that matches the selector name.  It
-       // tracks the best depth found so far and whether more than
-       // one field has been found at that depth.
-       bestDepth := -1
-       ambig := false
-       amberr := ""
-       mark := func(depth int, pathName string) {
-               switch {
-               case bestDepth == -1 || depth < bestDepth:
-                       bestDepth = depth
-                       ambig = false
-                       amberr = ""
-
-               case depth == bestDepth:
-                       ambig = true
-
-               default:
-                       log.Panicf("Marked field at depth %d, but already found one at depth %d", depth, bestDepth)
-               }
-               amberr += "\n\t" + pathName[1:]
-       }
-
-       visited := make(map[Type]bool)
-
-       // find recursively searches for the named field, starting at
-       // type t.  If it finds the named field, it returns a function
-       // which takes an expr that represents a value of type 't' and
-       // returns an expr that retrieves the named field.  We delay
-       // expr construction to avoid producing lots of useless expr's
-       // as we search.
-       //
-       // TODO(austin) Now that the expression compiler works on
-       // semantic values instead of AST's, there should be a much
-       // better way of doing this.
-       var find func(Type, int, string) func(*expr) *expr
-       find = func(t Type, depth int, pathName string) func(*expr) *expr {
-               // Don't bother looking if we've found something shallower
-               if bestDepth != -1 && bestDepth < depth {
-                       return nil
-               }
-
-               // Don't check the same type twice and avoid loops
-               if visited[t] {
-                       return nil
-               }
-               visited[t] = true
-
-               // Implicit dereference
-               deref := false
-               if ti, ok := t.(*PtrType); ok {
-                       deref = true
-                       t = ti.Elem
-               }
-
-               // If it's a named type, look for methods
-               if ti, ok := t.(*NamedType); ok {
-                       _, ok := ti.methods[name]
-                       if ok {
-                               mark(depth, pathName+"."+name)
-                               log.Panic("Methods not implemented")
-                       }
-                       t = ti.Def
-               }
-
-               // If it's a struct type, check fields and embedded types
-               var builder func(*expr) *expr
-               if t, ok := t.(*StructType); ok {
-                       for i, f := range t.Elems {
-                               var sub func(*expr) *expr
-                               switch {
-                               case f.Name == name:
-                                       mark(depth, pathName+"."+name)
-                                       sub = func(e *expr) *expr { return e }
-
-                               case f.Anonymous:
-                                       sub = find(f.Type, depth+1, pathName+"."+f.Name)
-                                       if sub == nil {
-                                               continue
-                                       }
-
-                               default:
-                                       continue
-                               }
-
-                               // We found something.  Create a
-                               // builder for accessing this field.
-                               ft := f.Type
-                               index := i
-                               builder = func(parent *expr) *expr {
-                                       if deref {
-                                               parent = a.compileStarExpr(parent)
-                                       }
-                                       expr := a.newExpr(ft, "selector expression")
-                                       pf := parent.asStruct()
-                                       evalAddr := func(t *Thread) Value { return pf(t).Field(t, index) }
-                                       expr.genValue(evalAddr)
-                                       return sub(expr)
-                               }
-                       }
-               }
-
-               return builder
-       }
-
-       builder := find(v.t, 0, "")
-       if builder == nil {
-               a.diag("type %v has no field or method %s", v.t, name)
-               return nil
-       }
-       if ambig {
-               a.diag("field %s is ambiguous in type %v%s", name, v.t, amberr)
-               return nil
-       }
-
-       return builder(v)
-}
-
-func (a *exprInfo) compileSliceExpr(arr, lo, hi *expr) *expr {
-       // Type check object
-       arr = arr.derefArray()
-
-       var at Type
-       var maxIndex int64 = -1
-
-       switch lt := arr.t.lit().(type) {
-       case *ArrayType:
-               at = NewSliceType(lt.Elem)
-               maxIndex = lt.Len
-
-       case *SliceType:
-               at = lt
-
-       case *stringType:
-               at = lt
-
-       default:
-               a.diag("cannot slice %v", arr.t)
-               return nil
-       }
-
-       // Type check index and convert to int
-       // XXX(Spec) It's unclear if ideal floats with no
-       // fractional part are allowed here.  6g allows it.  I
-       // believe that's wrong.
-       lo = lo.convertToInt(maxIndex, "slice", "slice")
-       hi = hi.convertToInt(maxIndex, "slice", "slice")
-       if lo == nil || hi == nil {
-               return nil
-       }
-
-       expr := a.newExpr(at, "slice expression")
-
-       // Compile
-       lof := lo.asInt()
-       hif := hi.asInt()
-       switch lt := arr.t.lit().(type) {
-       case *ArrayType:
-               arrf := arr.asArray()
-               bound := lt.Len
-               expr.eval = func(t *Thread) Slice {
-                       arr, lo, hi := arrf(t), lof(t), hif(t)
-                       if lo > hi || hi > bound || lo < 0 {
-                               t.Abort(SliceError{lo, hi, bound})
-                       }
-                       return Slice{arr.Sub(lo, bound-lo), hi - lo, bound - lo}
-               }
-
-       case *SliceType:
-               arrf := arr.asSlice()
-               expr.eval = func(t *Thread) Slice {
-                       arr, lo, hi := arrf(t), lof(t), hif(t)
-                       if lo > hi || hi > arr.Cap || lo < 0 {
-                               t.Abort(SliceError{lo, hi, arr.Cap})
-                       }
-                       return Slice{arr.Base.Sub(lo, arr.Cap-lo), hi - lo, arr.Cap - lo}
-               }
-
-       case *stringType:
-               arrf := arr.asString()
-               // TODO(austin) This pulls over the whole string in a
-               // remote setting, instead of creating a substring backed
-               // by remote memory.
-               expr.eval = func(t *Thread) string {
-                       arr, lo, hi := arrf(t), lof(t), hif(t)
-                       if lo > hi || hi > int64(len(arr)) || lo < 0 {
-                               t.Abort(SliceError{lo, hi, int64(len(arr))})
-                       }
-                       return arr[lo:hi]
-               }
-
-       default:
-               log.Panicf("unexpected left operand type %T", arr.t.lit())
-       }
-
-       return expr
-}
-
-func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
-       // Type check object
-       l = l.derefArray()
-
-       var at Type
-       intIndex := false
-       var maxIndex int64 = -1
-
-       switch lt := l.t.lit().(type) {
-       case *ArrayType:
-               at = lt.Elem
-               intIndex = true
-               maxIndex = lt.Len
-
-       case *SliceType:
-               at = lt.Elem
-               intIndex = true
-
-       case *stringType:
-               at = Uint8Type
-               intIndex = true
-
-       case *MapType:
-               at = lt.Elem
-               if r.t.isIdeal() {
-                       r = r.convertTo(lt.Key)
-                       if r == nil {
-                               return nil
-                       }
-               }
-               if !lt.Key.compat(r.t, false) {
-                       a.diag("cannot use %s as index into %s", r.t, lt)
-                       return nil
-               }
-
-       default:
-               a.diag("cannot index into %v", l.t)
-               return nil
-       }
-
-       // Type check index and convert to int if necessary
-       if intIndex {
-               // XXX(Spec) It's unclear if ideal floats with no
-               // fractional part are allowed here.  6g allows it.  I
-               // believe that's wrong.
-               r = r.convertToInt(maxIndex, "index", "index")
-               if r == nil {
-                       return nil
-               }
-       }
-
-       expr := a.newExpr(at, "index expression")
-
-       // Compile
-       switch lt := l.t.lit().(type) {
-       case *ArrayType:
-               lf := l.asArray()
-               rf := r.asInt()
-               bound := lt.Len
-               expr.genValue(func(t *Thread) Value {
-                       l, r := lf(t), rf(t)
-                       if r < 0 || r >= bound {
-                               t.Abort(IndexError{r, bound})
-                       }
-                       return l.Elem(t, r)
-               })
-
-       case *SliceType:
-               lf := l.asSlice()
-               rf := r.asInt()
-               expr.genValue(func(t *Thread) Value {
-                       l, r := lf(t), rf(t)
-                       if l.Base == nil {
-                               t.Abort(NilPointerError{})
-                       }
-                       if r < 0 || r >= l.Len {
-                               t.Abort(IndexError{r, l.Len})
-                       }
-                       return l.Base.Elem(t, r)
-               })
-
-       case *stringType:
-               lf := l.asString()
-               rf := r.asInt()
-               // TODO(austin) This pulls over the whole string in a
-               // remote setting, instead of just the one character.
-               expr.eval = func(t *Thread) uint64 {
-                       l, r := lf(t), rf(t)
-                       if r < 0 || r >= int64(len(l)) {
-                               t.Abort(IndexError{r, int64(len(l))})
-                       }
-                       return uint64(l[r])
-               }
-
-       case *MapType:
-               lf := l.asMap()
-               rf := r.asInterface()
-               expr.genValue(func(t *Thread) Value {
-                       m := lf(t)
-                       k := rf(t)
-                       if m == nil {
-                               t.Abort(NilPointerError{})
-                       }
-                       e := m.Elem(t, k)
-                       if e == nil {
-                               t.Abort(KeyError{k})
-                       }
-                       return e
-               })
-               // genValue makes things addressable, but map values
-               // aren't addressable.
-               expr.evalAddr = nil
-               expr.evalMapValue = func(t *Thread) (Map, interface{}) {
-                       // TODO(austin) Key check?  nil check?
-                       return lf(t), rf(t)
-               }
-
-       default:
-               log.Panicf("unexpected left operand type %T", l.t.lit())
-       }
-
-       return expr
-}
-
-func (a *exprInfo) compileCallExpr(b *block, l *expr, as []*expr) *expr {
-       // TODO(austin) Variadic functions.
-
-       // Type check
-
-       // XXX(Spec) Calling a named function type is okay.  I really
-       // think there needs to be a general discussion of named
-       // types.  A named type creates a new, distinct type, but the
-       // type of that type is still whatever it's defined to.  Thus,
-       // in "type Foo int", Foo is still an integer type and in
-       // "type Foo func()", Foo is a function type.
-       lt, ok := l.t.lit().(*FuncType)
-       if !ok {
-               a.diag("cannot call non-function type %v", l.t)
-               return nil
-       }
-
-       // The arguments must be single-valued expressions assignment
-       // compatible with the parameters of F.
-       //
-       // XXX(Spec) The spec is wrong.  It can also be a single
-       // multi-valued expression.
-       nin := len(lt.In)
-       assign := a.compileAssign(a.pos, b, NewMultiType(lt.In), as, "function call", "argument")
-       if assign == nil {
-               return nil
-       }
-
-       var t Type
-       nout := len(lt.Out)
-       switch nout {
-       case 0:
-               t = EmptyType
-       case 1:
-               t = lt.Out[0]
-       default:
-               t = NewMultiType(lt.Out)
-       }
-       expr := a.newExpr(t, "function call")
-
-       // Gather argument and out types to initialize frame variables
-       vts := make([]Type, nin+nout)
-       copy(vts, lt.In)
-       copy(vts[nin:], lt.Out)
-
-       // Compile
-       lf := l.asFunc()
-       call := func(t *Thread) []Value {
-               fun := lf(t)
-               fr := fun.NewFrame()
-               for i, t := range vts {
-                       fr.Vars[i] = t.Zero()
-               }
-               assign(multiV(fr.Vars[0:nin]), t)
-               oldf := t.f
-               t.f = fr
-               fun.Call(t)
-               t.f = oldf
-               return fr.Vars[nin : nin+nout]
-       }
-       expr.genFuncCall(call)
-
-       return expr
-}
-
-func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *expr {
-       checkCount := func(min, max int) bool {
-               if len(as) < min {
-                       a.diag("not enough arguments to %s", ft.builtin)
-                       return false
-               } else if len(as) > max {
-                       a.diag("too many arguments to %s", ft.builtin)
-                       return false
-               }
-               return true
-       }
-
-       switch ft {
-       case capType:
-               if !checkCount(1, 1) {
-                       return nil
-               }
-               arg := as[0].derefArray()
-               expr := a.newExpr(IntType, "function call")
-               switch t := arg.t.lit().(type) {
-               case *ArrayType:
-                       // TODO(austin) It would be nice if this could
-                       // be a constant int.
-                       v := t.Len
-                       expr.eval = func(t *Thread) int64 { return v }
-
-               case *SliceType:
-                       vf := arg.asSlice()
-                       expr.eval = func(t *Thread) int64 { return vf(t).Cap }
-
-               //case *ChanType:
-
-               default:
-                       a.diag("illegal argument type for cap function\n\t%v", arg.t)
-                       return nil
-               }
-               return expr
-
-       case copyType:
-               if !checkCount(2, 2) {
-                       return nil
-               }
-               src := as[1]
-               dst := as[0]
-               if src.t != dst.t {
-                       a.diag("arguments to built-in function 'copy' must have same type\nsrc: %s\ndst: %s\n", src.t, dst.t)
-                       return nil
-               }
-               if _, ok := src.t.lit().(*SliceType); !ok {
-                       a.diag("src argument to 'copy' must be a slice (got: %s)", src.t)
-                       return nil
-               }
-               if _, ok := dst.t.lit().(*SliceType); !ok {
-                       a.diag("dst argument to 'copy' must be a slice (got: %s)", dst.t)
-                       return nil
-               }
-               expr := a.newExpr(IntType, "function call")
-               srcf := src.asSlice()
-               dstf := dst.asSlice()
-               expr.eval = func(t *Thread) int64 {
-                       src, dst := srcf(t), dstf(t)
-                       nelems := src.Len
-                       if nelems > dst.Len {
-                               nelems = dst.Len
-                       }
-                       dst.Base.Sub(0, nelems).Assign(t, src.Base.Sub(0, nelems))
-                       return nelems
-               }
-               return expr
-
-       case lenType:
-               if !checkCount(1, 1) {
-                       return nil
-               }
-               arg := as[0].derefArray()
-               expr := a.newExpr(IntType, "function call")
-               switch t := arg.t.lit().(type) {
-               case *stringType:
-                       vf := arg.asString()
-                       expr.eval = func(t *Thread) int64 { return int64(len(vf(t))) }
-
-               case *ArrayType:
-                       // TODO(austin) It would be nice if this could
-                       // be a constant int.
-                       v := t.Len
-                       expr.eval = func(t *Thread) int64 { return v }
-
-               case *SliceType:
-                       vf := arg.asSlice()
-                       expr.eval = func(t *Thread) int64 { return vf(t).Len }
-
-               case *MapType:
-                       vf := arg.asMap()
-                       expr.eval = func(t *Thread) int64 {
-                               // XXX(Spec) What's the len of an
-                               // uninitialized map?
-                               m := vf(t)
-                               if m == nil {
-                                       return 0
-                               }
-                               return m.Len(t)
-                       }
-
-               //case *ChanType:
-
-               default:
-                       a.diag("illegal argument type for len function\n\t%v", arg.t)
-                       return nil
-               }
-               return expr
-
-       case makeType:
-               if !checkCount(1, 3) {
-                       return nil
-               }
-               // XXX(Spec) What are the types of the
-               // arguments?  Do they have to be ints?  6g
-               // accepts any integral type.
-               var lenexpr, capexpr *expr
-               var lenf, capf func(*Thread) int64
-               if len(as) > 1 {
-                       lenexpr = as[1].convertToInt(-1, "length", "make function")
-                       if lenexpr == nil {
-                               return nil
-                       }
-                       lenf = lenexpr.asInt()
-               }
-               if len(as) > 2 {
-                       capexpr = as[2].convertToInt(-1, "capacity", "make function")
-                       if capexpr == nil {
-                               return nil
-                       }
-                       capf = capexpr.asInt()
-               }
-
-               switch t := as[0].valType.lit().(type) {
-               case *SliceType:
-                       // A new, initialized slice value for a given
-                       // element type T is made using the built-in
-                       // function make, which takes a slice type and
-                       // parameters specifying the length and
-                       // optionally the capacity.
-                       if !checkCount(2, 3) {
-                               return nil
-                       }
-                       et := t.Elem
-                       expr := a.newExpr(t, "function call")
-                       expr.eval = func(t *Thread) Slice {
-                               l := lenf(t)
-                               // XXX(Spec) What if len or cap is
-                               // negative?  The runtime panics.
-                               if l < 0 {
-                                       t.Abort(NegativeLengthError{l})
-                               }
-                               c := l
-                               if capf != nil {
-                                       c = capf(t)
-                                       if c < 0 {
-                                               t.Abort(NegativeCapacityError{c})
-                                       }
-                                       // XXX(Spec) What happens if
-                                       // len > cap?  The runtime
-                                       // sets cap to len.
-                                       if l > c {
-                                               c = l
-                                       }
-                               }
-                               base := arrayV(make([]Value, c))
-                               for i := int64(0); i < c; i++ {
-                                       base[i] = et.Zero()
-                               }
-                               return Slice{&base, l, c}
-                       }
-                       return expr
-
-               case *MapType:
-                       // A new, empty map value is made using the
-                       // built-in function make, which takes the map
-                       // type and an optional capacity hint as
-                       // arguments.
-                       if !checkCount(1, 2) {
-                               return nil
-                       }
-                       expr := a.newExpr(t, "function call")
-                       expr.eval = func(t *Thread) Map {
-                               if lenf == nil {
-                                       return make(evalMap)
-                               }
-                               l := lenf(t)
-                               return make(evalMap, l)
-                       }
-                       return expr
-
-               //case *ChanType:
-
-               default:
-                       a.diag("illegal argument type for make function\n\t%v", as[0].valType)
-                       return nil
-               }
-
-       case closeType, closedType:
-               a.diag("built-in function %s not implemented", ft.builtin)
-               return nil
-
-       case newType:
-               if !checkCount(1, 1) {
-                       return nil
-               }
-
-               t := as[0].valType
-               expr := a.newExpr(NewPtrType(t), "new")
-               expr.eval = func(*Thread) Value { return t.Zero() }
-               return expr
-
-       case panicType, printType, printlnType:
-               evals := make([]func(*Thread) interface{}, len(as))
-               for i, x := range as {
-                       evals[i] = x.asInterface()
-               }
-               spaces := ft == printlnType
-               newline := ft != printType
-               printer := func(t *Thread) {
-                       for i, eval := range evals {
-                               if i > 0 && spaces {
-                                       print(" ")
-                               }
-                               v := eval(t)
-                               type stringer interface {
-                                       String() string
-                               }
-                               switch v1 := v.(type) {
-                               case bool:
-                                       print(v1)
-                               case uint64:
-                                       print(v1)
-                               case int64:
-                                       print(v1)
-                               case float64:
-                                       print(v1)
-                               case string:
-                                       print(v1)
-                               case stringer:
-                                       print(v1.String())
-                               default:
-                                       print("???")
-                               }
-                       }
-                       if newline {
-                               print("\n")
-                       }
-               }
-               expr := a.newExpr(EmptyType, "print")
-               expr.exec = printer
-               if ft == panicType {
-                       expr.exec = func(t *Thread) {
-                               printer(t)
-                               t.Abort(os.NewError("panic"))
-                       }
-               }
-               return expr
-       }
-
-       log.Panicf("unexpected built-in function '%s'", ft.builtin)
-       panic("unreachable")
-}
-
-func (a *exprInfo) compileStarExpr(v *expr) *expr {
-       switch vt := v.t.lit().(type) {
-       case *PtrType:
-               expr := a.newExpr(vt.Elem, "indirect expression")
-               vf := v.asPtr()
-               expr.genValue(func(t *Thread) Value {
-                       v := vf(t)
-                       if v == nil {
-                               t.Abort(NilPointerError{})
-                       }
-                       return v
-               })
-               return expr
-       }
-
-       a.diagOpType(token.MUL, v.t)
-       return nil
-}
-
-var unaryOpDescs = make(map[token.Token]string)
-
-func (a *exprInfo) compileUnaryExpr(op token.Token, v *expr) *expr {
-       // Type check
-       var t Type
-       switch op {
-       case token.ADD, token.SUB:
-               if !v.t.isInteger() && !v.t.isFloat() {
-                       a.diagOpType(op, v.t)
-                       return nil
-               }
-               t = v.t
-
-       case token.NOT:
-               if !v.t.isBoolean() {
-                       a.diagOpType(op, v.t)
-                       return nil
-               }
-               t = BoolType
-
-       case token.XOR:
-               if !v.t.isInteger() {
-                       a.diagOpType(op, v.t)
-                       return nil
-               }
-               t = v.t
-
-       case token.AND:
-               // The unary prefix address-of operator & generates
-               // the address of its operand, which must be a
-               // variable, pointer indirection, field selector, or
-               // array or slice indexing operation.
-               if v.evalAddr == nil {
-                       a.diag("cannot take the address of %s", v.desc)
-                       return nil
-               }
-
-               // TODO(austin) Implement "It is illegal to take the
-               // address of a function result variable" once I have
-               // function result variables.
-
-               t = NewPtrType(v.t)
-
-       case token.ARROW:
-               log.Panicf("Unary op %v not implemented", op)
-
-       default:
-               log.Panicf("unknown unary operator %v", op)
-       }
-
-       desc, ok := unaryOpDescs[op]
-       if !ok {
-               desc = "unary " + op.String() + " expression"
-               unaryOpDescs[op] = desc
-       }
-
-       // Compile
-       expr := a.newExpr(t, desc)
-       switch op {
-       case token.ADD:
-               // Just compile it out
-               expr = v
-               expr.desc = desc
-
-       case token.SUB:
-               expr.genUnaryOpNeg(v)
-
-       case token.NOT:
-               expr.genUnaryOpNot(v)
-
-       case token.XOR:
-               expr.genUnaryOpXor(v)
-
-       case token.AND:
-               vf := v.evalAddr
-               expr.eval = func(t *Thread) Value { return vf(t) }
-
-       default:
-               log.Panicf("Compilation of unary op %v not implemented", op)
-       }
-
-       return expr
-}
-
-var binOpDescs = make(map[token.Token]string)
-
-func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
-       // Save the original types of l.t and r.t for error messages.
-       origlt := l.t
-       origrt := r.t
-
-       // XXX(Spec) What is the exact definition of a "named type"?
-
-       // XXX(Spec) Arithmetic operators: "Integer types" apparently
-       // means all types compatible with basic integer types, though
-       // this is never explained.  Likewise for float types, etc.
-       // This relates to the missing explanation of named types.
-
-       // XXX(Spec) Operators: "If both operands are ideal numbers,
-       // the conversion is to ideal floats if one of the operands is
-       // an ideal float (relevant for / and %)."  How is that
-       // relevant only for / and %?  If I add an ideal int and an
-       // ideal float, I get an ideal float.
-
-       if op != token.SHL && op != token.SHR {
-               // Except in shift expressions, if one operand has
-               // 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.isFloat()) && !l.t.isIdeal() && r.t.isIdeal() {
-                       r = r.convertTo(l.t)
-               } else if (r.t.isInteger() || r.t.isFloat()) && !r.t.isIdeal() && l.t.isIdeal() {
-                       l = l.convertTo(r.t)
-               }
-               if l == nil || r == nil {
-                       return nil
-               }
-
-               // Except in shift expressions, if both operands are
-               // ideal numbers and one is an ideal float, the other
-               // is converted to ideal float.
-               if l.t.isIdeal() && r.t.isIdeal() {
-                       if l.t.isInteger() && r.t.isFloat() {
-                               l = l.convertTo(r.t)
-                       } else if l.t.isFloat() && r.t.isInteger() {
-                               r = r.convertTo(l.t)
-                       }
-                       if l == nil || r == nil {
-                               return nil
-                       }
-               }
-       }
-
-       // Useful type predicates
-       // TODO(austin) CL 33668 mandates identical types except for comparisons.
-       compat := func() bool { return l.t.compat(r.t, false) }
-       integers := func() bool { return l.t.isInteger() && r.t.isInteger() }
-       floats := func() bool { return l.t.isFloat() && r.t.isFloat() }
-       strings := func() bool {
-               // TODO(austin) Deal with named types
-               return l.t == StringType && r.t == StringType
-       }
-       booleans := func() bool { return l.t.isBoolean() && r.t.isBoolean() }
-
-       // Type check
-       var t Type
-       switch op {
-       case token.ADD:
-               if !compat() || (!integers() && !floats() && !strings()) {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               t = l.t
-
-       case token.SUB, token.MUL, token.QUO:
-               if !compat() || (!integers() && !floats()) {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               t = l.t
-
-       case token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
-               if !compat() || !integers() {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               t = l.t
-
-       case token.SHL, token.SHR:
-               // XXX(Spec) Is it okay for the right operand to be an
-               // ideal float with no fractional part?  "The right
-               // operand in a shift operation must be always be of
-               // unsigned integer type or an ideal number that can
-               // be safely converted into an unsigned integer type
-               // (ยงArithmetic operators)" suggests so and 6g agrees.
-
-               if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-
-               // The right operand in a shift operation must be
-               // always be of unsigned integer type or an ideal
-               // number that can be safely converted into an
-               // unsigned integer type.
-               if r.t.isIdeal() {
-                       r2 := r.convertTo(UintType)
-                       if r2 == nil {
-                               return nil
-                       }
-
-                       // If the left operand is not ideal, convert
-                       // the right to not ideal.
-                       if !l.t.isIdeal() {
-                               r = r2
-                       }
-
-                       // If both are ideal, but the right side isn't
-                       // an ideal int, convert it to simplify things.
-                       if l.t.isIdeal() && !r.t.isInteger() {
-                               r = r.convertTo(IdealIntType)
-                               if r == nil {
-                                       log.Panicf("conversion to uintType succeeded, but conversion to idealIntType failed")
-                               }
-                       }
-               } else if _, ok := r.t.lit().(*uintType); !ok {
-                       a.diag("right operand of shift must be unsigned")
-                       return nil
-               }
-
-               if l.t.isIdeal() && !r.t.isIdeal() {
-                       // XXX(Spec) What is the meaning of "ideal >>
-                       // non-ideal"?  Russ says the ideal should be
-                       // converted to an int.  6g propagates the
-                       // type down from assignments as a hint.
-
-                       l = l.convertTo(IntType)
-                       if l == nil {
-                               return nil
-                       }
-               }
-
-               // At this point, we should have one of three cases:
-               // 1) uint SHIFT uint
-               // 2) int SHIFT uint
-               // 3) ideal int SHIFT ideal int
-
-               t = l.t
-
-       case token.LOR, token.LAND:
-               if !booleans() {
-                       return nil
-               }
-               // XXX(Spec) There's no mention of *which* boolean
-               // type the logical operators return.  From poking at
-               // 6g, it appears to be the named boolean type, NOT
-               // the type of the left operand, and NOT an unnamed
-               // boolean type.
-
-               t = BoolType
-
-       case token.ARROW:
-               // The operands in channel sends differ in type: one
-               // is always a channel and the other is a variable or
-               // value of the channel's element type.
-               log.Panic("Binary op <- not implemented")
-               t = BoolType
-
-       case token.LSS, token.GTR, token.LEQ, token.GEQ:
-               // XXX(Spec) It's really unclear what types which
-               // comparison operators apply to.  I feel like the
-               // text is trying to paint a Venn diagram for me,
-               // which it's really pretty simple: <, <=, >, >= apply
-               // only to numeric types and strings.  == and != apply
-               // to everything except arrays and structs, and there
-               // are some restrictions on when it applies to slices.
-
-               if !compat() || (!integers() && !floats() && !strings()) {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               t = BoolType
-
-       case token.EQL, token.NEQ:
-               // XXX(Spec) The rules for type checking comparison
-               // operators are spread across three places that all
-               // partially overlap with each other: the Comparison
-               // Compatibility section, the Operators section, and
-               // the Comparison Operators section.  The Operators
-               // section should just say that operators require
-               // identical types (as it does currently) except that
-               // there a few special cases for comparison, which are
-               // described in section X.  Currently it includes just
-               // one of the four special cases.  The Comparison
-               // Compatibility section and the Comparison Operators
-               // section should either be merged, or at least the
-               // Comparison Compatibility section should be
-               // exclusively about type checking and the Comparison
-               // Operators section should be exclusively about
-               // semantics.
-
-               // XXX(Spec) Comparison operators: "All comparison
-               // operators apply to basic types except bools."  This
-               // is very difficult to parse.  It's explained much
-               // better in the Comparison Compatibility section.
-
-               // XXX(Spec) Comparison compatibility: "Function
-               // values are equal if they refer to the same
-               // function." is rather vague.  It should probably be
-               // similar to the way the rule for map values is
-               // written: Function values are equal if they were
-               // created by the same execution of a function literal
-               // or refer to the same function declaration.  This is
-               // *almost* but not quite what 6g implements.  If a
-               // function literals does not capture any variables,
-               // then multiple executions of it will result in the
-               // same closure.  Russ says he'll change that.
-
-               // TODO(austin) Deal with remaining special cases
-
-               if !compat() {
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               // Arrays and structs may not be compared to anything.
-               switch l.t.(type) {
-               case *ArrayType, *StructType:
-                       a.diagOpTypes(op, origlt, origrt)
-                       return nil
-               }
-               t = BoolType
-
-       default:
-               log.Panicf("unknown binary operator %v", op)
-       }
-
-       desc, ok := binOpDescs[op]
-       if !ok {
-               desc = op.String() + " expression"
-               binOpDescs[op] = desc
-       }
-
-       // Check for ideal divide by zero
-       switch op {
-       case token.QUO, token.REM:
-               if r.t.isIdeal() {
-                       if (r.t.isInteger() && r.asIdealInt()().Sign() == 0) ||
-                               (r.t.isFloat() && r.asIdealFloat()().Sign() == 0) {
-                               a.diag("divide by zero")
-                               return nil
-                       }
-               }
-       }
-
-       // Compile
-       expr := a.newExpr(t, desc)
-       switch op {
-       case token.ADD:
-               expr.genBinOpAdd(l, r)
-
-       case token.SUB:
-               expr.genBinOpSub(l, r)
-
-       case token.MUL:
-               expr.genBinOpMul(l, r)
-
-       case token.QUO:
-               expr.genBinOpQuo(l, r)
-
-       case token.REM:
-               expr.genBinOpRem(l, r)
-
-       case token.AND:
-               expr.genBinOpAnd(l, r)
-
-       case token.OR:
-               expr.genBinOpOr(l, r)
-
-       case token.XOR:
-               expr.genBinOpXor(l, r)
-
-       case token.AND_NOT:
-               expr.genBinOpAndNot(l, r)
-
-       case token.SHL:
-               if l.t.isIdeal() {
-                       lv := l.asIdealInt()()
-                       rv := r.asIdealInt()()
-                       const maxShift = 99999
-                       if rv.Cmp(big.NewInt(maxShift)) > 0 {
-                               a.diag("left shift by %v; exceeds implementation limit of %v", rv, maxShift)
-                               expr.t = nil
-                               return nil
-                       }
-                       val := new(big.Int).Lsh(lv, uint(rv.Int64()))
-                       expr.eval = func() *big.Int { return val }
-               } else {
-                       expr.genBinOpShl(l, r)
-               }
-
-       case token.SHR:
-               if l.t.isIdeal() {
-                       lv := l.asIdealInt()()
-                       rv := r.asIdealInt()()
-                       val := new(big.Int).Rsh(lv, uint(rv.Int64()))
-                       expr.eval = func() *big.Int { return val }
-               } else {
-                       expr.genBinOpShr(l, r)
-               }
-
-       case token.LSS:
-               expr.genBinOpLss(l, r)
-
-       case token.GTR:
-               expr.genBinOpGtr(l, r)
-
-       case token.LEQ:
-               expr.genBinOpLeq(l, r)
-
-       case token.GEQ:
-               expr.genBinOpGeq(l, r)
-
-       case token.EQL:
-               expr.genBinOpEql(l, r)
-
-       case token.NEQ:
-               expr.genBinOpNeq(l, r)
-
-       case token.LAND:
-               expr.genBinOpLogAnd(l, r)
-
-       case token.LOR:
-               expr.genBinOpLogOr(l, r)
-
-       default:
-               log.Panicf("Compilation of binary op %v not implemented", op)
-       }
-
-       return expr
-}
-
-// TODO(austin) This is a hack to eliminate a circular dependency
-// between type.go and expr.go
-func (a *compiler) compileArrayLen(b *block, expr ast.Expr) (int64, bool) {
-       lenExpr := a.compileExpr(b, true, expr)
-       if lenExpr == nil {
-               return 0, false
-       }
-
-       // XXX(Spec) Are ideal floats with no fractional part okay?
-       if lenExpr.t.isIdeal() {
-               lenExpr = lenExpr.convertTo(IntType)
-               if lenExpr == nil {
-                       return 0, false
-               }
-       }
-
-       if !lenExpr.t.isInteger() {
-               a.diagAt(expr.Pos(), "array size must be an integer")
-               return 0, false
-       }
-
-       switch lenExpr.t.lit().(type) {
-       case *intType:
-               return lenExpr.asInt()(nil), true
-       case *uintType:
-               return int64(lenExpr.asUint()(nil)), true
-       }
-       log.Panicf("unexpected integer type %T", lenExpr.t)
-       return 0, false
-}
-
-func (a *compiler) compileExpr(b *block, constant bool, expr ast.Expr) *expr {
-       ec := &exprCompiler{a, b, constant}
-       nerr := a.numError()
-       e := ec.compile(expr, false)
-       if e == nil && nerr == a.numError() {
-               log.Panicf("expression compilation failed without reporting errors")
-       }
-       return e
-}
-
-// extractEffect separates out any effects that the expression may
-// have, returning a function that will perform those effects and a
-// new exprCompiler that is guaranteed to be side-effect free.  These
-// are the moral equivalents of "temp := expr" and "temp" (or "temp :=
-// &expr" and "*temp" for addressable exprs).  Because this creates a
-// temporary variable, the caller should create a temporary block for
-// the compilation of this expression and the evaluation of the
-// results.
-func (a *expr) extractEffect(b *block, errOp string) (func(*Thread), *expr) {
-       // Create "&a" if a is addressable
-       rhs := a
-       if a.evalAddr != nil {
-               rhs = a.compileUnaryExpr(token.AND, rhs)
-       }
-
-       // Create temp
-       ac, ok := a.checkAssign(a.pos, []*expr{rhs}, errOp, "")
-       if !ok {
-               return nil, nil
-       }
-       if len(ac.rmt.Elems) != 1 {
-               a.diag("multi-valued expression not allowed in %s", errOp)
-               return nil, nil
-       }
-       tempType := ac.rmt.Elems[0]
-       if tempType.isIdeal() {
-               // It's too bad we have to duplicate this rule.
-               switch {
-               case tempType.isInteger():
-                       tempType = IntType
-               case tempType.isFloat():
-                       tempType = Float64Type
-               default:
-                       log.Panicf("unexpected ideal type %v", tempType)
-               }
-       }
-       temp := b.DefineTemp(tempType)
-       tempIdx := temp.Index
-
-       // Create "temp := rhs"
-       assign := ac.compile(b, tempType)
-       if assign == nil {
-               log.Panicf("compileAssign type check failed")
-       }
-
-       effect := func(t *Thread) {
-               tempVal := tempType.Zero()
-               t.f.Vars[tempIdx] = tempVal
-               assign(tempVal, t)
-       }
-
-       // Generate "temp" or "*temp"
-       getTemp := a.compileVariable(0, temp)
-       if a.evalAddr == nil {
-               return effect, getTemp
-       }
-
-       deref := a.compileStarExpr(getTemp)
-       if deref == nil {
-               return nil, nil
-       }
-       return effect, deref
-}
diff --git a/src/pkg/exp/eval/expr1.go b/src/pkg/exp/eval/expr1.go
deleted file mode 100755 (executable)
index 5d0e500..0000000
+++ /dev/null
@@ -1,1874 +0,0 @@
-// This file is machine generated by gen.go.
-// 6g gen.go && 6l gen.6 && ./6.out >expr1.go
-
-package eval
-
-import (
-       "big"
-       "log"
-)
-
-/*
- * "As" functions.  These retrieve evaluator functions from an
- * expr, panicking if the requested evaluator has the wrong type.
- */
-func (a *expr) asBool() func(*Thread) bool {
-       return a.eval.(func(*Thread) bool)
-}
-func (a *expr) asUint() func(*Thread) uint64 {
-       return a.eval.(func(*Thread) uint64)
-}
-func (a *expr) asInt() func(*Thread) int64 {
-       return a.eval.(func(*Thread) int64)
-}
-func (a *expr) asIdealInt() func() *big.Int {
-       return a.eval.(func() *big.Int)
-}
-func (a *expr) asFloat() func(*Thread) float64 {
-       return a.eval.(func(*Thread) float64)
-}
-func (a *expr) asIdealFloat() func() *big.Rat {
-       return a.eval.(func() *big.Rat)
-}
-func (a *expr) asString() func(*Thread) string {
-       return a.eval.(func(*Thread) string)
-}
-func (a *expr) asArray() func(*Thread) ArrayValue {
-       return a.eval.(func(*Thread) ArrayValue)
-}
-func (a *expr) asStruct() func(*Thread) StructValue {
-       return a.eval.(func(*Thread) StructValue)
-}
-func (a *expr) asPtr() func(*Thread) Value {
-       return a.eval.(func(*Thread) Value)
-}
-func (a *expr) asFunc() func(*Thread) Func {
-       return a.eval.(func(*Thread) Func)
-}
-func (a *expr) asSlice() func(*Thread) Slice {
-       return a.eval.(func(*Thread) Slice)
-}
-func (a *expr) asMap() func(*Thread) Map {
-       return a.eval.(func(*Thread) Map)
-}
-func (a *expr) asMulti() func(*Thread) []Value {
-       return a.eval.(func(*Thread) []Value)
-}
-
-func (a *expr) asInterface() func(*Thread) interface{} {
-       switch sf := a.eval.(type) {
-       case func(t *Thread) bool:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) uint64:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) int64:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func() *big.Int:
-               return func(*Thread) interface{} { return sf() }
-       case func(t *Thread) float64:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func() *big.Rat:
-               return func(*Thread) interface{} { return sf() }
-       case func(t *Thread) string:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) ArrayValue:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) StructValue:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) Value:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) Func:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) Slice:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(t *Thread) Map:
-               return func(t *Thread) interface{} { return sf(t) }
-       default:
-               log.Panicf("unexpected expression node type %T at %v", a.eval, a.pos)
-       }
-       panic("fail")
-}
-
-/*
- * Operator generators.
- */
-
-func (a *expr) genConstant(v Value) {
-       switch a.t.lit().(type) {
-       case *boolType:
-               a.eval = func(t *Thread) bool { return v.(BoolValue).Get(t) }
-       case *uintType:
-               a.eval = func(t *Thread) uint64 { return v.(UintValue).Get(t) }
-       case *intType:
-               a.eval = func(t *Thread) int64 { return v.(IntValue).Get(t) }
-       case *idealIntType:
-               val := v.(IdealIntValue).Get()
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               a.eval = func(t *Thread) float64 { return v.(FloatValue).Get(t) }
-       case *idealFloatType:
-               val := v.(IdealFloatValue).Get()
-               a.eval = func() *big.Rat { return val }
-       case *stringType:
-               a.eval = func(t *Thread) string { return v.(StringValue).Get(t) }
-       case *ArrayType:
-               a.eval = func(t *Thread) ArrayValue { return v.(ArrayValue).Get(t) }
-       case *StructType:
-               a.eval = func(t *Thread) StructValue { return v.(StructValue).Get(t) }
-       case *PtrType:
-               a.eval = func(t *Thread) Value { return v.(PtrValue).Get(t) }
-       case *FuncType:
-               a.eval = func(t *Thread) Func { return v.(FuncValue).Get(t) }
-       case *SliceType:
-               a.eval = func(t *Thread) Slice { return v.(SliceValue).Get(t) }
-       case *MapType:
-               a.eval = func(t *Thread) Map { return v.(MapValue).Get(t) }
-       default:
-               log.Panicf("unexpected constant type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genIdentOp(level, index int) {
-       a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) }
-       switch a.t.lit().(type) {
-       case *boolType:
-               a.eval = func(t *Thread) bool { return t.f.Get(level, index).(BoolValue).Get(t) }
-       case *uintType:
-               a.eval = func(t *Thread) uint64 { return t.f.Get(level, index).(UintValue).Get(t) }
-       case *intType:
-               a.eval = func(t *Thread) int64 { return t.f.Get(level, index).(IntValue).Get(t) }
-       case *floatType:
-               a.eval = func(t *Thread) float64 { return t.f.Get(level, index).(FloatValue).Get(t) }
-       case *stringType:
-               a.eval = func(t *Thread) string { return t.f.Get(level, index).(StringValue).Get(t) }
-       case *ArrayType:
-               a.eval = func(t *Thread) ArrayValue { return t.f.Get(level, index).(ArrayValue).Get(t) }
-       case *StructType:
-               a.eval = func(t *Thread) StructValue { return t.f.Get(level, index).(StructValue).Get(t) }
-       case *PtrType:
-               a.eval = func(t *Thread) Value { return t.f.Get(level, index).(PtrValue).Get(t) }
-       case *FuncType:
-               a.eval = func(t *Thread) Func { return t.f.Get(level, index).(FuncValue).Get(t) }
-       case *SliceType:
-               a.eval = func(t *Thread) Slice { return t.f.Get(level, index).(SliceValue).Get(t) }
-       case *MapType:
-               a.eval = func(t *Thread) Map { return t.f.Get(level, index).(MapValue).Get(t) }
-       default:
-               log.Panicf("unexpected identifier type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genFuncCall(call func(t *Thread) []Value) {
-       a.exec = func(t *Thread) { call(t) }
-       switch a.t.lit().(type) {
-       case *boolType:
-               a.eval = func(t *Thread) bool { return call(t)[0].(BoolValue).Get(t) }
-       case *uintType:
-               a.eval = func(t *Thread) uint64 { return call(t)[0].(UintValue).Get(t) }
-       case *intType:
-               a.eval = func(t *Thread) int64 { return call(t)[0].(IntValue).Get(t) }
-       case *floatType:
-               a.eval = func(t *Thread) float64 { return call(t)[0].(FloatValue).Get(t) }
-       case *stringType:
-               a.eval = func(t *Thread) string { return call(t)[0].(StringValue).Get(t) }
-       case *ArrayType:
-               a.eval = func(t *Thread) ArrayValue { return call(t)[0].(ArrayValue).Get(t) }
-       case *StructType:
-               a.eval = func(t *Thread) StructValue { return call(t)[0].(StructValue).Get(t) }
-       case *PtrType:
-               a.eval = func(t *Thread) Value { return call(t)[0].(PtrValue).Get(t) }
-       case *FuncType:
-               a.eval = func(t *Thread) Func { return call(t)[0].(FuncValue).Get(t) }
-       case *SliceType:
-               a.eval = func(t *Thread) Slice { return call(t)[0].(SliceValue).Get(t) }
-       case *MapType:
-               a.eval = func(t *Thread) Map { return call(t)[0].(MapValue).Get(t) }
-       case *MultiType:
-               a.eval = func(t *Thread) []Value { return call(t) }
-       default:
-               log.Panicf("unexpected result type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genValue(vf func(*Thread) Value) {
-       a.evalAddr = vf
-       switch a.t.lit().(type) {
-       case *boolType:
-               a.eval = func(t *Thread) bool { return vf(t).(BoolValue).Get(t) }
-       case *uintType:
-               a.eval = func(t *Thread) uint64 { return vf(t).(UintValue).Get(t) }
-       case *intType:
-               a.eval = func(t *Thread) int64 { return vf(t).(IntValue).Get(t) }
-       case *floatType:
-               a.eval = func(t *Thread) float64 { return vf(t).(FloatValue).Get(t) }
-       case *stringType:
-               a.eval = func(t *Thread) string { return vf(t).(StringValue).Get(t) }
-       case *ArrayType:
-               a.eval = func(t *Thread) ArrayValue { return vf(t).(ArrayValue).Get(t) }
-       case *StructType:
-               a.eval = func(t *Thread) StructValue { return vf(t).(StructValue).Get(t) }
-       case *PtrType:
-               a.eval = func(t *Thread) Value { return vf(t).(PtrValue).Get(t) }
-       case *FuncType:
-               a.eval = func(t *Thread) Func { return vf(t).(FuncValue).Get(t) }
-       case *SliceType:
-               a.eval = func(t *Thread) Slice { return vf(t).(SliceValue).Get(t) }
-       case *MapType:
-               a.eval = func(t *Thread) Map { return vf(t).(MapValue).Get(t) }
-       default:
-               log.Panicf("unexpected result type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genUnaryOpNeg(v *expr) {
-       switch a.t.lit().(type) {
-       case *uintType:
-               vf := v.asUint()
-               a.eval = func(t *Thread) uint64 { v := vf(t); return -v }
-       case *intType:
-               vf := v.asInt()
-               a.eval = func(t *Thread) int64 { v := vf(t); return -v }
-       case *idealIntType:
-               val := v.asIdealInt()()
-               val.Neg(val)
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               vf := v.asFloat()
-               a.eval = func(t *Thread) float64 { v := vf(t); return -v }
-       case *idealFloatType:
-               val := v.asIdealFloat()()
-               val.Neg(val)
-               a.eval = func() *big.Rat { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genUnaryOpNot(v *expr) {
-       switch a.t.lit().(type) {
-       case *boolType:
-               vf := v.asBool()
-               a.eval = func(t *Thread) bool { v := vf(t); return !v }
-       default:
-               log.Panicf("unexpected type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genUnaryOpXor(v *expr) {
-       switch a.t.lit().(type) {
-       case *uintType:
-               vf := v.asUint()
-               a.eval = func(t *Thread) uint64 { v := vf(t); return ^v }
-       case *intType:
-               vf := v.asInt()
-               a.eval = func(t *Thread) int64 { v := vf(t); return ^v }
-       case *idealIntType:
-               val := v.asIdealInt()()
-               val.Not(val)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpLogAnd(l, r *expr) {
-       lf := l.asBool()
-       rf := r.asBool()
-       a.eval = func(t *Thread) bool { return lf(t) && rf(t) }
-}
-
-func (a *expr) genBinOpLogOr(l, r *expr) {
-       lf := l.asBool()
-       rf := r.asBool()
-       a.eval = func(t *Thread) bool { return lf(t) || rf(t) }
-}
-
-func (a *expr) genBinOpAdd(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l + r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l + r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l + r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l + r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l + r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l + r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l + r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l + r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l + r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l + r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Add(l, r)
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               switch t.Bits {
-               case 32:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l + r
-                               return float64(float32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l + r
-                               return float64(float64(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Add(l, r)
-               a.eval = func() *big.Rat { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) string {
-                       l, r := lf(t), rf(t)
-                       return l + r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpSub(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l - r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l - r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l - r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l - r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l - r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l - r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l - r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l - r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l - r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l - r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Sub(l, r)
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               switch t.Bits {
-               case 32:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l - r
-                               return float64(float32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l - r
-                               return float64(float64(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Sub(l, r)
-               a.eval = func() *big.Rat { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpMul(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l * r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l * r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l * r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l * r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l * r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l * r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l * r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l * r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l * r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l * r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Mul(l, r)
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               switch t.Bits {
-               case 32:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l * r
-                               return float64(float32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               ret = l * r
-                               return float64(float64(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Mul(l, r)
-               a.eval = func() *big.Rat { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpQuo(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Quo(l, r)
-               a.eval = func() *big.Int { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               switch t.Bits {
-               case 32:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return float64(float32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) float64 {
-                               l, r := lf(t), rf(t)
-                               var ret float64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l / r
-                               return float64(float64(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Quo(l, r)
-               a.eval = func() *big.Rat { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpRem(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               if r == 0 {
-                                       t.Abort(DivByZeroError{})
-                               }
-                               ret = l % r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Rem(l, r)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpAnd(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l & r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l & r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l & r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l & r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l & r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l & r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l & r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l & r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l & r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l & r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.And(l, r)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpOr(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l | r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l | r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l | r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l | r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l | r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l | r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l | r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l | r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l | r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l | r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Or(l, r)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpXor(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l ^ r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l ^ r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l ^ r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l ^ r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l ^ r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l ^ r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l ^ r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l ^ r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l ^ r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l ^ r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Xor(l, r)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpAndNot(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l &^ r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l &^ r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l &^ r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l &^ r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l &^ r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l &^ r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l &^ r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l &^ r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l &^ r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l &^ r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.AndNot(l, r)
-               a.eval = func() *big.Int { return val }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpShl(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l << r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l << r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l << r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l << r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l << r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l << r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l << r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l << r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l << r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l << r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpShr(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l >> r
-                               return uint64(uint8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l >> r
-                               return uint64(uint16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l >> r
-                               return uint64(uint32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l >> r
-                               return uint64(uint64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) uint64 {
-                               l, r := lf(t), rf(t)
-                               var ret uint64
-                               ret = l >> r
-                               return uint64(uint(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asUint()
-               switch t.Bits {
-               case 8:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l >> r
-                               return int64(int8(ret))
-                       }
-               case 16:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l >> r
-                               return int64(int16(ret))
-                       }
-               case 32:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l >> r
-                               return int64(int32(ret))
-                       }
-               case 64:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l >> r
-                               return int64(int64(ret))
-                       }
-               case 0:
-                       a.eval = func(t *Thread) int64 {
-                               l, r := lf(t), rf(t)
-                               var ret int64
-                               ret = l >> r
-                               return int64(int(ret))
-                       }
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpLss(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l < r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l < r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) < 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l < r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) < 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l < r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpGtr(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l > r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l > r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) > 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l > r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) > 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l > r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpLeq(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l <= r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l <= r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) <= 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l <= r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) <= 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l <= r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpGeq(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l >= r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l >= r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) >= 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l >= r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) >= 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l >= r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpEql(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *boolType:
-               lf := l.asBool()
-               rf := r.asBool()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) == 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) == 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *PtrType:
-               lf := l.asPtr()
-               rf := r.asPtr()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *FuncType:
-               lf := l.asFunc()
-               rf := r.asFunc()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       case *MapType:
-               lf := l.asMap()
-               rf := r.asMap()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l == r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func (a *expr) genBinOpNeq(l, r *expr) {
-       switch t := l.t.lit().(type) {
-       case *boolType:
-               lf := l.asBool()
-               rf := r.asBool()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *uintType:
-               lf := l.asUint()
-               rf := r.asUint()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *intType:
-               lf := l.asInt()
-               rf := r.asInt()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *idealIntType:
-               l := l.asIdealInt()()
-               r := r.asIdealInt()()
-               val := l.Cmp(r) != 0
-               a.eval = func(t *Thread) bool { return val }
-       case *floatType:
-               lf := l.asFloat()
-               rf := r.asFloat()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *idealFloatType:
-               l := l.asIdealFloat()()
-               r := r.asIdealFloat()()
-               val := l.Cmp(r) != 0
-               a.eval = func(t *Thread) bool { return val }
-       case *stringType:
-               lf := l.asString()
-               rf := r.asString()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *PtrType:
-               lf := l.asPtr()
-               rf := r.asPtr()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *FuncType:
-               lf := l.asFunc()
-               rf := r.asFunc()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       case *MapType:
-               lf := l.asMap()
-               rf := r.asMap()
-               a.eval = func(t *Thread) bool {
-                       l, r := lf(t), rf(t)
-                       return l != r
-               }
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-func genAssign(lt Type, r *expr) func(lv Value, t *Thread) {
-       switch lt.lit().(type) {
-       case *boolType:
-               rf := r.asBool()
-               return func(lv Value, t *Thread) { lv.(BoolValue).Set(t, rf(t)) }
-       case *uintType:
-               rf := r.asUint()
-               return func(lv Value, t *Thread) { lv.(UintValue).Set(t, rf(t)) }
-       case *intType:
-               rf := r.asInt()
-               return func(lv Value, t *Thread) { lv.(IntValue).Set(t, rf(t)) }
-       case *floatType:
-               rf := r.asFloat()
-               return func(lv Value, t *Thread) { lv.(FloatValue).Set(t, rf(t)) }
-       case *stringType:
-               rf := r.asString()
-               return func(lv Value, t *Thread) { lv.(StringValue).Set(t, rf(t)) }
-       case *ArrayType:
-               rf := r.asArray()
-               return func(lv Value, t *Thread) { lv.Assign(t, rf(t)) }
-       case *StructType:
-               rf := r.asStruct()
-               return func(lv Value, t *Thread) { lv.Assign(t, rf(t)) }
-       case *PtrType:
-               rf := r.asPtr()
-               return func(lv Value, t *Thread) { lv.(PtrValue).Set(t, rf(t)) }
-       case *FuncType:
-               rf := r.asFunc()
-               return func(lv Value, t *Thread) { lv.(FuncValue).Set(t, rf(t)) }
-       case *SliceType:
-               rf := r.asSlice()
-               return func(lv Value, t *Thread) { lv.(SliceValue).Set(t, rf(t)) }
-       case *MapType:
-               rf := r.asMap()
-               return func(lv Value, t *Thread) { lv.(MapValue).Set(t, rf(t)) }
-       default:
-               log.Panicf("unexpected left operand type %v at %v", lt, r.pos)
-       }
-       panic("fail")
-}
diff --git a/src/pkg/exp/eval/expr_test.go b/src/pkg/exp/eval/expr_test.go
deleted file mode 100644 (file)
index 0dbce43..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "testing"
-)
-
-var undefined = "undefined"
-var typeAsExpr = "type .* used as expression"
-var badCharLit = "character literal"
-var unknownEscape = "unknown escape sequence"
-var opTypes = "illegal (operand|argument) type|cannot index into"
-var badAddrOf = "cannot take the address"
-var constantTruncated = "constant [^ ]* truncated"
-var constantUnderflows = "constant [^ ]* underflows"
-var constantOverflows = "constant [^ ]* overflows"
-var implLimit = "implementation limit"
-var mustBeUnsigned = "must be unsigned"
-var divByZero = "divide by zero"
-
-var hugeInteger = new(big.Int).Lsh(idealOne, 64)
-
-var exprTests = []test{
-       Val("i", 1),
-       CErr("zzz", undefined),
-       // TODO(austin) Test variable in constant context
-       //CErr("t", typeAsExpr),
-
-       Val("'a'", big.NewInt('a')),
-       Val("'\\uffff'", big.NewInt('\uffff')),
-       Val("'\\n'", big.NewInt('\n')),
-       CErr("''+x", badCharLit),
-       // Produces two parse errors
-       //CErr("'''", ""),
-       CErr("'\n'", badCharLit),
-       CErr("'\\z'", unknownEscape),
-       CErr("'ab'", badCharLit),
-
-       Val("1.0", big.NewRat(1, 1)),
-       Val("1.", big.NewRat(1, 1)),
-       Val(".1", big.NewRat(1, 10)),
-       Val("1e2", big.NewRat(100, 1)),
-
-       Val("\"abc\"", "abc"),
-       Val("\"\"", ""),
-       Val("\"\\n\\\"\"", "\n\""),
-       CErr("\"\\z\"", unknownEscape),
-       CErr("\"abc", "string not terminated"),
-
-       Val("(i)", 1),
-
-       Val("ai[0]", 1),
-       Val("(&ai)[0]", 1),
-       Val("ai[1]", 2),
-       Val("ai[i]", 2),
-       Val("ai[u]", 2),
-       CErr("ai[f]", opTypes),
-       CErr("ai[0][0]", opTypes),
-       CErr("ai[2]", "index 2 exceeds"),
-       CErr("ai[1+1]", "index 2 exceeds"),
-       CErr("ai[-1]", "negative index"),
-       RErr("ai[i+i]", "index 2 exceeds"),
-       RErr("ai[-i]", "negative index"),
-       CErr("i[0]", opTypes),
-       CErr("f[0]", opTypes),
-
-       Val("aai[0][0]", 1),
-       Val("aai[1][1]", 4),
-       CErr("aai[2][0]", "index 2 exceeds"),
-       CErr("aai[0][2]", "index 2 exceeds"),
-
-       Val("sli[0]", 1),
-       Val("sli[1]", 2),
-       CErr("sli[-1]", "negative index"),
-       RErr("sli[-i]", "negative index"),
-       RErr("sli[2]", "index 2 exceeds"),
-
-       Val("s[0]", uint8('a')),
-       Val("s[1]", uint8('b')),
-       CErr("s[-1]", "negative index"),
-       RErr("s[-i]", "negative index"),
-       RErr("s[3]", "index 3 exceeds"),
-
-       Val("ai[0:2]", vslice{varray{1, 2}, 2, 2}),
-       Val("ai[0:1]", vslice{varray{1, 2}, 1, 2}),
-       Val("ai[0:]", vslice{varray{1, 2}, 2, 2}),
-       Val("ai[i:]", vslice{varray{2}, 1, 1}),
-
-       Val("sli[0:2]", vslice{varray{1, 2, 3}, 2, 3}),
-       Val("sli[0:i]", vslice{varray{1, 2, 3}, 1, 3}),
-       Val("sli[1:]", vslice{varray{2, 3}, 1, 2}),
-
-       CErr("1(2)", "cannot call"),
-       CErr("fn(1,2)", "too many"),
-       CErr("fn()", "not enough"),
-       CErr("fn(true)", opTypes),
-       CErr("fn(true)", "function call"),
-       // Single argument functions don't say which argument.
-       //CErr("fn(true)", "argument 1"),
-       Val("fn(1)", 2),
-       Val("fn(1.0)", 2),
-       CErr("fn(1.5)", constantTruncated),
-       Val("fn(i)", 2),
-       CErr("fn(u)", opTypes),
-
-       CErr("void()+2", opTypes),
-       CErr("oneTwo()+2", opTypes),
-
-       Val("cap(ai)", 2),
-       Val("cap(&ai)", 2),
-       Val("cap(aai)", 2),
-       Val("cap(sli)", 3),
-       CErr("cap(0)", opTypes),
-       CErr("cap(i)", opTypes),
-       CErr("cap(s)", opTypes),
-
-       Val("len(s)", 3),
-       Val("len(ai)", 2),
-       Val("len(&ai)", 2),
-       Val("len(ai[0:])", 2),
-       Val("len(ai[1:])", 1),
-       Val("len(ai[2:])", 0),
-       Val("len(aai)", 2),
-       Val("len(sli)", 2),
-       Val("len(sli[0:])", 2),
-       Val("len(sli[1:])", 1),
-       Val("len(sli[2:])", 0),
-       // TODO(austin) Test len of map
-       CErr("len(0)", opTypes),
-       CErr("len(i)", opTypes),
-
-       CErr("*i", opTypes),
-       Val("*&i", 1),
-       Val("*&(i)", 1),
-       CErr("&1", badAddrOf),
-       CErr("&c", badAddrOf),
-       Val("*(&ai[0])", 1),
-
-       Val("+1", big.NewInt(+1)),
-       Val("+1.0", big.NewRat(1, 1)),
-       Val("01.5", big.NewRat(15, 10)),
-       CErr("+\"x\"", opTypes),
-
-       Val("-42", big.NewInt(-42)),
-       Val("-i", -1),
-       Val("-f", -1.0),
-       // 6g bug?
-       //Val("-(f-1)", -0.0),
-       CErr("-\"x\"", opTypes),
-
-       // TODO(austin) Test unary !
-
-       Val("^2", big.NewInt(^2)),
-       Val("^(-2)", big.NewInt(^(-2))),
-       CErr("^2.0", opTypes),
-       CErr("^2.5", opTypes),
-       Val("^i", ^1),
-       Val("^u", ^uint(1)),
-       CErr("^f", opTypes),
-
-       Val("1+i", 2),
-       Val("1+u", uint(2)),
-       Val("3.0+i", 4),
-       Val("1+1", big.NewInt(2)),
-       Val("f+f", 2.0),
-       Val("1+f", 2.0),
-       Val("1.0+1", big.NewRat(2, 1)),
-       Val("\"abc\" + \"def\"", "abcdef"),
-       CErr("i+u", opTypes),
-       CErr("-1+u", constantUnderflows),
-       // TODO(austin) Test named types
-
-       Val("2-1", big.NewInt(1)),
-       Val("2.0-1", big.NewRat(1, 1)),
-       Val("f-2", -1.0),
-       Val("-0.0", big.NewRat(0, 1)),
-       Val("2*2", big.NewInt(4)),
-       Val("2*i", 2),
-       Val("3/2", big.NewInt(1)),
-       Val("3/i", 3),
-       CErr("1/0", divByZero),
-       CErr("1.0/0", divByZero),
-       RErr("i/0", divByZero),
-       Val("3%2", big.NewInt(1)),
-       Val("i%2", 1),
-       CErr("3%0", divByZero),
-       CErr("3.0%0", opTypes),
-       RErr("i%0", divByZero),
-
-       // Examples from "Arithmetic operators"
-       Val("5/3", big.NewInt(1)),
-       Val("(i+4)/(i+2)", 1),
-       Val("5%3", big.NewInt(2)),
-       Val("(i+4)%(i+2)", 2),
-       Val("-5/3", big.NewInt(-1)),
-       Val("(i-6)/(i+2)", -1),
-       Val("-5%3", big.NewInt(-2)),
-       Val("(i-6)%(i+2)", -2),
-       Val("5/-3", big.NewInt(-1)),
-       Val("(i+4)/(i-4)", -1),
-       Val("5%-3", big.NewInt(2)),
-       Val("(i+4)%(i-4)", 2),
-       Val("-5/-3", big.NewInt(1)),
-       Val("(i-6)/(i-4)", 1),
-       Val("-5%-3", big.NewInt(-2)),
-       Val("(i-6)%(i-4)", -2),
-
-       // Examples from "Arithmetic operators"
-       Val("11/4", big.NewInt(2)),
-       Val("(i+10)/4", 2),
-       Val("11%4", big.NewInt(3)),
-       Val("(i+10)%4", 3),
-       Val("11>>2", big.NewInt(2)),
-       Val("(i+10)>>2", 2),
-       Val("11&3", big.NewInt(3)),
-       Val("(i+10)&3", 3),
-       Val("-11/4", big.NewInt(-2)),
-       Val("(i-12)/4", -2),
-       Val("-11%4", big.NewInt(-3)),
-       Val("(i-12)%4", -3),
-       Val("-11>>2", big.NewInt(-3)),
-       Val("(i-12)>>2", -3),
-       Val("-11&3", big.NewInt(1)),
-       Val("(i-12)&3", 1),
-
-       // TODO(austin) Test bit ops
-
-       // For shift, we try nearly every combination of positive
-       // ideal int, negative ideal int, big ideal int, ideal
-       // fractional float, ideal non-fractional float, int, uint,
-       // and float.
-       Val("2<<2", big.NewInt(2<<2)),
-       CErr("2<<(-1)", constantUnderflows),
-       CErr("2<<0x10000000000000000", constantOverflows),
-       CErr("2<<2.5", constantTruncated),
-       Val("2<<2.0", big.NewInt(2<<2.0)),
-       CErr("2<<i", mustBeUnsigned),
-       Val("2<<u", 2<<1),
-       CErr("2<<f", opTypes),
-
-       Val("-2<<2", big.NewInt(-2<<2)),
-       CErr("-2<<(-1)", constantUnderflows),
-       CErr("-2<<0x10000000000000000", constantOverflows),
-       CErr("-2<<2.5", constantTruncated),
-       Val("-2<<2.0", big.NewInt(-2<<2.0)),
-       CErr("-2<<i", mustBeUnsigned),
-       Val("-2<<u", -2<<1),
-       CErr("-2<<f", opTypes),
-
-       Val("0x10000000000000000<<2", new(big.Int).Lsh(hugeInteger, 2)),
-       CErr("0x10000000000000000<<(-1)", constantUnderflows),
-       CErr("0x10000000000000000<<0x10000000000000000", constantOverflows),
-       CErr("0x10000000000000000<<2.5", constantTruncated),
-       Val("0x10000000000000000<<2.0", new(big.Int).Lsh(hugeInteger, 2)),
-       CErr("0x10000000000000000<<i", mustBeUnsigned),
-       CErr("0x10000000000000000<<u", constantOverflows),
-       CErr("0x10000000000000000<<f", opTypes),
-
-       CErr("2.5<<2", opTypes),
-       CErr("2.0<<2", opTypes),
-
-       Val("i<<2", 1<<2),
-       CErr("i<<(-1)", constantUnderflows),
-       CErr("i<<0x10000000000000000", constantOverflows),
-       CErr("i<<2.5", constantTruncated),
-       Val("i<<2.0", 1<<2),
-       CErr("i<<i", mustBeUnsigned),
-       Val("i<<u", 1<<1),
-       CErr("i<<f", opTypes),
-       Val("i<<u", 1<<1),
-
-       Val("u<<2", uint(1<<2)),
-       CErr("u<<(-1)", constantUnderflows),
-       CErr("u<<0x10000000000000000", constantOverflows),
-       CErr("u<<2.5", constantTruncated),
-       Val("u<<2.0", uint(1<<2)),
-       CErr("u<<i", mustBeUnsigned),
-       Val("u<<u", uint(1<<1)),
-       CErr("u<<f", opTypes),
-       Val("u<<u", uint(1<<1)),
-
-       CErr("f<<2", opTypes),
-
-       // <, <=, >, >=
-       Val("1<2", 1 < 2),
-       Val("1<=2", 1 <= 2),
-       Val("2<=2", 2 <= 2),
-       Val("1>2", 1 > 2),
-       Val("1>=2", 1 >= 2),
-       Val("2>=2", 2 >= 2),
-
-       Val("i<2", 1 < 2),
-       Val("i<=2", 1 <= 2),
-       Val("i+1<=2", 2 <= 2),
-       Val("i>2", 1 > 2),
-       Val("i>=2", 1 >= 2),
-       Val("i+1>=2", 2 >= 2),
-
-       Val("u<2", 1 < 2),
-       Val("f<2", 1 < 2),
-
-       Val("s<\"b\"", true),
-       Val("s<\"a\"", false),
-       Val("s<=\"abc\"", true),
-       Val("s>\"aa\"", true),
-       Val("s>\"ac\"", false),
-       Val("s>=\"abc\"", true),
-
-       CErr("i<u", opTypes),
-       CErr("i<f", opTypes),
-       CErr("i<s", opTypes),
-       CErr("&i<&i", opTypes),
-       CErr("ai<ai", opTypes),
-
-       // ==, !=
-       Val("1==1", true),
-       Val("1!=1", false),
-       Val("1==2", false),
-       Val("1!=2", true),
-
-       Val("1.0==1", true),
-       Val("1.5==1", false),
-
-       Val("i==1", true),
-       Val("i!=1", false),
-       Val("i==2", false),
-       Val("i!=2", true),
-
-       Val("u==1", true),
-       Val("f==1", true),
-
-       Val("s==\"abc\"", true),
-       Val("s!=\"abc\"", false),
-       Val("s==\"abcd\"", false),
-       Val("s!=\"abcd\"", true),
-
-       Val("&i==&i", true),
-       Val("&i==&i2", false),
-
-       Val("fn==fn", true),
-       Val("fn==func(int)int{return 0}", false),
-
-       CErr("i==u", opTypes),
-       CErr("i==f", opTypes),
-       CErr("&i==&f", opTypes),
-       CErr("ai==ai", opTypes),
-       CErr("t==t", opTypes),
-       CErr("fn==oneTwo", opTypes),
-}
-
-func TestExpr(t *testing.T) { runTests(t, "exprTests", exprTests) }
diff --git a/src/pkg/exp/eval/func.go b/src/pkg/exp/eval/func.go
deleted file mode 100644 (file)
index cb1b579..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import "os"
-
-/*
- * Virtual machine
- */
-
-type Thread struct {
-       abort chan os.Error
-       pc    uint
-       // The execution frame of this function.  This remains the
-       // same throughout a function invocation.
-       f *Frame
-}
-
-type code []func(*Thread)
-
-func (i code) exec(t *Thread) {
-       opc := t.pc
-       t.pc = 0
-       l := uint(len(i))
-       for t.pc < l {
-               pc := t.pc
-               t.pc++
-               i[pc](t)
-       }
-       t.pc = opc
-}
-
-/*
- * Code buffer
- */
-
-type codeBuf struct {
-       instrs code
-}
-
-func newCodeBuf() *codeBuf { return &codeBuf{make(code, 0, 16)} }
-
-func (b *codeBuf) push(instr func(*Thread)) {
-       b.instrs = append(b.instrs, instr)
-}
-
-func (b *codeBuf) nextPC() uint { return uint(len(b.instrs)) }
-
-func (b *codeBuf) get() code {
-       // Freeze this buffer into an array of exactly the right size
-       a := make(code, len(b.instrs))
-       copy(a, b.instrs)
-       return code(a)
-}
-
-/*
- * User-defined functions
- */
-
-type evalFunc struct {
-       outer     *Frame
-       frameSize int
-       code      code
-}
-
-func (f *evalFunc) NewFrame() *Frame { return f.outer.child(f.frameSize) }
-
-func (f *evalFunc) Call(t *Thread) { f.code.exec(t) }
diff --git a/src/pkg/exp/eval/gen.go b/src/pkg/exp/eval/gen.go
deleted file mode 100644 (file)
index 1e00bdc..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-// generate operator implementations
-
-import (
-       "log"
-       "os"
-       "template"
-)
-
-type Op struct {
-       Name        string
-       Expr        string
-       Body        string // overrides Expr
-       ConstExpr   string
-       AsRightName string
-       ReturnType  string
-       Types       []*Type
-}
-
-type Size struct {
-       Bits  int
-       Sized string
-}
-
-type Type struct {
-       Repr      string
-       Value     string
-       Native    string
-       As        string
-       IsIdeal   bool
-       HasAssign bool
-       Sizes     []Size
-}
-
-var (
-       boolType = &Type{Repr: "*boolType", Value: "BoolValue", Native: "bool", As: "asBool"}
-       uintType = &Type{Repr: "*uintType", Value: "UintValue", Native: "uint64", As: "asUint",
-               Sizes: []Size{{8, "uint8"}, {16, "uint16"}, {32, "uint32"}, {64, "uint64"}, {0, "uint"}},
-       }
-       intType = &Type{Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt",
-               Sizes: []Size{{8, "int8"}, {16, "int16"}, {32, "int32"}, {64, "int64"}, {0, "int"}},
-       }
-       idealIntType = &Type{Repr: "*idealIntType", Value: "IdealIntValue", Native: "*big.Int", As: "asIdealInt", IsIdeal: true}
-       floatType    = &Type{Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat",
-               Sizes: []Size{{32, "float32"}, {64, "float64"}},
-       }
-       idealFloatType = &Type{Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*big.Rat", As: "asIdealFloat", IsIdeal: true}
-       stringType     = &Type{Repr: "*stringType", Value: "StringValue", Native: "string", As: "asString"}
-       arrayType      = &Type{Repr: "*ArrayType", Value: "ArrayValue", Native: "ArrayValue", As: "asArray", HasAssign: true}
-       structType     = &Type{Repr: "*StructType", Value: "StructValue", Native: "StructValue", As: "asStruct", HasAssign: true}
-       ptrType        = &Type{Repr: "*PtrType", Value: "PtrValue", Native: "Value", As: "asPtr"}
-       funcType       = &Type{Repr: "*FuncType", Value: "FuncValue", Native: "Func", As: "asFunc"}
-       sliceType      = &Type{Repr: "*SliceType", Value: "SliceValue", Native: "Slice", As: "asSlice"}
-       mapType        = &Type{Repr: "*MapType", Value: "MapValue", Native: "Map", As: "asMap"}
-
-       all = []*Type{
-               boolType,
-               uintType,
-               intType,
-               idealIntType,
-               floatType,
-               idealFloatType,
-               stringType,
-               arrayType,
-               structType,
-               ptrType,
-               funcType,
-               sliceType,
-               mapType,
-       }
-       bools     = all[0:1]
-       integers  = all[1:4]
-       shiftable = all[1:3]
-       numbers   = all[1:6]
-       addable   = all[1:7]
-       cmpable   = []*Type{
-               boolType,
-               uintType,
-               intType,
-               idealIntType,
-               floatType,
-               idealFloatType,
-               stringType,
-               ptrType,
-               funcType,
-               mapType,
-       }
-)
-
-var unOps = []Op{
-       {Name: "Neg", Expr: "-v", ConstExpr: "val.Neg(val)", Types: numbers},
-       {Name: "Not", Expr: "!v", Types: bools},
-       {Name: "Xor", Expr: "^v", ConstExpr: "val.Not(val)", Types: integers},
-}
-
-var binOps = []Op{
-       {Name: "Add", Expr: "l + r", ConstExpr: "l.Add(l, r)", Types: addable},
-       {Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(l, r)", Types: numbers},
-       {Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(l, r)", Types: numbers},
-       {Name: "Quo",
-               Body:      "if r == 0 { t.Abort(DivByZeroError{}) }; ret =  l / r",
-               ConstExpr: "l.Quo(l, r)",
-               Types:     numbers,
-       },
-       {Name: "Rem",
-               Body:      "if r == 0 { t.Abort(DivByZeroError{}) }; ret = l % r",
-               ConstExpr: "l.Rem(l, r)",
-               Types:     integers,
-       },
-       {Name: "And", Expr: "l & r", ConstExpr: "l.And(l, r)", Types: integers},
-       {Name: "Or", Expr: "l | r", ConstExpr: "l.Or(l, r)", Types: integers},
-       {Name: "Xor", Expr: "l ^ r", ConstExpr: "l.Xor(l, r)", Types: integers},
-       {Name: "AndNot", Expr: "l &^ r", ConstExpr: "l.AndNot(l, r)", Types: integers},
-       {Name: "Shl", Expr: "l << r", ConstExpr: "l.Lsh(l, uint(r.Value()))",
-               AsRightName: "asUint", Types: shiftable,
-       },
-       {Name: "Shr", Expr: "l >> r", ConstExpr: "new(big.Int).Rsh(l, uint(r.Value()))",
-               AsRightName: "asUint", Types: shiftable,
-       },
-       {Name: "Lss", Expr: "l < r", ConstExpr: "l.Cmp(r) < 0", ReturnType: "bool", Types: addable},
-       {Name: "Gtr", Expr: "l > r", ConstExpr: "l.Cmp(r) > 0", ReturnType: "bool", Types: addable},
-       {Name: "Leq", Expr: "l <= r", ConstExpr: "l.Cmp(r) <= 0", ReturnType: "bool", Types: addable},
-       {Name: "Geq", Expr: "l >= r", ConstExpr: "l.Cmp(r) >= 0", ReturnType: "bool", Types: addable},
-       {Name: "Eql", Expr: "l == r", ConstExpr: "l.Cmp(r) == 0", ReturnType: "bool", Types: cmpable},
-       {Name: "Neq", Expr: "l != r", ConstExpr: "l.Cmp(r) != 0", ReturnType: "bool", Types: cmpable},
-}
-
-type Data struct {
-       UnaryOps  []Op
-       BinaryOps []Op
-       Types     []*Type
-}
-
-var data = Data{
-       unOps,
-       binOps,
-       all,
-}
-
-const templateStr = `
-// This file is machine generated by gen.go.
-// 6g gen.go && 6l gen.6 && ./6.out >expr1.go
-
-package eval
-
-import (
-       "big"
-       "log"
-)
-
-/*
- * "As" functions.  These retrieve evaluator functions from an
- * expr, panicking if the requested evaluator has the wrong type.
- */
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-func (a *expr) ยซAsยป() (func() ยซNativeยป) {
-       return a.eval.(func()(ยซNativeยป))
-}
-ยซ.orยป
-func (a *expr) ยซAsยป() (func(*Thread) ยซNativeยป) {
-       return a.eval.(func(*Thread)(ยซNativeยป))
-}
-ยซ.endยป
-ยซ.endยป
-func (a *expr) asMulti() (func(*Thread) []Value) {
-       return a.eval.(func(*Thread)[]Value)
-}
-
-func (a *expr) asInterface() (func(*Thread) interface{}) {
-       switch sf := a.eval.(type) {
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-       case func()ยซNativeยป:
-               return func(*Thread) interface{} { return sf() }
-ยซ.orยป
-       case func(t *Thread)ยซNativeยป:
-               return func(t *Thread) interface{} { return sf(t) }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected expression node type %T at %v", a.eval, a.pos)
-       }
-       panic("fail")
-}
-
-/*
- * Operator generators.
- */
-
-func (a *expr) genConstant(v Value) {
-       switch a.t.lit().(type) {
-ยซ.repeated section Typesยป
-       case ยซReprยป:
-ยซ.section IsIdealยป
-               val := v.(ยซValueยป).Get()
-               a.eval = func() ยซNativeยป { return val }
-ยซ.orยป
-               a.eval = func(t *Thread) ยซNativeยป { return v.(ยซValueยป).Get(t) }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected constant type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genIdentOp(level, index int) {
-       a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) }
-       switch a.t.lit().(type) {
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-ยซ.orยป
-       case ยซReprยป:
-               a.eval = func(t *Thread) ยซNativeยป { return t.f.Get(level, index).(ยซValueยป).Get(t) }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected identifier type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genFuncCall(call func(t *Thread) []Value) {
-       a.exec = func(t *Thread) { call(t)}
-       switch a.t.lit().(type) {
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-ยซ.orยป
-       case ยซReprยป:
-               a.eval = func(t *Thread) ยซNativeยป { return call(t)[0].(ยซValueยป).Get(t) }
-ยซ.endยป
-ยซ.endยป
-       case *MultiType:
-               a.eval = func(t *Thread) []Value { return call(t) }
-       default:
-               log.Panicf("unexpected result type %v at %v", a.t, a.pos)
-       }
-}
-
-func (a *expr) genValue(vf func(*Thread) Value) {
-       a.evalAddr = vf
-       switch a.t.lit().(type) {
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-ยซ.orยป
-       case ยซReprยป:
-               a.eval = func(t *Thread) ยซNativeยป { return vf(t).(ยซValueยป).Get(t) }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected result type %v at %v", a.t, a.pos)
-       }
-}
-
-ยซ.repeated section UnaryOpsยป
-func (a *expr) genUnaryOpยซNameยป(v *expr) {
-       switch a.t.lit().(type) {
-ยซ.repeated section Typesยป
-       case ยซReprยป:
-ยซ.section IsIdealยป
-               val := v.ยซAsยป()()
-               ยซConstExprยป
-               a.eval = func() ยซNativeยป { return val }
-ยซ.orยป
-               vf := v.ยซAsยป()
-               a.eval = func(t *Thread) ยซNativeยป { v := vf(t); return ยซExprยป }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected type %v at %v", a.t, a.pos)
-       }
-}
-
-ยซ.endยป
-func (a *expr) genBinOpLogAnd(l, r *expr) {
-       lf := l.asBool()
-       rf := r.asBool()
-       a.eval = func(t *Thread) bool { return lf(t) && rf(t) }
-}
-
-func (a *expr) genBinOpLogOr(l, r *expr) {
-       lf := l.asBool()
-       rf := r.asBool()
-       a.eval = func(t *Thread) bool { return lf(t) || rf(t) }
-}
-
-ยซ.repeated section BinaryOpsยป
-func (a *expr) genBinOpยซNameยป(l, r *expr) {
-       switch t := l.t.lit().(type) {
-ยซ.repeated section Typesยป
-       case ยซReprยป:
-       ยซ.section IsIdealยป
-               l := l.ยซAsยป()()
-               r := r.ยซAsยป()()
-               val := ยซConstExprยป
-               ยซ.section ReturnTypeยป
-               a.eval = func(t *Thread) ยซReturnTypeยป { return val }
-               ยซ.orยป
-               a.eval = func() ยซNativeยป { return val }
-               ยซ.endยป
-       ยซ.orยป
-               lf := l.ยซAsยป()
-               rf := r.ยซ.section AsRightNameยปยซ@ยปยซ.orยปยซAsยปยซ.endยป()
-               ยซ.section ReturnTypeยป
-               a.eval = func(t *Thread) ยซ@ยป {
-                       l, r := lf(t), rf(t)
-                       return ยซExprยป
-               }
-               ยซ.orยป
-               ยซ.section Sizesยป
-               switch t.Bits {
-               ยซ.repeated section @ยป
-               case ยซBitsยป:
-                       a.eval = func(t *Thread) ยซNativeยป {
-                               l, r := lf(t), rf(t)
-                               var ret ยซNativeยป
-                               ยซ.section Bodyยป
-                               ยซBodyยป
-                               ยซ.orยป
-                               ret = ยซExprยป
-                               ยซ.endยป
-                               return ยซNativeยป(ยซSizedยป(ret))
-                       }
-               ยซ.endยป
-               default:
-                       log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
-               }
-               ยซ.orยป
-               a.eval = func(t *Thread) ยซNativeยป {
-                       l, r := lf(t), rf(t)
-                       return ยซExprยป
-               }
-               ยซ.endยป
-               ยซ.endยป
-       ยซ.endยป
-       ยซ.endยป
-       default:
-               log.Panicf("unexpected type %v at %v", l.t, a.pos)
-       }
-}
-
-ยซ.endยป
-func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) {
-       switch lt.lit().(type) {
-ยซ.repeated section Typesยป
-ยซ.section IsIdealยป
-ยซ.orยป
-       case ยซReprยป:
-               rf := r.ยซAsยป()
-               return func(lv Value, t *Thread) { ยซ.section HasAssignยปlv.Assign(t, rf(t))ยซ.orยปlv.(ยซValueยป).Set(t, rf(t))ยซ.endยป }
-ยซ.endยป
-ยซ.endยป
-       default:
-               log.Panicf("unexpected left operand type %v at %v", lt, r.pos)
-       }
-       panic("fail")
-}
-`
-
-func main() {
-       t := template.New(nil)
-       t.SetDelims("ยซ", "ยป")
-       err := t.Parse(templateStr)
-       if err != nil {
-               log.Fatal(err)
-       }
-       err = t.Execute(os.Stdout, data)
-       if err != nil {
-               log.Fatal(err)
-       }
-}
diff --git a/src/pkg/exp/eval/main.go b/src/pkg/exp/eval/main.go
deleted file mode 100644 (file)
index d87e8f2..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-       "bufio"
-       "exp/eval"
-       "flag"
-       "go/parser"
-       "go/scanner"
-       "go/token"
-       "io/ioutil"
-       "os"
-)
-
-var fset = token.NewFileSet()
-var filename = flag.String("f", "", "file to run")
-
-func main() {
-       flag.Parse()
-       w := eval.NewWorld()
-       if *filename != "" {
-               data, err := ioutil.ReadFile(*filename)
-               if err != nil {
-                       println(err.String())
-                       os.Exit(1)
-               }
-               file, err := parser.ParseFile(fset, *filename, data, 0)
-               if err != nil {
-                       println(err.String())
-                       os.Exit(1)
-               }
-               code, err := w.CompileDeclList(fset, file.Decls)
-               if err != nil {
-                       if list, ok := err.(scanner.ErrorList); ok {
-                               for _, e := range list {
-                                       println(e.String())
-                               }
-                       } else {
-                               println(err.String())
-                       }
-                       os.Exit(1)
-               }
-               _, err = code.Run()
-               if err != nil {
-                       println(err.String())
-                       os.Exit(1)
-               }
-               code, err = w.Compile(fset, "init()")
-               if code != nil {
-                       _, err := code.Run()
-                       if err != nil {
-                               println(err.String())
-                               os.Exit(1)
-                       }
-               }
-               code, err = w.Compile(fset, "main()")
-               if err != nil {
-                       println(err.String())
-                       os.Exit(1)
-               }
-               _, err = code.Run()
-               if err != nil {
-                       println(err.String())
-                       os.Exit(1)
-               }
-               os.Exit(0)
-       }
-
-       r := bufio.NewReader(os.Stdin)
-       for {
-               print("; ")
-               line, err := r.ReadString('\n')
-               if err != nil {
-                       break
-               }
-               code, err := w.Compile(fset, line)
-               if err != nil {
-                       println(err.String())
-                       continue
-               }
-               v, err := code.Run()
-               if err != nil {
-                       println(err.String())
-                       continue
-               }
-               if v != nil {
-                       println(v.String())
-               }
-       }
-}
diff --git a/src/pkg/exp/eval/scope.go b/src/pkg/exp/eval/scope.go
deleted file mode 100644 (file)
index 66305de..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "go/token"
-       "log"
-)
-
-/*
- * Blocks and scopes
- */
-
-// A definition can be a *Variable, *Constant, or Type.
-type Def interface {
-       Pos() token.Pos
-}
-
-type Variable struct {
-       VarPos token.Pos
-       // Index of this variable in the Frame structure
-       Index int
-       // Static type of this variable
-       Type Type
-       // Value of this variable.  This is only used by Scope.NewFrame;
-       // therefore, it is useful for global scopes but cannot be used
-       // in function scopes.
-       Init Value
-}
-
-func (v *Variable) Pos() token.Pos {
-       return v.VarPos
-}
-
-type Constant struct {
-       ConstPos token.Pos
-       Type     Type
-       Value    Value
-}
-
-func (c *Constant) Pos() token.Pos {
-       return c.ConstPos
-}
-
-// A block represents a definition block in which a name may not be
-// defined more than once.
-type block struct {
-       // The block enclosing this one, including blocks in other
-       // scopes.
-       outer *block
-       // The nested block currently being compiled, or nil.
-       inner *block
-       // The Scope containing this block.
-       scope *Scope
-       // The Variables, Constants, and Types defined in this block.
-       defs map[string]Def
-       // The index of the first variable defined in this block.
-       // This must be greater than the index of any variable defined
-       // in any parent of this block within the same Scope at the
-       // time this block is entered.
-       offset int
-       // The number of Variables defined in this block.
-       numVars int
-       // If global, do not allocate new vars and consts in
-       // the frame; assume that the refs will be compiled in
-       // using defs[name].Init.
-       global bool
-}
-
-// A Scope is the compile-time analogue of a Frame, which captures
-// some subtree of blocks.
-type Scope struct {
-       // The root block of this scope.
-       *block
-       // The maximum number of variables required at any point in
-       // this Scope.  This determines the number of slots needed in
-       // Frame's created from this Scope at run-time.
-       maxVars int
-}
-
-func (b *block) enterChild() *block {
-       if b.inner != nil && b.inner.scope == b.scope {
-               log.Panic("Failed to exit child block before entering another child")
-       }
-       sub := &block{
-               outer:  b,
-               scope:  b.scope,
-               defs:   make(map[string]Def),
-               offset: b.offset + b.numVars,
-       }
-       b.inner = sub
-       return sub
-}
-
-func (b *block) exit() {
-       if b.outer == nil {
-               log.Panic("Cannot exit top-level block")
-       }
-       if b.outer.scope == b.scope {
-               if b.outer.inner != b {
-                       log.Panic("Already exited block")
-               }
-               if b.inner != nil && b.inner.scope == b.scope {
-                       log.Panic("Exit of parent block without exit of child block")
-               }
-       }
-       b.outer.inner = nil
-}
-
-func (b *block) ChildScope() *Scope {
-       if b.inner != nil && b.inner.scope == b.scope {
-               log.Panic("Failed to exit child block before entering a child scope")
-       }
-       sub := b.enterChild()
-       sub.offset = 0
-       sub.scope = &Scope{sub, 0}
-       return sub.scope
-}
-
-func (b *block) DefineVar(name string, pos token.Pos, t Type) (*Variable, Def) {
-       if prev, ok := b.defs[name]; ok {
-               return nil, prev
-       }
-       v := b.defineSlot(t, false)
-       v.VarPos = pos
-       b.defs[name] = v
-       return v, nil
-}
-
-func (b *block) DefineTemp(t Type) *Variable { return b.defineSlot(t, true) }
-
-func (b *block) defineSlot(t Type, temp bool) *Variable {
-       if b.inner != nil && b.inner.scope == b.scope {
-               log.Panic("Failed to exit child block before defining variable")
-       }
-       index := -1
-       if !b.global || temp {
-               index = b.offset + b.numVars
-               b.numVars++
-               if index >= b.scope.maxVars {
-                       b.scope.maxVars = index + 1
-               }
-       }
-       v := &Variable{token.NoPos, index, t, nil}
-       return v
-}
-
-func (b *block) DefineConst(name string, pos token.Pos, t Type, v Value) (*Constant, Def) {
-       if prev, ok := b.defs[name]; ok {
-               return nil, prev
-       }
-       c := &Constant{pos, t, v}
-       b.defs[name] = c
-       return c, nil
-}
-
-func (b *block) DefineType(name string, pos token.Pos, t Type) Type {
-       if _, ok := b.defs[name]; ok {
-               return nil
-       }
-       nt := &NamedType{pos, name, nil, true, make(map[string]Method)}
-       if t != nil {
-               nt.Complete(t)
-       }
-       b.defs[name] = nt
-       return nt
-}
-
-func (b *block) Lookup(name string) (bl *block, level int, def Def) {
-       for b != nil {
-               if d, ok := b.defs[name]; ok {
-                       return b, level, d
-               }
-               if b.outer != nil && b.scope != b.outer.scope {
-                       level++
-               }
-               b = b.outer
-       }
-       return nil, 0, nil
-}
-
-func (s *Scope) NewFrame(outer *Frame) *Frame { return outer.child(s.maxVars) }
-
-/*
- * Frames
- */
-
-type Frame struct {
-       Outer *Frame
-       Vars  []Value
-}
-
-func (f *Frame) Get(level int, index int) Value {
-       for ; level > 0; level-- {
-               f = f.Outer
-       }
-       return f.Vars[index]
-}
-
-func (f *Frame) child(numVars int) *Frame {
-       // TODO(austin) This is probably rather expensive.  All values
-       // require heap allocation and zeroing them when we execute a
-       // definition typically requires some computation.
-       return &Frame{f, make([]Value, numVars)}
-}
diff --git a/src/pkg/exp/eval/stmt.go b/src/pkg/exp/eval/stmt.go
deleted file mode 100644 (file)
index 57bf20e..0000000
+++ /dev/null
@@ -1,1299 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "log"
-       "go/ast"
-       "go/token"
-)
-
-const (
-       returnPC = ^uint(0)
-       badPC    = ^uint(1)
-)
-
-/*
- * Statement compiler
- */
-
-type stmtCompiler struct {
-       *blockCompiler
-       pos token.Pos
-       // This statement's label, or nil if it is not labeled.
-       stmtLabel *label
-}
-
-func (a *stmtCompiler) diag(format string, args ...interface{}) {
-       a.diagAt(a.pos, format, args...)
-}
-
-/*
- * Flow checker
- */
-
-type flowEnt struct {
-       // Whether this flow entry is conditional.  If true, flow can
-       // continue to the next PC.
-       cond bool
-       // True if this will terminate flow (e.g., a return statement).
-       // cond must be false and jumps must be nil if this is true.
-       term bool
-       // PC's that can be reached from this flow entry.
-       jumps []*uint
-       // Whether this flow entry has been visited by reachesEnd.
-       visited bool
-}
-
-type flowBlock struct {
-       // If this is a goto, the target label.
-       target string
-       // The inner-most block containing definitions.
-       block *block
-       // The numVars from each block leading to the root of the
-       // scope, starting at block.
-       numVars []int
-}
-
-type flowBuf struct {
-       cb *codeBuf
-       // ents is a map from PC's to flow entries.  Any PC missing
-       // from this map is assumed to reach only PC+1.
-       ents map[uint]*flowEnt
-       // gotos is a map from goto positions to information on the
-       // block at the point of the goto.
-       gotos map[token.Pos]*flowBlock
-       // labels is a map from label name to information on the block
-       // at the point of the label.  labels are tracked by name,
-       // since multiple labels at the same PC can have different
-       // blocks.
-       labels map[string]*flowBlock
-}
-
-func newFlowBuf(cb *codeBuf) *flowBuf {
-       return &flowBuf{cb, make(map[uint]*flowEnt), make(map[token.Pos]*flowBlock), make(map[string]*flowBlock)}
-}
-
-// put creates a flow control point for the next PC in the code buffer.
-// This should be done before pushing the instruction into the code buffer.
-func (f *flowBuf) put(cond bool, term bool, jumps []*uint) {
-       pc := f.cb.nextPC()
-       if ent, ok := f.ents[pc]; ok {
-               log.Panicf("Flow entry already exists at PC %d: %+v", pc, ent)
-       }
-       f.ents[pc] = &flowEnt{cond, term, jumps, false}
-}
-
-// putTerm creates a flow control point at the next PC that
-// unconditionally terminates execution.
-func (f *flowBuf) putTerm() { f.put(false, true, nil) }
-
-// put1 creates a flow control point at the next PC that jumps to one
-// PC and, if cond is true, can also continue to the PC following the
-// next PC.
-func (f *flowBuf) put1(cond bool, jumpPC *uint) {
-       f.put(cond, false, []*uint{jumpPC})
-}
-
-func newFlowBlock(target string, b *block) *flowBlock {
-       // Find the inner-most block containing definitions
-       for b.numVars == 0 && b.outer != nil && b.outer.scope == b.scope {
-               b = b.outer
-       }
-
-       // Count parents leading to the root of the scope
-       n := 0
-       for bp := b; bp.scope == b.scope; bp = bp.outer {
-               n++
-       }
-
-       // Capture numVars from each block to the root of the scope
-       numVars := make([]int, n)
-       i := 0
-       for bp := b; i < n; bp = bp.outer {
-               numVars[i] = bp.numVars
-               i++
-       }
-
-       return &flowBlock{target, b, numVars}
-}
-
-// putGoto captures the block at a goto statement.  This should be
-// called in addition to putting a flow control point.
-func (f *flowBuf) putGoto(pos token.Pos, target string, b *block) {
-       f.gotos[pos] = newFlowBlock(target, b)
-}
-
-// putLabel captures the block at a label.
-func (f *flowBuf) putLabel(name string, b *block) {
-       f.labels[name] = newFlowBlock("", b)
-}
-
-// reachesEnd returns true if the end of f's code buffer can be
-// reached from the given program counter.  Error reporting is the
-// caller's responsibility.
-func (f *flowBuf) reachesEnd(pc uint) bool {
-       endPC := f.cb.nextPC()
-       if pc > endPC {
-               log.Panicf("Reached bad PC %d past end PC %d", pc, endPC)
-       }
-
-       for ; pc < endPC; pc++ {
-               ent, ok := f.ents[pc]
-               if !ok {
-                       continue
-               }
-
-               if ent.visited {
-                       return false
-               }
-               ent.visited = true
-
-               if ent.term {
-                       return false
-               }
-
-               // If anything can reach the end, we can reach the end
-               // from pc.
-               for _, j := range ent.jumps {
-                       if f.reachesEnd(*j) {
-                               return true
-                       }
-               }
-               // If the jump was conditional, we can reach the next
-               // PC, so try reaching the end from it.
-               if ent.cond {
-                       continue
-               }
-               return false
-       }
-       return true
-}
-
-// gotosObeyScopes returns true if no goto statement causes any
-// variables to come into scope that were not in scope at the point of
-// the goto.  Reports any errors using the given compiler.
-func (f *flowBuf) gotosObeyScopes(a *compiler) {
-       for pos, src := range f.gotos {
-               tgt := f.labels[src.target]
-
-               // The target block must be a parent of this block
-               numVars := src.numVars
-               b := src.block
-               for len(numVars) > 0 && b != tgt.block {
-                       b = b.outer
-                       numVars = numVars[1:]
-               }
-               if b != tgt.block {
-                       // We jumped into a deeper block
-                       a.diagAt(pos, "goto causes variables to come into scope")
-                       return
-               }
-
-               // There must be no variables in the target block that
-               // did not exist at the jump
-               tgtNumVars := tgt.numVars
-               for i := range numVars {
-                       if tgtNumVars[i] > numVars[i] {
-                               a.diagAt(pos, "goto causes variables to come into scope")
-                               return
-                       }
-               }
-       }
-}
-
-/*
- * Statement generation helpers
- */
-
-func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
-       v, prev := a.block.DefineVar(ident.Name, ident.Pos(), t)
-       if prev != nil {
-               if prev.Pos().IsValid() {
-                       a.diagAt(ident.Pos(), "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name, a.fset.Position(prev.Pos()))
-               } else {
-                       a.diagAt(ident.Pos(), "variable %s redeclared in this block", ident.Name)
-               }
-               return nil
-       }
-
-       // Initialize the variable
-       index := v.Index
-       if v.Index >= 0 {
-               a.push(func(v *Thread) { v.f.Vars[index] = t.Zero() })
-       }
-       return v
-}
-
-// TODO(austin) Move doAssign to here
-
-/*
- * Statement compiler
- */
-
-func (a *stmtCompiler) compile(s ast.Stmt) {
-       if a.block.inner != nil {
-               log.Panic("Child scope still entered")
-       }
-
-       notimpl := false
-       switch s := s.(type) {
-       case *ast.BadStmt:
-               // Error already reported by parser.
-               a.silentErrors++
-
-       case *ast.DeclStmt:
-               a.compileDeclStmt(s)
-
-       case *ast.EmptyStmt:
-               // Do nothing.
-
-       case *ast.LabeledStmt:
-               a.compileLabeledStmt(s)
-
-       case *ast.ExprStmt:
-               a.compileExprStmt(s)
-
-       case *ast.IncDecStmt:
-               a.compileIncDecStmt(s)
-
-       case *ast.AssignStmt:
-               a.compileAssignStmt(s)
-
-       case *ast.GoStmt:
-               notimpl = true
-
-       case *ast.DeferStmt:
-               notimpl = true
-
-       case *ast.ReturnStmt:
-               a.compileReturnStmt(s)
-
-       case *ast.BranchStmt:
-               a.compileBranchStmt(s)
-
-       case *ast.BlockStmt:
-               a.compileBlockStmt(s)
-
-       case *ast.IfStmt:
-               a.compileIfStmt(s)
-
-       case *ast.CaseClause:
-               a.diag("case clause outside switch")
-
-       case *ast.SwitchStmt:
-               a.compileSwitchStmt(s)
-
-       case *ast.TypeSwitchStmt:
-               notimpl = true
-
-       case *ast.CommClause:
-               notimpl = true
-
-       case *ast.SelectStmt:
-               notimpl = true
-
-       case *ast.ForStmt:
-               a.compileForStmt(s)
-
-       case *ast.RangeStmt:
-               notimpl = true
-
-       default:
-               log.Panicf("unexpected ast node type %T", s)
-       }
-
-       if notimpl {
-               a.diag("%T statement node not implemented", s)
-       }
-
-       if a.block.inner != nil {
-               log.Panic("Forgot to exit child scope")
-       }
-}
-
-func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) {
-       switch decl := s.Decl.(type) {
-       case *ast.BadDecl:
-               // Do nothing.  Already reported by parser.
-               a.silentErrors++
-
-       case *ast.FuncDecl:
-               if !a.block.global {
-                       log.Panic("FuncDecl at statement level")
-               }
-
-       case *ast.GenDecl:
-               if decl.Tok == token.IMPORT && !a.block.global {
-                       log.Panic("import at statement level")
-               }
-
-       default:
-               log.Panicf("Unexpected Decl type %T", s.Decl)
-       }
-       a.compileDecl(s.Decl)
-}
-
-func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) {
-       for _, spec := range decl.Specs {
-               spec := spec.(*ast.ValueSpec)
-               if spec.Values == nil {
-                       // Declaration without assignment
-                       if spec.Type == nil {
-                               // Parser should have caught
-                               log.Panic("Type and Values nil")
-                       }
-                       t := a.compileType(a.block, spec.Type)
-                       // Define placeholders even if type compile failed
-                       for _, n := range spec.Names {
-                               a.defineVar(n, t)
-                       }
-               } else {
-                       // Declaration with assignment
-                       lhs := make([]ast.Expr, len(spec.Names))
-                       for i, n := range spec.Names {
-                               lhs[i] = n
-                       }
-                       a.doAssign(lhs, spec.Values, decl.Tok, spec.Type)
-               }
-       }
-}
-
-func (a *stmtCompiler) compileDecl(decl ast.Decl) {
-       switch d := decl.(type) {
-       case *ast.BadDecl:
-               // Do nothing.  Already reported by parser.
-               a.silentErrors++
-
-       case *ast.FuncDecl:
-               decl := a.compileFuncType(a.block, d.Type)
-               if decl == nil {
-                       return
-               }
-               // Declare and initialize v before compiling func
-               // so that body can refer to itself.
-               c, prev := a.block.DefineConst(d.Name.Name, a.pos, decl.Type, decl.Type.Zero())
-               if prev != nil {
-                       pos := prev.Pos()
-                       if pos.IsValid() {
-                               a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name, a.fset.Position(pos))
-                       } else {
-                               a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block", d.Name.Name)
-                       }
-               }
-               fn := a.compileFunc(a.block, decl, d.Body)
-               if c == nil || fn == nil {
-                       return
-               }
-               var zeroThread Thread
-               c.Value.(FuncValue).Set(nil, fn(&zeroThread))
-
-       case *ast.GenDecl:
-               switch d.Tok {
-               case token.IMPORT:
-                       log.Panicf("%v not implemented", d.Tok)
-               case token.CONST:
-                       log.Panicf("%v not implemented", d.Tok)
-               case token.TYPE:
-                       a.compileTypeDecl(a.block, d)
-               case token.VAR:
-                       a.compileVarDecl(d)
-               }
-
-       default:
-               log.Panicf("Unexpected Decl type %T", decl)
-       }
-}
-
-func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) {
-       // Define label
-       l, ok := a.labels[s.Label.Name]
-       if ok {
-               if l.resolved.IsValid() {
-                       a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name, a.fset.Position(l.resolved))
-               }
-       } else {
-               pc := badPC
-               l = &label{name: s.Label.Name, gotoPC: &pc}
-               a.labels[l.name] = l
-       }
-       l.desc = "regular label"
-       l.resolved = s.Pos()
-
-       // Set goto PC
-       *l.gotoPC = a.nextPC()
-
-       // Define flow entry so we can check for jumps over declarations.
-       a.flow.putLabel(l.name, a.block)
-
-       // Compile the statement.  Reuse our stmtCompiler for simplicity.
-       sc := &stmtCompiler{a.blockCompiler, s.Stmt.Pos(), l}
-       sc.compile(s.Stmt)
-}
-
-func (a *stmtCompiler) compileExprStmt(s *ast.ExprStmt) {
-       bc := a.enterChild()
-       defer bc.exit()
-
-       e := a.compileExpr(bc.block, false, s.X)
-       if e == nil {
-               return
-       }
-
-       if e.exec == nil {
-               a.diag("%s cannot be used as expression statement", e.desc)
-               return
-       }
-
-       a.push(e.exec)
-}
-
-func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
-       // Create temporary block for extractEffect
-       bc := a.enterChild()
-       defer bc.exit()
-
-       l := a.compileExpr(bc.block, false, s.X)
-       if l == nil {
-               return
-       }
-
-       if l.evalAddr == nil {
-               l.diag("cannot assign to %s", l.desc)
-               return
-       }
-       if !(l.t.isInteger() || l.t.isFloat()) {
-               l.diagOpType(s.Tok, l.t)
-               return
-       }
-
-       var op token.Token
-       var desc string
-       switch s.Tok {
-       case token.INC:
-               op = token.ADD
-               desc = "increment statement"
-       case token.DEC:
-               op = token.SUB
-               desc = "decrement statement"
-       default:
-               log.Panicf("Unexpected IncDec token %v", s.Tok)
-       }
-
-       effect, l := l.extractEffect(bc.block, desc)
-
-       one := l.newExpr(IdealIntType, "constant")
-       one.pos = s.Pos()
-       one.eval = func() *big.Int { return big.NewInt(1) }
-
-       binop := l.compileBinaryExpr(op, l, one)
-       if binop == nil {
-               return
-       }
-
-       assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "")
-       if assign == nil {
-               log.Panicf("compileAssign type check failed")
-       }
-
-       lf := l.evalAddr
-       a.push(func(v *Thread) {
-               effect(v)
-               assign(lf(v), v)
-       })
-}
-
-func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, declTypeExpr ast.Expr) {
-       nerr := a.numError()
-
-       // Compile right side first so we have the types when
-       // compiling the left side and so we don't see definitions
-       // made on the left side.
-       rs := make([]*expr, len(rhs))
-       for i, re := range rhs {
-               rs[i] = a.compileExpr(a.block, false, re)
-       }
-
-       errOp := "assignment"
-       if tok == token.DEFINE || tok == token.VAR {
-               errOp = "declaration"
-       }
-       ac, ok := a.checkAssign(a.pos, rs, errOp, "value")
-       ac.allowMapForms(len(lhs))
-
-       // If this is a definition and the LHS is too big, we won't be
-       // able to produce the usual error message because we can't
-       // begin to infer the types of the LHS.
-       if (tok == token.DEFINE || tok == token.VAR) && len(lhs) > len(ac.rmt.Elems) {
-               a.diag("not enough values for definition")
-       }
-
-       // Compile left type if there is one
-       var declType Type
-       if declTypeExpr != nil {
-               declType = a.compileType(a.block, declTypeExpr)
-       }
-
-       // Compile left side
-       ls := make([]*expr, len(lhs))
-       nDefs := 0
-       for i, le := range lhs {
-               // If this is a definition, get the identifier and its type
-               var ident *ast.Ident
-               var lt Type
-               switch tok {
-               case token.DEFINE:
-                       // Check that it's an identifier
-                       ident, ok = le.(*ast.Ident)
-                       if !ok {
-                               a.diagAt(le.Pos(), "left side of := must be a name")
-                               // Suppress new definitions errors
-                               nDefs++
-                               continue
-                       }
-
-                       // Is this simply an assignment?
-                       if _, ok := a.block.defs[ident.Name]; ok {
-                               ident = nil
-                               break
-                       }
-                       nDefs++
-
-               case token.VAR:
-                       ident = le.(*ast.Ident)
-               }
-
-               // If it's a definition, get or infer its type.
-               if ident != nil {
-                       // Compute the identifier's type from the RHS
-                       // type.  We use the computed MultiType so we
-                       // don't have to worry about unpacking.
-                       switch {
-                       case declTypeExpr != nil:
-                               // We have a declaration type, use it.
-                               // If declType is nil, we gave an
-                               // error when we compiled it.
-                               lt = declType
-
-                       case i >= len(ac.rmt.Elems):
-                               // Define a placeholder.  We already
-                               // gave the "not enough" error above.
-                               lt = nil
-
-                       case ac.rmt.Elems[i] == nil:
-                               // We gave the error when we compiled
-                               // the RHS.
-                               lt = nil
-
-                       case ac.rmt.Elems[i].isIdeal():
-                               // If the type is absent and the
-                               // corresponding expression is a
-                               // constant expression of ideal
-                               // integer or ideal float type, the
-                               // type of the declared variable is
-                               // int or float respectively.
-                               switch {
-                               case ac.rmt.Elems[i].isInteger():
-                                       lt = IntType
-                               case ac.rmt.Elems[i].isFloat():
-                                       lt = Float64Type
-                               default:
-                                       log.Panicf("unexpected ideal type %v", rs[i].t)
-                               }
-
-                       default:
-                               lt = ac.rmt.Elems[i]
-                       }
-               }
-
-               // If it's a definition, define the identifier
-               if ident != nil {
-                       if a.defineVar(ident, lt) == nil {
-                               continue
-                       }
-               }
-
-               // Compile LHS
-               ls[i] = a.compileExpr(a.block, false, le)
-               if ls[i] == nil {
-                       continue
-               }
-
-               if ls[i].evalMapValue != nil {
-                       // Map indexes are not generally addressable,
-                       // but they are assignable.
-                       //
-                       // TODO(austin) Now that the expression
-                       // compiler uses semantic values, this might
-                       // be easier to implement as a function call.
-                       sub := ls[i]
-                       ls[i] = ls[i].newExpr(sub.t, sub.desc)
-                       ls[i].evalMapValue = sub.evalMapValue
-                       mvf := sub.evalMapValue
-                       et := sub.t
-                       ls[i].evalAddr = func(t *Thread) Value {
-                               m, k := mvf(t)
-                               e := m.Elem(t, k)
-                               if e == nil {
-                                       e = et.Zero()
-                                       m.SetElem(t, k, e)
-                               }
-                               return e
-                       }
-               } else if ls[i].evalAddr == nil {
-                       ls[i].diag("cannot assign to %s", ls[i].desc)
-                       continue
-               }
-       }
-
-       // A short variable declaration may redeclare variables
-       // provided they were originally declared in the same block
-       // with the same type, and at least one of the variables is
-       // new.
-       if tok == token.DEFINE && nDefs == 0 {
-               a.diag("at least one new variable must be declared")
-               return
-       }
-
-       // If there have been errors, our arrays are full of nil's so
-       // get out of here now.
-       if nerr != a.numError() {
-               return
-       }
-
-       // Check for 'a[x] = r, ok'
-       if len(ls) == 1 && len(rs) == 2 && ls[0].evalMapValue != nil {
-               a.diag("a[x] = r, ok form not implemented")
-               return
-       }
-
-       // Create assigner
-       var lt Type
-       n := len(lhs)
-       if n == 1 {
-               lt = ls[0].t
-       } else {
-               lts := make([]Type, len(ls))
-               for i, l := range ls {
-                       if l != nil {
-                               lts[i] = l.t
-                       }
-               }
-               lt = NewMultiType(lts)
-       }
-       bc := a.enterChild()
-       defer bc.exit()
-       assign := ac.compile(bc.block, lt)
-       if assign == nil {
-               return
-       }
-
-       // Compile
-       if n == 1 {
-               // Don't need temporaries and can avoid []Value.
-               lf := ls[0].evalAddr
-               a.push(func(t *Thread) { assign(lf(t), t) })
-       } else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) {
-               // Don't need temporaries
-               lfs := make([]func(*Thread) Value, n)
-               for i, l := range ls {
-                       lfs[i] = l.evalAddr
-               }
-               a.push(func(t *Thread) {
-                       dest := make([]Value, n)
-                       for i, lf := range lfs {
-                               dest[i] = lf(t)
-                       }
-                       assign(multiV(dest), t)
-               })
-       } else {
-               // Need temporaries
-               lmt := lt.(*MultiType)
-               lfs := make([]func(*Thread) Value, n)
-               for i, l := range ls {
-                       lfs[i] = l.evalAddr
-               }
-               a.push(func(t *Thread) {
-                       temp := lmt.Zero().(multiV)
-                       assign(temp, t)
-                       // Copy to destination
-                       for i := 0; i < n; i++ {
-                               // TODO(austin) Need to evaluate LHS
-                               // before RHS
-                               lfs[i](t).Assign(t, temp[i])
-                       }
-               })
-       }
-}
-
-var assignOpToOp = map[token.Token]token.Token{
-       token.ADD_ASSIGN: token.ADD,
-       token.SUB_ASSIGN: token.SUB,
-       token.MUL_ASSIGN: token.MUL,
-       token.QUO_ASSIGN: token.QUO,
-       token.REM_ASSIGN: token.REM,
-
-       token.AND_ASSIGN:     token.AND,
-       token.OR_ASSIGN:      token.OR,
-       token.XOR_ASSIGN:     token.XOR,
-       token.SHL_ASSIGN:     token.SHL,
-       token.SHR_ASSIGN:     token.SHR,
-       token.AND_NOT_ASSIGN: token.AND_NOT,
-}
-
-func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
-       if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
-               a.diag("tuple assignment cannot be combined with an arithmetic operation")
-               return
-       }
-
-       // Create temporary block for extractEffect
-       bc := a.enterChild()
-       defer bc.exit()
-
-       l := a.compileExpr(bc.block, false, s.Lhs[0])
-       r := a.compileExpr(bc.block, false, s.Rhs[0])
-       if l == nil || r == nil {
-               return
-       }
-
-       if l.evalAddr == nil {
-               l.diag("cannot assign to %s", l.desc)
-               return
-       }
-
-       effect, l := l.extractEffect(bc.block, "operator-assignment")
-
-       binop := r.compileBinaryExpr(assignOpToOp[s.Tok], l, r)
-       if binop == nil {
-               return
-       }
-
-       assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "assignment", "value")
-       if assign == nil {
-               log.Panicf("compileAssign type check failed")
-       }
-
-       lf := l.evalAddr
-       a.push(func(t *Thread) {
-               effect(t)
-               assign(lf(t), t)
-       })
-}
-
-func (a *stmtCompiler) compileAssignStmt(s *ast.AssignStmt) {
-       switch s.Tok {
-       case token.ASSIGN, token.DEFINE:
-               a.doAssign(s.Lhs, s.Rhs, s.Tok, nil)
-
-       default:
-               a.doAssignOp(s)
-       }
-}
-
-func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
-       if a.fnType == nil {
-               a.diag("cannot return at the top level")
-               return
-       }
-
-       if len(s.Results) == 0 && (len(a.fnType.Out) == 0 || a.outVarsNamed) {
-               // Simple case.  Simply exit from the function.
-               a.flow.putTerm()
-               a.push(func(v *Thread) { v.pc = returnPC })
-               return
-       }
-
-       bc := a.enterChild()
-       defer bc.exit()
-
-       // Compile expressions
-       bad := false
-       rs := make([]*expr, len(s.Results))
-       for i, re := range s.Results {
-               rs[i] = a.compileExpr(bc.block, false, re)
-               if rs[i] == nil {
-                       bad = true
-               }
-       }
-       if bad {
-               return
-       }
-
-       // Create assigner
-
-       // However, if the expression list in the "return" statement
-       // is a single call to a multi-valued function, the values
-       // returned from the called function will be returned from
-       // this one.
-       assign := a.compileAssign(s.Pos(), bc.block, NewMultiType(a.fnType.Out), rs, "return", "value")
-
-       // XXX(Spec) "The result types of the current function and the
-       // called function must match."  Match is fuzzy.  It should
-       // say that they must be assignment compatible.
-
-       // Compile
-       start := len(a.fnType.In)
-       nout := len(a.fnType.Out)
-       a.flow.putTerm()
-       a.push(func(t *Thread) {
-               assign(multiV(t.f.Vars[start:start+nout]), t)
-               t.pc = returnPC
-       })
-}
-
-func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool, errOp, errCtx string) *label {
-       bc := a.blockCompiler
-       for ; bc != nil; bc = bc.parent {
-               if bc.label == nil {
-                       continue
-               }
-               l := bc.label
-               if name == nil && pred(l) {
-                       return l
-               }
-               if name != nil && l.name == name.Name {
-                       if !pred(l) {
-                               a.diag("cannot %s to %s %s", errOp, l.desc, l.name)
-                               return nil
-                       }
-                       return l
-               }
-       }
-       if name == nil {
-               a.diag("%s outside %s", errOp, errCtx)
-       } else {
-               a.diag("%s label %s not defined", errOp, name.Name)
-       }
-       return nil
-}
-
-func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
-       var pc *uint
-
-       switch s.Tok {
-       case token.BREAK:
-               l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.breakPC != nil }, "break", "for loop, switch, or select")
-               if l == nil {
-                       return
-               }
-               pc = l.breakPC
-
-       case token.CONTINUE:
-               l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop")
-               if l == nil {
-                       return
-               }
-               pc = l.continuePC
-
-       case token.GOTO:
-               l, ok := a.labels[s.Label.Name]
-               if !ok {
-                       pc := badPC
-                       l = &label{name: s.Label.Name, desc: "unresolved label", gotoPC: &pc, used: s.Pos()}
-                       a.labels[l.name] = l
-               }
-
-               pc = l.gotoPC
-               a.flow.putGoto(s.Pos(), l.name, a.block)
-
-       case token.FALLTHROUGH:
-               a.diag("fallthrough outside switch")
-               return
-
-       default:
-               log.Panicf("Unexpected branch token %v", s.Tok)
-       }
-
-       a.flow.put1(false, pc)
-       a.push(func(v *Thread) { v.pc = *pc })
-}
-
-func (a *stmtCompiler) compileBlockStmt(s *ast.BlockStmt) {
-       bc := a.enterChild()
-       bc.compileStmts(s)
-       bc.exit()
-}
-
-func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
-       // The scope of any variables declared by [the init] statement
-       // extends to the end of the "if" statement and the variables
-       // are initialized once before the statement is entered.
-       //
-       // XXX(Spec) What this really wants to say is that there's an
-       // implicit scope wrapping every if, for, and switch
-       // statement.  This is subtly different from what it actually
-       // says when there's a non-block else clause, because that
-       // else claus has to execute in a scope that is *not* the
-       // surrounding scope.
-       bc := a.enterChild()
-       defer bc.exit()
-
-       // Compile init statement, if any
-       if s.Init != nil {
-               bc.compileStmt(s.Init)
-       }
-
-       elsePC := badPC
-       endPC := badPC
-
-       // Compile condition, if any.  If there is no condition, we
-       // fall through to the body.
-       if s.Cond != nil {
-               e := bc.compileExpr(bc.block, false, s.Cond)
-               switch {
-               case e == nil:
-                       // Error reported by compileExpr
-               case !e.t.isBoolean():
-                       e.diag("'if' condition must be boolean\n\t%v", e.t)
-               default:
-                       eval := e.asBool()
-                       a.flow.put1(true, &elsePC)
-                       a.push(func(t *Thread) {
-                               if !eval(t) {
-                                       t.pc = elsePC
-                               }
-                       })
-               }
-       }
-
-       // Compile body
-       body := bc.enterChild()
-       body.compileStmts(s.Body)
-       body.exit()
-
-       // Compile else
-       if s.Else != nil {
-               // Skip over else if we executed the body
-               a.flow.put1(false, &endPC)
-               a.push(func(v *Thread) { v.pc = endPC })
-               elsePC = a.nextPC()
-               bc.compileStmt(s.Else)
-       } else {
-               elsePC = a.nextPC()
-       }
-       endPC = a.nextPC()
-}
-
-func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
-       // Create implicit scope around switch
-       bc := a.enterChild()
-       defer bc.exit()
-
-       // Compile init statement, if any
-       if s.Init != nil {
-               bc.compileStmt(s.Init)
-       }
-
-       // Compile condition, if any, and extract its effects
-       var cond *expr
-       condbc := bc.enterChild()
-       if s.Tag != nil {
-               e := condbc.compileExpr(condbc.block, false, s.Tag)
-               if e != nil {
-                       var effect func(*Thread)
-                       effect, cond = e.extractEffect(condbc.block, "switch")
-                       a.push(effect)
-               }
-       }
-
-       // Count cases
-       ncases := 0
-       hasDefault := false
-       for _, c := range s.Body.List {
-               clause, ok := c.(*ast.CaseClause)
-               if !ok {
-                       a.diagAt(clause.Pos(), "switch statement must contain case clauses")
-                       continue
-               }
-               if clause.List == nil {
-                       if hasDefault {
-                               a.diagAt(clause.Pos(), "switch statement contains more than one default case")
-                       }
-                       hasDefault = true
-               } else {
-                       ncases += len(clause.List)
-               }
-       }
-
-       // Compile case expressions
-       cases := make([]func(*Thread) bool, ncases)
-       i := 0
-       for _, c := range s.Body.List {
-               clause, ok := c.(*ast.CaseClause)
-               if !ok {
-                       continue
-               }
-               for _, v := range clause.List {
-                       e := condbc.compileExpr(condbc.block, false, v)
-                       switch {
-                       case e == nil:
-                               // Error reported by compileExpr
-                       case cond == nil && !e.t.isBoolean():
-                               a.diagAt(v.Pos(), "'case' condition must be boolean")
-                       case cond == nil:
-                               cases[i] = e.asBool()
-                       case cond != nil:
-                               // Create comparison
-                               // TOOD(austin) This produces bad error messages
-                               compare := e.compileBinaryExpr(token.EQL, cond, e)
-                               if compare != nil {
-                                       cases[i] = compare.asBool()
-                               }
-                       }
-                       i++
-               }
-       }
-
-       // Emit condition
-       casePCs := make([]*uint, ncases+1)
-       endPC := badPC
-
-       a.flow.put(false, false, casePCs)
-       a.push(func(t *Thread) {
-               for i, c := range cases {
-                       if c(t) {
-                               t.pc = *casePCs[i]
-                               return
-                       }
-               }
-               t.pc = *casePCs[ncases]
-       })
-       condbc.exit()
-
-       // Compile cases
-       i = 0
-       for _, c := range s.Body.List {
-               clause, ok := c.(*ast.CaseClause)
-               if !ok {
-                       continue
-               }
-
-               // Save jump PC's
-               pc := a.nextPC()
-               if clause.List != nil {
-                       for _ = range clause.List {
-                               casePCs[i] = &pc
-                               i++
-                       }
-               } else {
-                       // Default clause
-                       casePCs[ncases] = &pc
-               }
-
-               // Compile body
-               fall := false
-               for j, s := range clause.Body {
-                       if br, ok := s.(*ast.BranchStmt); ok && br.Tok == token.FALLTHROUGH {
-                               // println("Found fallthrough");
-                               // It may be used only as the final
-                               // non-empty statement in a case or
-                               // default clause in an expression
-                               // "switch" statement.
-                               for _, s2 := range clause.Body[j+1:] {
-                                       // XXX(Spec) 6g also considers
-                                       // empty blocks to be empty
-                                       // statements.
-                                       if _, ok := s2.(*ast.EmptyStmt); !ok {
-                                               a.diagAt(s.Pos(), "fallthrough statement must be final statement in case")
-                                               break
-                                       }
-                               }
-                               fall = true
-                       } else {
-                               bc.compileStmt(s)
-                       }
-               }
-               // Jump out of switch, unless there was a fallthrough
-               if !fall {
-                       a.flow.put1(false, &endPC)
-                       a.push(func(v *Thread) { v.pc = endPC })
-               }
-       }
-
-       // Get end PC
-       endPC = a.nextPC()
-       if !hasDefault {
-               casePCs[ncases] = &endPC
-       }
-}
-
-func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
-       // Wrap the entire for in a block.
-       bc := a.enterChild()
-       defer bc.exit()
-
-       // Compile init statement, if any
-       if s.Init != nil {
-               bc.compileStmt(s.Init)
-       }
-
-       bodyPC := badPC
-       postPC := badPC
-       checkPC := badPC
-       endPC := badPC
-
-       // Jump to condition check.  We generate slightly less code by
-       // placing the condition check after the body.
-       a.flow.put1(false, &checkPC)
-       a.push(func(v *Thread) { v.pc = checkPC })
-
-       // Compile body
-       bodyPC = a.nextPC()
-       body := bc.enterChild()
-       if a.stmtLabel != nil {
-               body.label = a.stmtLabel
-       } else {
-               body.label = &label{resolved: s.Pos()}
-       }
-       body.label.desc = "for loop"
-       body.label.breakPC = &endPC
-       body.label.continuePC = &postPC
-       body.compileStmts(s.Body)
-       body.exit()
-
-       // Compile post, if any
-       postPC = a.nextPC()
-       if s.Post != nil {
-               // TODO(austin) Does the parser disallow short
-               // declarations in s.Post?
-               bc.compileStmt(s.Post)
-       }
-
-       // Compile condition check, if any
-       checkPC = a.nextPC()
-       if s.Cond == nil {
-               // If the condition is absent, it is equivalent to true.
-               a.flow.put1(false, &bodyPC)
-               a.push(func(v *Thread) { v.pc = bodyPC })
-       } else {
-               e := bc.compileExpr(bc.block, false, s.Cond)
-               switch {
-               case e == nil:
-                       // Error reported by compileExpr
-               case !e.t.isBoolean():
-                       a.diag("'for' condition must be boolean\n\t%v", e.t)
-               default:
-                       eval := e.asBool()
-                       a.flow.put1(true, &bodyPC)
-                       a.push(func(t *Thread) {
-                               if eval(t) {
-                                       t.pc = bodyPC
-                               }
-                       })
-               }
-       }
-
-       endPC = a.nextPC()
-}
-
-/*
- * Block compiler
- */
-
-func (a *blockCompiler) compileStmt(s ast.Stmt) {
-       sc := &stmtCompiler{a, s.Pos(), nil}
-       sc.compile(s)
-}
-
-func (a *blockCompiler) compileStmts(block *ast.BlockStmt) {
-       for _, sub := range block.List {
-               a.compileStmt(sub)
-       }
-}
-
-func (a *blockCompiler) enterChild() *blockCompiler {
-       block := a.block.enterChild()
-       return &blockCompiler{
-               funcCompiler: a.funcCompiler,
-               block:        block,
-               parent:       a,
-       }
-}
-
-func (a *blockCompiler) exit() { a.block.exit() }
-
-/*
- * Function compiler
- */
-
-func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) func(*Thread) Func {
-       // Create body scope
-       //
-       // The scope of a parameter or result is the body of the
-       // corresponding function.
-       bodyScope := b.ChildScope()
-       defer bodyScope.exit()
-       for i, t := range decl.Type.In {
-               if decl.InNames[i] != nil {
-                       bodyScope.DefineVar(decl.InNames[i].Name, decl.InNames[i].Pos(), t)
-               } else {
-                       bodyScope.DefineTemp(t)
-               }
-       }
-       for i, t := range decl.Type.Out {
-               if decl.OutNames[i] != nil {
-                       bodyScope.DefineVar(decl.OutNames[i].Name, decl.OutNames[i].Pos(), t)
-               } else {
-                       bodyScope.DefineTemp(t)
-               }
-       }
-
-       // Create block context
-       cb := newCodeBuf()
-       fc := &funcCompiler{
-               compiler:     a,
-               fnType:       decl.Type,
-               outVarsNamed: len(decl.OutNames) > 0 && decl.OutNames[0] != nil,
-               codeBuf:      cb,
-               flow:         newFlowBuf(cb),
-               labels:       make(map[string]*label),
-       }
-       bc := &blockCompiler{
-               funcCompiler: fc,
-               block:        bodyScope.block,
-       }
-
-       // Compile body
-       nerr := a.numError()
-       bc.compileStmts(body)
-       fc.checkLabels()
-       if nerr != a.numError() {
-               return nil
-       }
-
-       // Check that the body returned if necessary.  We only check
-       // this if there were no errors compiling the body.
-       if len(decl.Type.Out) > 0 && fc.flow.reachesEnd(0) {
-               // XXX(Spec) Not specified.
-               a.diagAt(body.Rbrace, "function ends without a return statement")
-               return nil
-       }
-
-       code := fc.get()
-       maxVars := bodyScope.maxVars
-       return func(t *Thread) Func { return &evalFunc{t.f, maxVars, code} }
-}
-
-// Checks that labels were resolved and that all jumps obey scoping
-// rules.  Reports an error and set fc.err if any check fails.
-func (a *funcCompiler) checkLabels() {
-       nerr := a.numError()
-       for _, l := range a.labels {
-               if !l.resolved.IsValid() {
-                       a.diagAt(l.used, "label %s not defined", l.name)
-               }
-       }
-       if nerr != a.numError() {
-               // Don't check scopes if we have unresolved labels
-               return
-       }
-
-       // Executing the "goto" statement must not cause any variables
-       // to come into scope that were not already in scope at the
-       // point of the goto.
-       a.flow.gotosObeyScopes(a.compiler)
-}
diff --git a/src/pkg/exp/eval/stmt_test.go b/src/pkg/exp/eval/stmt_test.go
deleted file mode 100644 (file)
index a8a3e16..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import "testing"
-
-var atLeastOneDecl = "at least one new variable must be declared"
-
-var stmtTests = []test{
-       // Short declarations
-       Val1("x := i", "x", 1),
-       Val1("x := f", "x", 1.0),
-       // Type defaulting
-       Val1("a := 42", "a", 42),
-       Val1("a := 1.0", "a", 1.0),
-       // Parallel assignment
-       Val2("a, b := 1, 2", "a", 1, "b", 2),
-       Val2("a, i := 1, 2", "a", 1, "i", 2),
-       CErr("a, i := 1, f", opTypes),
-       CErr("a, b := 1, 2, 3", "too many"),
-       CErr("a := 1, 2", "too many"),
-       CErr("a, b := 1", "not enough"),
-       // Mixed declarations
-       CErr("i := 1", atLeastOneDecl),
-       CErr("i, u := 1, 2", atLeastOneDecl),
-       Val2("i, x := 2, f", "i", 2, "x", 1.0),
-       // Various errors
-       CErr("1 := 2", "expected identifier"),
-       CErr("c, a := 1, 1", "cannot assign"),
-       // Unpacking
-       Val2("x, y := oneTwo()", "x", 1, "y", 2),
-       CErr("x := oneTwo()", "too many"),
-       CErr("x, y, z := oneTwo()", "not enough"),
-       CErr("x, y := oneTwo(), 2", "multi-valued"),
-       CErr("x := oneTwo()+2", opTypes),
-       // TOOD(austin) This error message is weird
-       CErr("x := void()", "not enough"),
-       // Placeholders
-       CErr("x := 1+\"x\"; i=x+1", opTypes),
-
-       // Assignment
-       Val1("i = 2", "i", 2),
-       Val1("(i) = 2", "i", 2),
-       CErr("1 = 2", "cannot assign"),
-       CErr("1-1 = 2", "- expression"),
-       Val1("i = 2.0", "i", 2),
-       CErr("i = 2.2", constantTruncated),
-       CErr("u = -2", constantUnderflows),
-       CErr("i = f", opTypes),
-       CErr("i, u = 0, f", opTypes),
-       CErr("i, u = 0, f", "value 2"),
-       Val2("i, i2 = i2, i", "i", 2, "i2", 1),
-       CErr("c = 1", "cannot assign"),
-
-       Val1("x := &i; *x = 2", "i", 2),
-
-       Val1("ai[0] = 42", "ai", varray{42, 2}),
-       Val1("aai[1] = ai; ai[0] = 42", "aai", varray{varray{1, 2}, varray{1, 2}}),
-       Val1("aai = aai2", "aai", varray{varray{5, 6}, varray{7, 8}}),
-
-       // Assignment conversions
-       Run("var sl []int; sl = &ai"),
-       CErr("type ST []int; type AT *[2]int; var x AT = &ai; var y ST = x", opTypes),
-       Run("type ST []int; var y ST = &ai"),
-       Run("type AT *[2]int; var x AT = &ai; var y []int = x"),
-
-       // Op-assignment
-       Val1("i += 2", "i", 3),
-       Val("i", 1),
-       Val1("f += 2", "f", 3.0),
-       CErr("2 += 2", "cannot assign"),
-       CErr("i, j += 2", "cannot be combined"),
-       CErr("i += 2, 3", "cannot be combined"),
-       Val2("s2 := s; s += \"def\"", "s2", "abc", "s", "abcdef"),
-       CErr("s += 1", opTypes),
-       // Single evaluation
-       Val2("ai[func()int{i+=1;return 0}()] *= 3; i2 = ai[0]", "i", 2, "i2", 3),
-
-       // Type declarations
-       // Identifiers
-       Run("type T int"),
-       CErr("type T x", "undefined"),
-       CErr("type T c", "constant"),
-       CErr("type T i", "variable"),
-       CErr("type T T", "recursive"),
-       CErr("type T x; type U T; var v U; v = 1", "undefined"),
-       // Pointer types
-       Run("type T *int"),
-       Run("type T *T"),
-       // Array types
-       Run("type T [5]int"),
-       Run("type T [c+42/2]int"),
-       Run("type T [2.0]int"),
-       CErr("type T [i]int", "constant expression"),
-       CErr("type T [2.5]int", constantTruncated),
-       CErr("type T [-1]int", "negative"),
-       CErr("type T [2]T", "recursive"),
-       // Struct types
-       Run("type T struct { a int; b int }"),
-       Run("type T struct { a int; int }"),
-       Run("type T struct { x *T }"),
-       Run("type T int; type U struct { T }"),
-       CErr("type T *int; type U struct { T }", "embedded.*pointer"),
-       CErr("type T *struct { T }", "embedded.*pointer"),
-       CErr("type T struct { a int; a int }", " a .*redeclared.*:1:17"),
-       CErr("type T struct { int; int }", "int .*redeclared.*:1:17"),
-       CErr("type T struct { int int; int }", "int .*redeclared.*:1:17"),
-       Run("type T struct { x *struct { T } }"),
-       CErr("type T struct { x struct { T } }", "recursive"),
-       CErr("type T struct { x }; type U struct { T }", "undefined"),
-       // Function types
-       Run("type T func()"),
-       Run("type T func(a, b int) int"),
-       Run("type T func(a, b int) (x int, y int)"),
-       Run("type T func(a, a int) (a int, a int)"),
-       Run("type T func(a, b int) (x, y int)"),
-       Run("type T func(int, int) (int, int)"),
-       CErr("type T func(x); type U T", "undefined"),
-       CErr("type T func(a T)", "recursive"),
-       // Interface types
-       Run("type T interface {x(a, b int) int}"),
-       Run("type T interface {x(a, b int) int}; type U interface {T; y(c int)}"),
-       CErr("type T interface {x(a int); x()}", "method x redeclared"),
-       CErr("type T interface {x()}; type U interface {T; x()}", "method x redeclared"),
-       CErr("type T int; type U interface {T}", "embedded type"),
-       // Parens
-       Run("type T (int)"),
-
-       // Variable declarations
-       Val2("var x int", "i", 1, "x", 0),
-       Val1("var x = 1", "x", 1),
-       Val1("var x = 1.0", "x", 1.0),
-       Val1("var x int = 1.0", "x", 1),
-       // Placeholders
-       CErr("var x foo; x = 1", "undefined"),
-       CErr("var x foo = 1; x = 1", "undefined"),
-       // Redeclaration
-       CErr("var i, x int", " i .*redeclared"),
-       CErr("var x int; var x int", " x .*redeclared.*:1:5"),
-
-       // Expression statements
-       CErr("x := func(){ 1-1 }", "expression statement"),
-       CErr("x := func(){ 1-1 }", "- expression"),
-       Val1("fn(2)", "i", 1),
-
-       // IncDec statements
-       Val1("i++", "i", 2),
-       Val1("i--", "i", 0),
-       Val1("u++", "u", uint(2)),
-       Val1("u--", "u", uint(0)),
-       Val1("f++", "f", 2.0),
-       Val1("f--", "f", 0.0),
-       // Single evaluation
-       Val2("ai[func()int{i+=1;return 0}()]++; i2 = ai[0]", "i", 2, "i2", 2),
-       // Operand types
-       CErr("s++", opTypes),
-       CErr("s++", "'\\+\\+'"),
-       CErr("2++", "cannot assign"),
-       CErr("c++", "cannot assign"),
-
-       // Function scoping
-       Val1("fn1 := func() { i=2 }; fn1()", "i", 2),
-       Val1("fn1 := func() { i:=2 }; fn1()", "i", 1),
-       Val2("fn1 := func() int { i=2; i:=3; i=4; return i }; x := fn1()", "i", 2, "x", 4),
-
-       // Basic returns
-       CErr("fn1 := func() int {}", "return"),
-       Run("fn1 := func() {}"),
-       CErr("fn1 := func() (r int) {}", "return"),
-       Val1("fn1 := func() (r int) {return}; i = fn1()", "i", 0),
-       Val1("fn1 := func() (r int) {r = 2; return}; i = fn1()", "i", 2),
-       Val1("fn1 := func() (r int) {return 2}; i = fn1()", "i", 2),
-       Val1("fn1 := func(int) int {return 2}; i = fn1(1)", "i", 2),
-
-       // Multi-valued returns
-       Val2("fn1 := func() (bool, int) {return true, 2}; x, y := fn1()", "x", true, "y", 2),
-       CErr("fn1 := func() int {return}", "not enough values"),
-       CErr("fn1 := func() int {return 1,2}", "too many values"),
-       CErr("fn1 := func() {return 1}", "too many values"),
-       CErr("fn1 := func() (int,int,int) {return 1,2}", "not enough values"),
-       Val2("fn1 := func() (int, int) {return oneTwo()}; x, y := fn1()", "x", 1, "y", 2),
-       CErr("fn1 := func() int {return oneTwo()}", "too many values"),
-       CErr("fn1 := func() (int,int,int) {return oneTwo()}", "not enough values"),
-       Val1("fn1 := func(x,y int) int {return x+y}; x := fn1(oneTwo())", "x", 3),
-
-       // Return control flow
-       Val2("fn1 := func(x *int) bool { *x = 2; return true; *x = 3; }; x := fn1(&i)", "i", 2, "x", true),
-
-       // Break/continue/goto/fallthrough
-       CErr("break", "outside"),
-       CErr("break foo", "break.*foo.*not defined"),
-       CErr("continue", "outside"),
-       CErr("continue foo", "continue.*foo.*not defined"),
-       CErr("fallthrough", "outside"),
-       CErr("goto foo", "foo.*not defined"),
-       CErr(" foo: foo:;", "foo.*redeclared.*:1:2"),
-       Val1("i+=2; goto L; i+=4; L: i+=8", "i", 1+2+8),
-       // Return checking
-       CErr("fn1 := func() int { goto L; return 1; L: }", "return"),
-       Run("fn1 := func() int { L: goto L; i = 2 }"),
-       Run("fn1 := func() int { return 1; L: goto L }"),
-       // Scope checking
-       Run("fn1 := func() { { L: x:=1 }; goto L }"),
-       CErr("fn1 := func() { { x:=1; L: }; goto L }", "into scope"),
-       CErr("fn1 := func() { goto L; x:=1; L: }", "into scope"),
-       Run("fn1 := func() { goto L; { L: x:=1 } }"),
-       CErr("fn1 := func() { goto L; { x:=1; L: } }", "into scope"),
-
-       // Blocks
-       CErr("fn1 := func() int {{}}", "return"),
-       Val1("fn1 := func() bool { { return true } }; b := fn1()", "b", true),
-
-       // If
-       Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4),
-       Val2("if false { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
-       Val2("if i == i2 { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
-       // Omit optional parts
-       Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4),
-       Val2("if true { i = 2 }; i2 = 4", "i", 2, "i2", 4),
-       Val2("if false { i = 2 }; i2 = 4", "i", 1, "i2", 4),
-       // Init
-       Val2("if x := true; x { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4),
-       Val2("if x := false; x { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
-       // Statement else
-       Val2("if true { i = 2 } else i = 3; i2 = 4", "i", 2, "i2", 4),
-       Val2("if false { i = 2 } else i = 3; i2 = 4", "i", 3, "i2", 4),
-       // Scoping
-       Val2("if true { i := 2 } else { i := 3 }; i2 = i", "i", 1, "i2", 1),
-       Val2("if false { i := 2 } else { i := 3 }; i2 = i", "i", 1, "i2", 1),
-       Val2("if false { i := 2 } else i := 3; i2 = i", "i", 1, "i2", 1),
-       CErr("if true { x := 2 }; x = 4", undefined),
-       Val2("if i := 2; true { i2 = i; i := 3 }", "i", 1, "i2", 2),
-       Val2("if i := 2; false {} else { i2 = i; i := 3 }", "i", 1, "i2", 2),
-       // Return checking
-       Run("fn1 := func() int { if true { return 1 } else { return 2 } }"),
-       Run("fn1 := func() int { if true { return 1 } else return 2 }"),
-       CErr("fn1 := func() int { if true { return 1 } else { } }", "return"),
-       CErr("fn1 := func() int { if true { } else { return 1 } }", "return"),
-       CErr("fn1 := func() int { if true { } else return 1 }", "return"),
-       CErr("fn1 := func() int { if true { } else { } }", "return"),
-       CErr("fn1 := func() int { if true { return 1 } }", "return"),
-       CErr("fn1 := func() int { if true { } }", "return"),
-       Run("fn1 := func() int { if true { }; return 1 }"),
-       CErr("fn1 := func() int { if true { } }", "return"),
-       CErr("fn1 := func() int { if true { } else { return 2 } }", "return"),
-       Run("fn1 := func() int { if true { return 1 }; return 0 }"),
-       Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
-       Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
-
-       // Switch
-       Val1("switch { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+4),
-       Val1("switch { default: i += 2; case false: i += 4; case true: i += 8 }", "i", 1+8),
-       CErr("switch { default: i += 2; default: i += 4 }", "more than one"),
-       Val1("switch false { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+2),
-       CErr("switch s { case 1: }", opTypes),
-       CErr("switch ai { case ai: i += 2 }", opTypes),
-       Val1("switch 1.0 { case 1: i += 2; case 2: i += 4 }", "i", 1+2),
-       Val1("switch 1.5 { case 1: i += 2; case 2: i += 4 }", "i", 1),
-       CErr("switch oneTwo() {}", "multi-valued expression"),
-       Val1("switch 2 { case 1: i += 2; fallthrough; case 2: i += 4; fallthrough; case 3: i += 8; fallthrough }", "i", 1+4+8),
-       Val1("switch 5 { case 1: i += 2; fallthrough; default: i += 4; fallthrough; case 2: i += 8; fallthrough; case 3: i += 16; fallthrough }", "i", 1+4+8+16),
-       CErr("switch { case true: fallthrough; i += 2 }", "final statement"),
-       Val1("switch { case true: i += 2; fallthrough; ; ; case false: i += 4 }", "i", 1+2+4),
-       Val1("switch 2 { case 0, 1: i += 2; case 2, 3: i += 4 }", "i", 1+4),
-       Val2("switch func()int{i2++;return 5}() { case 1, 2: i += 2; case 4, 5: i += 4 }", "i", 1+4, "i2", 3),
-       Run("switch i { case i: }"),
-       // TODO(austin) Why doesn't this fail?
-       //CErr("case 1:", "XXX"),
-
-       // For
-       Val2("for x := 1; x < 5; x++ { i+=x }; i2 = 4", "i", 11, "i2", 4),
-       Val2("for x := 1; x < 5; x++ { i+=x; break; i++ }; i2 = 4", "i", 2, "i2", 4),
-       Val2("for x := 1; x < 5; x++ { i+=x; continue; i++ }; i2 = 4", "i", 11, "i2", 4),
-       Val2("for i = 2; false; i = 3 { i = 4 }; i2 = 4", "i", 2, "i2", 4),
-       Val2("for i < 5 { i++ }; i2 = 4", "i", 5, "i2", 4),
-       Val2("for i < 0 { i++ }; i2 = 4", "i", 1, "i2", 4),
-       // Scoping
-       Val2("for i := 2; true; { i2 = i; i := 3; break }", "i", 1, "i2", 2),
-       // Labeled break/continue
-       Val1("L1: for { L2: for { i+=2; break L1; i+=4 }; i+=8 }", "i", 1+2),
-       Val1("L1: for { L2: for { i+=2; break L2; i+=4 }; i+=8; break; i+=16 }", "i", 1+2+8),
-       CErr("L1: { for { break L1 } }", "break.*not defined"),
-       CErr("L1: for {}; for { break L1 }", "break.*not defined"),
-       CErr("L1:; for { break L1 }", "break.*not defined"),
-       Val2("L1: for i = 0; i < 2; i++ { L2: for { i2++; continue L1; i2++ } }", "i", 2, "i2", 4),
-       CErr("L1: { for { continue L1 } }", "continue.*not defined"),
-       CErr("L1:; for { continue L1 }", "continue.*not defined"),
-       // Return checking
-       Run("fn1 := func() int{ for {} }"),
-       CErr("fn1 := func() int{ for true {} }", "return"),
-       CErr("fn1 := func() int{ for true {return 1} }", "return"),
-       CErr("fn1 := func() int{ for {break} }", "return"),
-       Run("fn1 := func() int{ for { for {break} } }"),
-       CErr("fn1 := func() int{ L1: for { for {break L1} } }", "return"),
-       Run("fn1 := func() int{ for true {}; return 1 }"),
-
-       // Selectors
-       Val1("var x struct { a int; b int }; x.a = 42; i = x.a", "i", 42),
-       Val1("type T struct { x int }; var y struct { T }; y.x = 42; i = y.x", "i", 42),
-       Val2("type T struct { x int }; var y struct { T; x int }; y.x = 42; i = y.x; i2 = y.T.x", "i", 42, "i2", 0),
-       Run("type T struct { x int }; var y struct { *T }; a := func(){i=y.x}"),
-       CErr("type T struct { x int }; var x T; x.y = 42", "no field"),
-       CErr("type T struct { x int }; type U struct { x int }; var y struct { T; U }; y.x = 42", "ambiguous.*\tT\\.x\n\tU\\.x"),
-       CErr("type T struct { *T }; var x T; x.foo", "no field"),
-
-       Val1("fib := func(int) int{return 0;}; fib = func(v int) int { if v < 2 { return 1 }; return fib(v-1)+fib(v-2) }; i = fib(20)", "i", 10946),
-
-       // Make slice
-       Val2("x := make([]int, 2); x[0] = 42; i, i2 = x[0], x[1]", "i", 42, "i2", 0),
-       Val2("x := make([]int, 2); x[1] = 42; i, i2 = x[0], x[1]", "i", 0, "i2", 42),
-       RErr("x := make([]int, 2); x[-i] = 42", "negative index"),
-       RErr("x := make([]int, 2); x[2] = 42", "index 2 exceeds"),
-       Val2("x := make([]int, 2, 3); i, i2 = len(x), cap(x)", "i", 2, "i2", 3),
-       Val2("x := make([]int, 3, 2); i, i2 = len(x), cap(x)", "i", 3, "i2", 3),
-       RErr("x := make([]int, -i)", "negative length"),
-       RErr("x := make([]int, 2, -i)", "negative capacity"),
-       RErr("x := make([]int, 2, 3); x[2] = 42", "index 2 exceeds"),
-       CErr("x := make([]int, 2, 3, 4)", "too many"),
-       CErr("x := make([]int)", "not enough"),
-
-       // TODO(austin) Test make map
-
-       // Maps
-       Val1("x := make(map[int] int); x[1] = 42; i = x[1]", "i", 42),
-       Val2("x := make(map[int] int); x[1] = 42; i, y := x[1]", "i", 42, "y", true),
-       Val2("x := make(map[int] int); x[1] = 42; i, y := x[2]", "i", 0, "y", false),
-       // Not implemented
-       //Val1("x := make(map[int] int); x[1] = 42, true; i = x[1]", "i", 42),
-       //Val2("x := make(map[int] int); x[1] = 42; x[1] = 42, false; i, y := x[1]", "i", 0, "y", false),
-       Run("var x int; a := make(map[int] int); a[0], x = 1, 2"),
-       CErr("x := make(map[int] int); (func(a,b int){})(x[0])", "not enough"),
-       CErr("x := make(map[int] int); x[1] = oneTwo()", "too many"),
-       RErr("x := make(map[int] int); i = x[1]", "key '1' not found"),
-
-       // Functions
-       Val2("func fib(n int) int { if n <= 2 { return n }; return fib(n-1) + fib(n-2) }", "fib(4)", 5, "fib(10)", 89),
-       Run("func f1(){}"),
-       Run2("func f1(){}", "f1()"),
-}
-
-func TestStmt(t *testing.T) { runTests(t, "stmtTests", stmtTests) }
diff --git a/src/pkg/exp/eval/test.bash b/src/pkg/exp/eval/test.bash
deleted file mode 100755 (executable)
index 50b61fd..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Run the interpreter against all the Go test programs
-# that begin with the magic
-#      // $G $D/$F.go && $L $F.$A && ./$A.out
-# line and do not contain imports.
-
-set -e
-
-gomake
-6g main.go && 6l main.6
-(
-for i in $(egrep -l '// \$G (\$D/)?\$F\.go \&\& \$L \$F\.\$A && \./\$A\.out' "$GOROOT"/test/*.go "$GOROOT"/test/*/*.go)
-do
-       if grep '^import' $i >/dev/null 2>&1
-       then
-               true
-       else
-               if "$GOROOT"/usr/austin/eval/6.out -f $i >/tmp/out 2>&1 && ! test -s /tmp/out
-               then
-                       echo PASS $i
-               else
-                       echo FAIL $i
-                       (
-                               echo '>>> ' $i
-                               cat /tmp/out
-                               echo
-                       ) 1>&3
-               fi
-       fi
-done | (tee /dev/fd/2 | awk '{print $1}' | sort | uniq -c) 2>&1
-) 3>test.log
diff --git a/src/pkg/exp/eval/type.go b/src/pkg/exp/eval/type.go
deleted file mode 100644 (file)
index 8a93d8a..0000000
+++ /dev/null
@@ -1,1252 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "go/ast"
-       "go/token"
-       "log"
-       "reflect"
-       "sort"
-       "unsafe" // For Sizeof
-)
-
-
-// XXX(Spec) The type compatibility section is very confusing because
-// it makes it seem like there are three distinct types of
-// compatibility: plain compatibility, assignment compatibility, and
-// comparison compatibility.  As I understand it, there's really only
-// assignment compatibility and comparison and conversion have some
-// restrictions and have special meaning in some cases where the types
-// are not otherwise assignment compatible.  The comparison
-// compatibility section is almost all about the semantics of
-// comparison, not the type checking of it, so it would make much more
-// sense in the comparison operators section.  The compatibility and
-// assignment compatibility sections should be rolled into one.
-
-type Type interface {
-       // compat returns whether this type is compatible with another
-       // type.  If conv is false, this is normal compatibility,
-       // where two named types are compatible only if they are the
-       // same named type.  If conv if true, this is conversion
-       // compatibility, where two named types are conversion
-       // compatible if their definitions are conversion compatible.
-       //
-       // TODO(austin) Deal with recursive types
-       compat(o Type, conv bool) bool
-       // lit returns this type's literal.  If this is a named type,
-       // this is the unnamed underlying type.  Otherwise, this is an
-       // identity operation.
-       lit() Type
-       // isBoolean returns true if this is a boolean type.
-       isBoolean() bool
-       // isInteger returns true if this is an integer type.
-       isInteger() bool
-       // isFloat returns true if this is a floating type.
-       isFloat() bool
-       // isIdeal returns true if this is an ideal int or float.
-       isIdeal() bool
-       // Zero returns a new zero value of this type.
-       Zero() Value
-       // String returns the string representation of this type.
-       String() string
-       // The position where this type was defined, if any.
-       Pos() token.Pos
-}
-
-type BoundedType interface {
-       Type
-       // minVal returns the smallest value of this type.
-       minVal() *big.Rat
-       // maxVal returns the largest value of this type.
-       maxVal() *big.Rat
-}
-
-var universePos = token.NoPos
-
-/*
- * Type array maps.  These are used to memoize composite types.
- */
-
-type typeArrayMapEntry struct {
-       key  []Type
-       v    interface{}
-       next *typeArrayMapEntry
-}
-
-type typeArrayMap map[uintptr]*typeArrayMapEntry
-
-func hashTypeArray(key []Type) uintptr {
-       hash := uintptr(0)
-       for _, t := range key {
-               hash = hash * 33
-               if t == nil {
-                       continue
-               }
-               addr := reflect.ValueOf(t).Pointer()
-               hash ^= addr
-       }
-       return hash
-}
-
-func newTypeArrayMap() typeArrayMap { return make(map[uintptr]*typeArrayMapEntry) }
-
-func (m typeArrayMap) Get(key []Type) interface{} {
-       ent, ok := m[hashTypeArray(key)]
-       if !ok {
-               return nil
-       }
-
-nextEnt:
-       for ; ent != nil; ent = ent.next {
-               if len(key) != len(ent.key) {
-                       continue
-               }
-               for i := 0; i < len(key); i++ {
-                       if key[i] != ent.key[i] {
-                               continue nextEnt
-                       }
-               }
-               // Found it
-               return ent.v
-       }
-
-       return nil
-}
-
-func (m typeArrayMap) Put(key []Type, v interface{}) interface{} {
-       hash := hashTypeArray(key)
-       ent := m[hash]
-
-       new := &typeArrayMapEntry{key, v, ent}
-       m[hash] = new
-       return v
-}
-
-/*
- * Common type
- */
-
-type commonType struct{}
-
-func (commonType) isBoolean() bool { return false }
-
-func (commonType) isInteger() bool { return false }
-
-func (commonType) isFloat() bool { return false }
-
-func (commonType) isIdeal() bool { return false }
-
-func (commonType) Pos() token.Pos { return token.NoPos }
-
-/*
- * Bool
- */
-
-type boolType struct {
-       commonType
-}
-
-var BoolType = universe.DefineType("bool", universePos, &boolType{})
-
-func (t *boolType) compat(o Type, conv bool) bool {
-       _, ok := o.lit().(*boolType)
-       return ok
-}
-
-func (t *boolType) lit() Type { return t }
-
-func (t *boolType) isBoolean() bool { return true }
-
-func (boolType) String() string {
-       // Use angle brackets as a convention for printing the
-       // underlying, unnamed type.  This should only show up in
-       // debug output.
-       return "<bool>"
-}
-
-func (t *boolType) Zero() Value {
-       res := boolV(false)
-       return &res
-}
-
-/*
- * Uint
- */
-
-type uintType struct {
-       commonType
-
-       // 0 for architecture-dependent types
-       Bits uint
-       // true for uintptr, false for all others
-       Ptr  bool
-       name string
-}
-
-var (
-       Uint8Type  = universe.DefineType("uint8", universePos, &uintType{commonType{}, 8, false, "uint8"})
-       Uint16Type = universe.DefineType("uint16", universePos, &uintType{commonType{}, 16, false, "uint16"})
-       Uint32Type = universe.DefineType("uint32", universePos, &uintType{commonType{}, 32, false, "uint32"})
-       Uint64Type = universe.DefineType("uint64", universePos, &uintType{commonType{}, 64, false, "uint64"})
-
-       UintType    = universe.DefineType("uint", universePos, &uintType{commonType{}, 0, false, "uint"})
-       UintptrType = universe.DefineType("uintptr", universePos, &uintType{commonType{}, 0, true, "uintptr"})
-)
-
-func (t *uintType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*uintType)
-       return ok && t == t2
-}
-
-func (t *uintType) lit() Type { return t }
-
-func (t *uintType) isInteger() bool { return true }
-
-func (t *uintType) String() string { return "<" + t.name + ">" }
-
-func (t *uintType) Zero() Value {
-       switch t.Bits {
-       case 0:
-               if t.Ptr {
-                       res := uintptrV(0)
-                       return &res
-               } else {
-                       res := uintV(0)
-                       return &res
-               }
-       case 8:
-               res := uint8V(0)
-               return &res
-       case 16:
-               res := uint16V(0)
-               return &res
-       case 32:
-               res := uint32V(0)
-               return &res
-       case 64:
-               res := uint64V(0)
-               return &res
-       }
-       panic("unexpected uint bit count")
-}
-
-func (t *uintType) minVal() *big.Rat { return big.NewRat(0, 1) }
-
-func (t *uintType) maxVal() *big.Rat {
-       bits := t.Bits
-       if bits == 0 {
-               if t.Ptr {
-                       bits = uint(8 * unsafe.Sizeof(uintptr(0)))
-               } else {
-                       bits = uint(8 * unsafe.Sizeof(uint(0)))
-               }
-       }
-       numer := big.NewInt(1)
-       numer.Lsh(numer, bits)
-       numer.Sub(numer, idealOne)
-       return new(big.Rat).SetInt(numer)
-}
-
-/*
- * Int
- */
-
-type intType struct {
-       commonType
-
-       // XXX(Spec) Numeric types: "There is also a set of
-       // architecture-independent basic numeric types whose size
-       // depends on the architecture."  Should that be
-       // architecture-dependent?
-
-       // 0 for architecture-dependent types
-       Bits uint
-       name string
-}
-
-var (
-       Int8Type  = universe.DefineType("int8", universePos, &intType{commonType{}, 8, "int8"})
-       Int16Type = universe.DefineType("int16", universePos, &intType{commonType{}, 16, "int16"})
-       Int32Type = universe.DefineType("int32", universePos, &intType{commonType{}, 32, "int32"})
-       Int64Type = universe.DefineType("int64", universePos, &intType{commonType{}, 64, "int64"})
-
-       IntType = universe.DefineType("int", universePos, &intType{commonType{}, 0, "int"})
-)
-
-func (t *intType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*intType)
-       return ok && t == t2
-}
-
-func (t *intType) lit() Type { return t }
-
-func (t *intType) isInteger() bool { return true }
-
-func (t *intType) String() string { return "<" + t.name + ">" }
-
-func (t *intType) Zero() Value {
-       switch t.Bits {
-       case 8:
-               res := int8V(0)
-               return &res
-       case 16:
-               res := int16V(0)
-               return &res
-       case 32:
-               res := int32V(0)
-               return &res
-       case 64:
-               res := int64V(0)
-               return &res
-
-       case 0:
-               res := intV(0)
-               return &res
-       }
-       panic("unexpected int bit count")
-}
-
-func (t *intType) minVal() *big.Rat {
-       bits := t.Bits
-       if bits == 0 {
-               bits = uint(8 * unsafe.Sizeof(int(0)))
-       }
-       numer := big.NewInt(-1)
-       numer.Lsh(numer, bits-1)
-       return new(big.Rat).SetInt(numer)
-}
-
-func (t *intType) maxVal() *big.Rat {
-       bits := t.Bits
-       if bits == 0 {
-               bits = uint(8 * unsafe.Sizeof(int(0)))
-       }
-       numer := big.NewInt(1)
-       numer.Lsh(numer, bits-1)
-       numer.Sub(numer, idealOne)
-       return new(big.Rat).SetInt(numer)
-}
-
-/*
- * Ideal int
- */
-
-type idealIntType struct {
-       commonType
-}
-
-var IdealIntType Type = &idealIntType{}
-
-func (t *idealIntType) compat(o Type, conv bool) bool {
-       _, ok := o.lit().(*idealIntType)
-       return ok
-}
-
-func (t *idealIntType) lit() Type { return t }
-
-func (t *idealIntType) isInteger() bool { return true }
-
-func (t *idealIntType) isIdeal() bool { return true }
-
-func (t *idealIntType) String() string { return "ideal integer" }
-
-func (t *idealIntType) Zero() Value { return &idealIntV{idealZero} }
-
-/*
- * Float
- */
-
-type floatType struct {
-       commonType
-
-       // 0 for architecture-dependent type
-       Bits uint
-
-       name string
-}
-
-var (
-       Float32Type = universe.DefineType("float32", universePos, &floatType{commonType{}, 32, "float32"})
-       Float64Type = universe.DefineType("float64", universePos, &floatType{commonType{}, 64, "float64"})
-)
-
-func (t *floatType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*floatType)
-       return ok && t == t2
-}
-
-func (t *floatType) lit() Type { return t }
-
-func (t *floatType) isFloat() bool { return true }
-
-func (t *floatType) String() string { return "<" + t.name + ">" }
-
-func (t *floatType) Zero() Value {
-       switch t.Bits {
-       case 32:
-               res := float32V(0)
-               return &res
-       case 64:
-               res := float64V(0)
-               return &res
-       }
-       panic("unexpected float bit count")
-}
-
-var maxFloat32Val *big.Rat
-var maxFloat64Val *big.Rat
-var minFloat32Val *big.Rat
-var minFloat64Val *big.Rat
-
-func (t *floatType) minVal() *big.Rat {
-       bits := t.Bits
-       switch bits {
-       case 32:
-               return minFloat32Val
-       case 64:
-               return minFloat64Val
-       }
-       log.Panicf("unexpected floating point bit count: %d", bits)
-       panic("unreachable")
-}
-
-func (t *floatType) maxVal() *big.Rat {
-       bits := t.Bits
-       switch bits {
-       case 32:
-               return maxFloat32Val
-       case 64:
-               return maxFloat64Val
-       }
-       log.Panicf("unexpected floating point bit count: %d", bits)
-       panic("unreachable")
-}
-
-/*
- * Ideal float
- */
-
-type idealFloatType struct {
-       commonType
-}
-
-var IdealFloatType Type = &idealFloatType{}
-
-func (t *idealFloatType) compat(o Type, conv bool) bool {
-       _, ok := o.lit().(*idealFloatType)
-       return ok
-}
-
-func (t *idealFloatType) lit() Type { return t }
-
-func (t *idealFloatType) isFloat() bool { return true }
-
-func (t *idealFloatType) isIdeal() bool { return true }
-
-func (t *idealFloatType) String() string { return "ideal float" }
-
-func (t *idealFloatType) Zero() Value { return &idealFloatV{big.NewRat(0, 1)} }
-
-/*
- * String
- */
-
-type stringType struct {
-       commonType
-}
-
-var StringType = universe.DefineType("string", universePos, &stringType{})
-
-func (t *stringType) compat(o Type, conv bool) bool {
-       _, ok := o.lit().(*stringType)
-       return ok
-}
-
-func (t *stringType) lit() Type { return t }
-
-func (t *stringType) String() string { return "<string>" }
-
-func (t *stringType) Zero() Value {
-       res := stringV("")
-       return &res
-}
-
-/*
- * Array
- */
-
-type ArrayType struct {
-       commonType
-       Len  int64
-       Elem Type
-}
-
-var arrayTypes = make(map[int64]map[Type]*ArrayType)
-
-// Two array types are identical if they have identical element types
-// and the same array length.
-
-func NewArrayType(len int64, elem Type) *ArrayType {
-       ts, ok := arrayTypes[len]
-       if !ok {
-               ts = make(map[Type]*ArrayType)
-               arrayTypes[len] = ts
-       }
-       t, ok := ts[elem]
-       if !ok {
-               t = &ArrayType{commonType{}, len, elem}
-               ts[elem] = t
-       }
-       return t
-}
-
-func (t *ArrayType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*ArrayType)
-       if !ok {
-               return false
-       }
-       return t.Len == t2.Len && t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *ArrayType) lit() Type { return t }
-
-func (t *ArrayType) String() string { return "[]" + t.Elem.String() }
-
-func (t *ArrayType) Zero() Value {
-       res := arrayV(make([]Value, t.Len))
-       // TODO(austin) It's unfortunate that each element is
-       // separately heap allocated.  We could add ZeroArray to
-       // everything, though that doesn't help with multidimensional
-       // arrays.  Or we could do something unsafe.  We'll have this
-       // same problem with structs.
-       for i := int64(0); i < t.Len; i++ {
-               res[i] = t.Elem.Zero()
-       }
-       return &res
-}
-
-/*
- * Struct
- */
-
-type StructField struct {
-       Name      string
-       Type      Type
-       Anonymous bool
-}
-
-type StructType struct {
-       commonType
-       Elems []StructField
-}
-
-var structTypes = newTypeArrayMap()
-
-// Two struct types are identical if they have the same sequence of
-// fields, and if corresponding fields have the same names and
-// identical types. Two anonymous fields are considered to have the
-// same name.
-
-func NewStructType(fields []StructField) *StructType {
-       // Start by looking up just the types
-       fts := make([]Type, len(fields))
-       for i, f := range fields {
-               fts[i] = f.Type
-       }
-       tMapI := structTypes.Get(fts)
-       if tMapI == nil {
-               tMapI = structTypes.Put(fts, make(map[string]*StructType))
-       }
-       tMap := tMapI.(map[string]*StructType)
-
-       // Construct key for field names
-       key := ""
-       for _, f := range fields {
-               // XXX(Spec) It's not clear if struct { T } and struct
-               // { T T } are either identical or compatible.  The
-               // "Struct Types" section says that the name of that
-               // field is "T", which suggests that they are
-               // identical, but it really means that it's the name
-               // for the purpose of selector expressions and nothing
-               // else.  We decided that they should be neither
-               // identical or compatible.
-               if f.Anonymous {
-                       key += "!"
-               }
-               key += f.Name + " "
-       }
-
-       // XXX(Spec) Do the tags also have to be identical for the
-       // types to be identical?  I certainly hope so, because
-       // otherwise, this is the only case where two distinct type
-       // objects can represent identical types.
-
-       t, ok := tMap[key]
-       if !ok {
-               // Create new struct type
-               t = &StructType{commonType{}, fields}
-               tMap[key] = t
-       }
-       return t
-}
-
-func (t *StructType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*StructType)
-       if !ok {
-               return false
-       }
-       if len(t.Elems) != len(t2.Elems) {
-               return false
-       }
-       for i, e := range t.Elems {
-               e2 := t2.Elems[i]
-               // XXX(Spec) An anonymous and a non-anonymous field
-               // are neither identical nor compatible.
-               if e.Anonymous != e2.Anonymous ||
-                       (!e.Anonymous && e.Name != e2.Name) ||
-                       !e.Type.compat(e2.Type, conv) {
-                       return false
-               }
-       }
-       return true
-}
-
-func (t *StructType) lit() Type { return t }
-
-func (t *StructType) String() string {
-       s := "struct {"
-       for i, f := range t.Elems {
-               if i > 0 {
-                       s += "; "
-               }
-               if !f.Anonymous {
-                       s += f.Name + " "
-               }
-               s += f.Type.String()
-       }
-       return s + "}"
-}
-
-func (t *StructType) Zero() Value {
-       res := structV(make([]Value, len(t.Elems)))
-       for i, f := range t.Elems {
-               res[i] = f.Type.Zero()
-       }
-       return &res
-}
-
-/*
- * Pointer
- */
-
-type PtrType struct {
-       commonType
-       Elem Type
-}
-
-var ptrTypes = make(map[Type]*PtrType)
-
-// Two pointer types are identical if they have identical base types.
-
-func NewPtrType(elem Type) *PtrType {
-       t, ok := ptrTypes[elem]
-       if !ok {
-               t = &PtrType{commonType{}, elem}
-               ptrTypes[elem] = t
-       }
-       return t
-}
-
-func (t *PtrType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*PtrType)
-       if !ok {
-               return false
-       }
-       return t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *PtrType) lit() Type { return t }
-
-func (t *PtrType) String() string { return "*" + t.Elem.String() }
-
-func (t *PtrType) Zero() Value { return &ptrV{nil} }
-
-/*
- * Function
- */
-
-type FuncType struct {
-       commonType
-       // TODO(austin) Separate receiver Type for methods?
-       In       []Type
-       Variadic bool
-       Out      []Type
-       builtin  string
-}
-
-var funcTypes = newTypeArrayMap()
-var variadicFuncTypes = newTypeArrayMap()
-
-// Create singleton function types for magic built-in functions
-var (
-       capType     = &FuncType{builtin: "cap"}
-       closeType   = &FuncType{builtin: "close"}
-       closedType  = &FuncType{builtin: "closed"}
-       lenType     = &FuncType{builtin: "len"}
-       makeType    = &FuncType{builtin: "make"}
-       newType     = &FuncType{builtin: "new"}
-       panicType   = &FuncType{builtin: "panic"}
-       printType   = &FuncType{builtin: "print"}
-       printlnType = &FuncType{builtin: "println"}
-       copyType    = &FuncType{builtin: "copy"}
-)
-
-// Two function types are identical if they have the same number of
-// parameters and result values and if corresponding parameter and
-// result types are identical. All "..." parameters have identical
-// type. Parameter and result names are not required to match.
-
-func NewFuncType(in []Type, variadic bool, out []Type) *FuncType {
-       inMap := funcTypes
-       if variadic {
-               inMap = variadicFuncTypes
-       }
-
-       outMapI := inMap.Get(in)
-       if outMapI == nil {
-               outMapI = inMap.Put(in, newTypeArrayMap())
-       }
-       outMap := outMapI.(typeArrayMap)
-
-       tI := outMap.Get(out)
-       if tI != nil {
-               return tI.(*FuncType)
-       }
-
-       t := &FuncType{commonType{}, in, variadic, out, ""}
-       outMap.Put(out, t)
-       return t
-}
-
-func (t *FuncType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*FuncType)
-       if !ok {
-               return false
-       }
-       if len(t.In) != len(t2.In) || t.Variadic != t2.Variadic || len(t.Out) != len(t2.Out) {
-               return false
-       }
-       for i := range t.In {
-               if !t.In[i].compat(t2.In[i], conv) {
-                       return false
-               }
-       }
-       for i := range t.Out {
-               if !t.Out[i].compat(t2.Out[i], conv) {
-                       return false
-               }
-       }
-       return true
-}
-
-func (t *FuncType) lit() Type { return t }
-
-func typeListString(ts []Type, ns []*ast.Ident) string {
-       s := ""
-       for i, t := range ts {
-               if i > 0 {
-                       s += ", "
-               }
-               if ns != nil && ns[i] != nil {
-                       s += ns[i].Name + " "
-               }
-               if t == nil {
-                       // Some places use nil types to represent errors
-                       s += "<none>"
-               } else {
-                       s += t.String()
-               }
-       }
-       return s
-}
-
-func (t *FuncType) String() string {
-       if t.builtin != "" {
-               return "built-in function " + t.builtin
-       }
-       args := typeListString(t.In, nil)
-       if t.Variadic {
-               if len(args) > 0 {
-                       args += ", "
-               }
-               args += "..."
-       }
-       s := "func(" + args + ")"
-       if len(t.Out) > 0 {
-               s += " (" + typeListString(t.Out, nil) + ")"
-       }
-       return s
-}
-
-func (t *FuncType) Zero() Value { return &funcV{nil} }
-
-type FuncDecl struct {
-       Type *FuncType
-       Name *ast.Ident // nil for function literals
-       // InNames will be one longer than Type.In if this function is
-       // variadic.
-       InNames  []*ast.Ident
-       OutNames []*ast.Ident
-}
-
-func (t *FuncDecl) String() string {
-       s := "func"
-       if t.Name != nil {
-               s += " " + t.Name.Name
-       }
-       s += funcTypeString(t.Type, t.InNames, t.OutNames)
-       return s
-}
-
-func funcTypeString(ft *FuncType, ins []*ast.Ident, outs []*ast.Ident) string {
-       s := "("
-       s += typeListString(ft.In, ins)
-       if ft.Variadic {
-               if len(ft.In) > 0 {
-                       s += ", "
-               }
-               s += "..."
-       }
-       s += ")"
-       if len(ft.Out) > 0 {
-               s += " (" + typeListString(ft.Out, outs) + ")"
-       }
-       return s
-}
-
-/*
- * Interface
- */
-
-// TODO(austin) Interface values, types, and type compilation are
-// implemented, but none of the type checking or semantics of
-// interfaces are.
-
-type InterfaceType struct {
-       commonType
-       // TODO(austin) This should be a map from names to
-       // *FuncType's.  We only need the sorted list for generating
-       // the type map key.  It's detrimental for everything else.
-       methods []IMethod
-}
-
-type IMethod struct {
-       Name string
-       Type *FuncType
-}
-
-var interfaceTypes = newTypeArrayMap()
-
-func NewInterfaceType(methods []IMethod, embeds []*InterfaceType) *InterfaceType {
-       // Count methods of embedded interfaces
-       nMethods := len(methods)
-       for _, e := range embeds {
-               nMethods += len(e.methods)
-       }
-
-       // Combine methods
-       allMethods := make([]IMethod, nMethods)
-       copy(allMethods, methods)
-       n := len(methods)
-       for _, e := range embeds {
-               for _, m := range e.methods {
-                       allMethods[n] = m
-                       n++
-               }
-       }
-
-       // Sort methods
-       sort.Sort(iMethodSorter(allMethods))
-
-       mts := make([]Type, len(allMethods))
-       for i, m := range methods {
-               mts[i] = m.Type
-       }
-       tMapI := interfaceTypes.Get(mts)
-       if tMapI == nil {
-               tMapI = interfaceTypes.Put(mts, make(map[string]*InterfaceType))
-       }
-       tMap := tMapI.(map[string]*InterfaceType)
-
-       key := ""
-       for _, m := range allMethods {
-               key += m.Name + " "
-       }
-
-       t, ok := tMap[key]
-       if !ok {
-               t = &InterfaceType{commonType{}, allMethods}
-               tMap[key] = t
-       }
-       return t
-}
-
-type iMethodSorter []IMethod
-
-func (s iMethodSorter) Less(a, b int) bool { return s[a].Name < s[b].Name }
-
-func (s iMethodSorter) Swap(a, b int) { s[a], s[b] = s[b], s[a] }
-
-func (s iMethodSorter) Len() int { return len(s) }
-
-func (t *InterfaceType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*InterfaceType)
-       if !ok {
-               return false
-       }
-       if len(t.methods) != len(t2.methods) {
-               return false
-       }
-       for i, e := range t.methods {
-               e2 := t2.methods[i]
-               if e.Name != e2.Name || !e.Type.compat(e2.Type, conv) {
-                       return false
-               }
-       }
-       return true
-}
-
-func (t *InterfaceType) lit() Type { return t }
-
-func (t *InterfaceType) String() string {
-       // TODO(austin) Instead of showing embedded interfaces, this
-       // shows their methods.
-       s := "interface {"
-       for i, m := range t.methods {
-               if i > 0 {
-                       s += "; "
-               }
-               s += m.Name + funcTypeString(m.Type, nil, nil)
-       }
-       return s + "}"
-}
-
-// implementedBy tests if o implements t, returning nil, true if it does.
-// Otherwise, it returns a method of t that o is missing and false.
-func (t *InterfaceType) implementedBy(o Type) (*IMethod, bool) {
-       if len(t.methods) == 0 {
-               return nil, true
-       }
-
-       // The methods of a named interface types are those of the
-       // underlying type.
-       if it, ok := o.lit().(*InterfaceType); ok {
-               o = it
-       }
-
-       // XXX(Spec) Interface types: "A type implements any interface
-       // comprising any subset of its methods" It's unclear if
-       // methods must have identical or compatible types.  6g
-       // requires identical types.
-
-       switch o := o.(type) {
-       case *NamedType:
-               for _, tm := range t.methods {
-                       sm, ok := o.methods[tm.Name]
-                       if !ok || sm.decl.Type != tm.Type {
-                               return &tm, false
-                       }
-               }
-               return nil, true
-
-       case *InterfaceType:
-               var ti, oi int
-               for ti < len(t.methods) && oi < len(o.methods) {
-                       tm, om := &t.methods[ti], &o.methods[oi]
-                       switch {
-                       case tm.Name == om.Name:
-                               if tm.Type != om.Type {
-                                       return tm, false
-                               }
-                               ti++
-                               oi++
-                       case tm.Name > om.Name:
-                               oi++
-                       default:
-                               return tm, false
-                       }
-               }
-               if ti < len(t.methods) {
-                       return &t.methods[ti], false
-               }
-               return nil, true
-       }
-
-       return &t.methods[0], false
-}
-
-func (t *InterfaceType) Zero() Value { return &interfaceV{} }
-
-/*
- * Slice
- */
-
-type SliceType struct {
-       commonType
-       Elem Type
-}
-
-var sliceTypes = make(map[Type]*SliceType)
-
-// Two slice types are identical if they have identical element types.
-
-func NewSliceType(elem Type) *SliceType {
-       t, ok := sliceTypes[elem]
-       if !ok {
-               t = &SliceType{commonType{}, elem}
-               sliceTypes[elem] = t
-       }
-       return t
-}
-
-func (t *SliceType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*SliceType)
-       if !ok {
-               return false
-       }
-       return t.Elem.compat(t2.Elem, conv)
-}
-
-func (t *SliceType) lit() Type { return t }
-
-func (t *SliceType) String() string { return "[]" + t.Elem.String() }
-
-func (t *SliceType) Zero() Value {
-       // The value of an uninitialized slice is nil. The length and
-       // capacity of a nil slice are 0.
-       return &sliceV{Slice{nil, 0, 0}}
-}
-
-/*
- * Map type
- */
-
-type MapType struct {
-       commonType
-       Key  Type
-       Elem Type
-}
-
-var mapTypes = make(map[Type]map[Type]*MapType)
-
-func NewMapType(key Type, elem Type) *MapType {
-       ts, ok := mapTypes[key]
-       if !ok {
-               ts = make(map[Type]*MapType)
-               mapTypes[key] = ts
-       }
-       t, ok := ts[elem]
-       if !ok {
-               t = &MapType{commonType{}, key, elem}
-               ts[elem] = t
-       }
-       return t
-}
-
-func (t *MapType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*MapType)
-       if !ok {
-               return false
-       }
-       return t.Elem.compat(t2.Elem, conv) && t.Key.compat(t2.Key, conv)
-}
-
-func (t *MapType) lit() Type { return t }
-
-func (t *MapType) String() string { return "map[" + t.Key.String() + "] " + t.Elem.String() }
-
-func (t *MapType) Zero() Value {
-       // The value of an uninitialized map is nil.
-       return &mapV{nil}
-}
-
-/*
-type ChanType struct {
-       // TODO(austin)
-}
-*/
-
-/*
- * Named types
- */
-
-type Method struct {
-       decl *FuncDecl
-       fn   Func
-}
-
-type NamedType struct {
-       NamePos token.Pos
-       Name    string
-       // Underlying type.  If incomplete is true, this will be nil.
-       // If incomplete is false and this is still nil, then this is
-       // a placeholder type representing an error.
-       Def Type
-       // True while this type is being defined.
-       incomplete bool
-       methods    map[string]Method
-}
-
-// TODO(austin) This is temporarily needed by the debugger's remote
-// type parser.  This should only be possible with block.DefineType.
-func NewNamedType(name string) *NamedType {
-       return &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
-}
-
-func (t *NamedType) Pos() token.Pos {
-       return t.NamePos
-}
-
-func (t *NamedType) Complete(def Type) {
-       if !t.incomplete {
-               log.Panicf("cannot complete already completed NamedType %+v", *t)
-       }
-       // We strip the name from def because multiple levels of
-       // naming are useless.
-       if ndef, ok := def.(*NamedType); ok {
-               def = ndef.Def
-       }
-       t.Def = def
-       t.incomplete = false
-}
-
-func (t *NamedType) compat(o Type, conv bool) bool {
-       t2, ok := o.(*NamedType)
-       if ok {
-               if conv {
-                       // Two named types are conversion compatible
-                       // if their literals are conversion
-                       // compatible.
-                       return t.Def.compat(t2.Def, conv)
-               } else {
-                       // Two named types are compatible if their
-                       // type names originate in the same type
-                       // declaration.
-                       return t == t2
-               }
-       }
-       // A named and an unnamed type are compatible if the
-       // respective type literals are compatible.
-       return o.compat(t.Def, conv)
-}
-
-func (t *NamedType) lit() Type { return t.Def.lit() }
-
-func (t *NamedType) isBoolean() bool { return t.Def.isBoolean() }
-
-func (t *NamedType) isInteger() bool { return t.Def.isInteger() }
-
-func (t *NamedType) isFloat() bool { return t.Def.isFloat() }
-
-func (t *NamedType) isIdeal() bool { return false }
-
-func (t *NamedType) String() string { return t.Name }
-
-func (t *NamedType) Zero() Value { return t.Def.Zero() }
-
-/*
- * Multi-valued type
- */
-
-// MultiType is a special type used for multi-valued expressions, akin
-// to a tuple type.  It's not generally accessible within the
-// language.
-type MultiType struct {
-       commonType
-       Elems []Type
-}
-
-var multiTypes = newTypeArrayMap()
-
-func NewMultiType(elems []Type) *MultiType {
-       if t := multiTypes.Get(elems); t != nil {
-               return t.(*MultiType)
-       }
-
-       t := &MultiType{commonType{}, elems}
-       multiTypes.Put(elems, t)
-       return t
-}
-
-func (t *MultiType) compat(o Type, conv bool) bool {
-       t2, ok := o.lit().(*MultiType)
-       if !ok {
-               return false
-       }
-       if len(t.Elems) != len(t2.Elems) {
-               return false
-       }
-       for i := range t.Elems {
-               if !t.Elems[i].compat(t2.Elems[i], conv) {
-                       return false
-               }
-       }
-       return true
-}
-
-var EmptyType Type = NewMultiType([]Type{})
-
-func (t *MultiType) lit() Type { return t }
-
-func (t *MultiType) String() string {
-       if len(t.Elems) == 0 {
-               return "<none>"
-       }
-       return typeListString(t.Elems, nil)
-}
-
-func (t *MultiType) Zero() Value {
-       res := make([]Value, len(t.Elems))
-       for i, t := range t.Elems {
-               res[i] = t.Zero()
-       }
-       return multiV(res)
-}
-
-/*
- * Initialize the universe
- */
-
-func init() {
-       numer := big.NewInt(0xffffff)
-       numer.Lsh(numer, 127-23)
-       maxFloat32Val = new(big.Rat).SetInt(numer)
-       numer.SetInt64(0x1fffffffffffff)
-       numer.Lsh(numer, 1023-52)
-       maxFloat64Val = new(big.Rat).SetInt(numer)
-       minFloat32Val = new(big.Rat).Neg(maxFloat32Val)
-       minFloat64Val = new(big.Rat).Neg(maxFloat64Val)
-
-       // To avoid portability issues all numeric types are distinct
-       // except byte, which is an alias for uint8.
-
-       // Make byte an alias for the named type uint8.  Type aliases
-       // are otherwise impossible in Go, so just hack it here.
-       universe.defs["byte"] = universe.defs["uint8"]
-
-       // Built-in functions
-       universe.DefineConst("cap", universePos, capType, nil)
-       universe.DefineConst("close", universePos, closeType, nil)
-       universe.DefineConst("closed", universePos, closedType, nil)
-       universe.DefineConst("copy", universePos, copyType, nil)
-       universe.DefineConst("len", universePos, lenType, nil)
-       universe.DefineConst("make", universePos, makeType, nil)
-       universe.DefineConst("new", universePos, newType, nil)
-       universe.DefineConst("panic", universePos, panicType, nil)
-       universe.DefineConst("print", universePos, printType, nil)
-       universe.DefineConst("println", universePos, printlnType, nil)
-}
diff --git a/src/pkg/exp/eval/typec.go b/src/pkg/exp/eval/typec.go
deleted file mode 100644 (file)
index 0ed24a8..0000000
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "go/ast"
-       "go/token"
-       "log"
-)
-
-
-/*
- * Type compiler
- */
-
-type typeCompiler struct {
-       *compiler
-       block *block
-       // Check to be performed after a type declaration is compiled.
-       //
-       // TODO(austin) This will probably have to change after we
-       // eliminate forward declarations.
-       lateCheck func() bool
-}
-
-func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
-       _, _, def := a.block.Lookup(x.Name)
-       if def == nil {
-               a.diagAt(x.Pos(), "%s: undefined", x.Name)
-               return nil
-       }
-       switch def := def.(type) {
-       case *Constant:
-               a.diagAt(x.Pos(), "constant %v used as type", x.Name)
-               return nil
-       case *Variable:
-               a.diagAt(x.Pos(), "variable %v used as type", x.Name)
-               return nil
-       case *NamedType:
-               if !allowRec && def.incomplete {
-                       a.diagAt(x.Pos(), "illegal recursive type")
-                       return nil
-               }
-               if !def.incomplete && def.Def == nil {
-                       // Placeholder type from an earlier error
-                       return nil
-               }
-               return def
-       case Type:
-               return def
-       }
-       log.Panicf("name %s has unknown type %T", x.Name, def)
-       return nil
-}
-
-func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
-       // Compile element type
-       elem := a.compileType(x.Elt, allowRec)
-
-       // Compile length expression
-       if x.Len == nil {
-               if elem == nil {
-                       return nil
-               }
-               return NewSliceType(elem)
-       }
-
-       if _, ok := x.Len.(*ast.Ellipsis); ok {
-               a.diagAt(x.Len.Pos(), "... array initializers not implemented")
-               return nil
-       }
-       l, ok := a.compileArrayLen(a.block, x.Len)
-       if !ok {
-               return nil
-       }
-       if l < 0 {
-               a.diagAt(x.Len.Pos(), "array length must be non-negative")
-               return nil
-       }
-       if elem == nil {
-               return nil
-       }
-
-       return NewArrayType(l, elem)
-}
-
-func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Pos, bool) {
-       n := fields.NumFields()
-       ts := make([]Type, n)
-       ns := make([]*ast.Ident, n)
-       ps := make([]token.Pos, n)
-       bad := false
-
-       if fields != nil {
-               i := 0
-               for _, f := range fields.List {
-                       t := a.compileType(f.Type, allowRec)
-                       if t == nil {
-                               bad = true
-                       }
-                       if f.Names == nil {
-                               ns[i] = nil
-                               ts[i] = t
-                               ps[i] = f.Type.Pos()
-                               i++
-                               continue
-                       }
-                       for _, n := range f.Names {
-                               ns[i] = n
-                               ts[i] = t
-                               ps[i] = n.Pos()
-                               i++
-                       }
-               }
-       }
-
-       return ts, ns, ps, bad
-}
-
-func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type {
-       ts, names, poss, bad := a.compileFields(x.Fields, allowRec)
-
-       // XXX(Spec) The spec claims that field identifiers must be
-       // unique, but 6g only checks this when they are accessed.  I
-       // think the spec is better in this regard: if I write two
-       // fields with the same name in the same struct type, clearly
-       // that's a mistake.  This definition does *not* descend into
-       // anonymous fields, so it doesn't matter if those change.
-       // There's separate language in the spec about checking
-       // uniqueness of field names inherited from anonymous fields
-       // at use time.
-       fields := make([]StructField, len(ts))
-       nameSet := make(map[string]token.Pos, len(ts))
-       for i := range fields {
-               // Compute field name and check anonymous fields
-               var name string
-               if names[i] != nil {
-                       name = names[i].Name
-               } else {
-                       if ts[i] == nil {
-                               continue
-                       }
-
-                       var nt *NamedType
-                       // [For anonymous fields,] the unqualified
-                       // type name acts as the field identifier.
-                       switch t := ts[i].(type) {
-                       case *NamedType:
-                               name = t.Name
-                               nt = t
-                       case *PtrType:
-                               switch t := t.Elem.(type) {
-                               case *NamedType:
-                                       name = t.Name
-                                       nt = t
-                               }
-                       }
-                       // [An anonymous field] must be specified as a
-                       // type name T or as a pointer to a type name
-                       // *T, and T itself, may not be a pointer or
-                       // interface type.
-                       if nt == nil {
-                               a.diagAt(poss[i], "embedded type must T or *T, where T is a named type")
-                               bad = true
-                               continue
-                       }
-                       // The check for embedded pointer types must
-                       // be deferred because of things like
-                       //  type T *struct { T }
-                       lateCheck := a.lateCheck
-                       a.lateCheck = func() bool {
-                               if _, ok := nt.lit().(*PtrType); ok {
-                                       a.diagAt(poss[i], "embedded type %v is a pointer type", nt)
-                                       return false
-                               }
-                               return lateCheck()
-                       }
-               }
-
-               // Check name uniqueness
-               if prev, ok := nameSet[name]; ok {
-                       a.diagAt(poss[i], "field %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev))
-                       bad = true
-                       continue
-               }
-               nameSet[name] = poss[i]
-
-               // Create field
-               fields[i].Name = name
-               fields[i].Type = ts[i]
-               fields[i].Anonymous = (names[i] == nil)
-       }
-
-       if bad {
-               return nil
-       }
-
-       return NewStructType(fields)
-}
-
-func (a *typeCompiler) compilePtrType(x *ast.StarExpr) Type {
-       elem := a.compileType(x.X, true)
-       if elem == nil {
-               return nil
-       }
-       return NewPtrType(elem)
-}
-
-func (a *typeCompiler) compileFuncType(x *ast.FuncType, allowRec bool) *FuncDecl {
-       // TODO(austin) Variadic function types
-
-       // The types of parameters and results must be complete.
-       //
-       // TODO(austin) It's not clear they actually have to be complete.
-       in, inNames, _, inBad := a.compileFields(x.Params, allowRec)
-       out, outNames, _, outBad := a.compileFields(x.Results, allowRec)
-
-       if inBad || outBad {
-               return nil
-       }
-       return &FuncDecl{NewFuncType(in, false, out), nil, inNames, outNames}
-}
-
-func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool) *InterfaceType {
-       ts, names, poss, bad := a.compileFields(x.Methods, allowRec)
-
-       methods := make([]IMethod, len(ts))
-       nameSet := make(map[string]token.Pos, len(ts))
-       embeds := make([]*InterfaceType, len(ts))
-
-       var nm, ne int
-       for i := range ts {
-               if ts[i] == nil {
-                       continue
-               }
-
-               if names[i] != nil {
-                       name := names[i].Name
-                       methods[nm].Name = name
-                       methods[nm].Type = ts[i].(*FuncType)
-                       nm++
-                       if prev, ok := nameSet[name]; ok {
-                               a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev))
-                               bad = true
-                               continue
-                       }
-                       nameSet[name] = poss[i]
-               } else {
-                       // Embedded interface
-                       it, ok := ts[i].lit().(*InterfaceType)
-                       if !ok {
-                               a.diagAt(poss[i], "embedded type must be an interface")
-                               bad = true
-                               continue
-                       }
-                       embeds[ne] = it
-                       ne++
-                       for _, m := range it.methods {
-                               if prev, ok := nameSet[m.Name]; ok {
-                                       a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", m.Name, a.fset.Position(prev))
-                                       bad = true
-                                       continue
-                               }
-                               nameSet[m.Name] = poss[i]
-                       }
-               }
-       }
-
-       if bad {
-               return nil
-       }
-
-       methods = methods[0:nm]
-       embeds = embeds[0:ne]
-
-       return NewInterfaceType(methods, embeds)
-}
-
-func (a *typeCompiler) compileMapType(x *ast.MapType) Type {
-       key := a.compileType(x.Key, true)
-       val := a.compileType(x.Value, true)
-       if key == nil || val == nil {
-               return nil
-       }
-       // XXX(Spec) The Map types section explicitly lists all types
-       // that can be map keys except for function types.
-       switch key.lit().(type) {
-       case *StructType:
-               a.diagAt(x.Pos(), "map key cannot be a struct type")
-               return nil
-       case *ArrayType:
-               a.diagAt(x.Pos(), "map key cannot be an array type")
-               return nil
-       case *SliceType:
-               a.diagAt(x.Pos(), "map key cannot be a slice type")
-               return nil
-       }
-       return NewMapType(key, val)
-}
-
-func (a *typeCompiler) compileType(x ast.Expr, allowRec bool) Type {
-       switch x := x.(type) {
-       case *ast.BadExpr:
-               // Error already reported by parser
-               a.silentErrors++
-               return nil
-
-       case *ast.Ident:
-               return a.compileIdent(x, allowRec)
-
-       case *ast.ArrayType:
-               return a.compileArrayType(x, allowRec)
-
-       case *ast.StructType:
-               return a.compileStructType(x, allowRec)
-
-       case *ast.StarExpr:
-               return a.compilePtrType(x)
-
-       case *ast.FuncType:
-               fd := a.compileFuncType(x, allowRec)
-               if fd == nil {
-                       return nil
-               }
-               return fd.Type
-
-       case *ast.InterfaceType:
-               return a.compileInterfaceType(x, allowRec)
-
-       case *ast.MapType:
-               return a.compileMapType(x)
-
-       case *ast.ChanType:
-               goto notimpl
-
-       case *ast.ParenExpr:
-               return a.compileType(x.X, allowRec)
-
-       case *ast.Ellipsis:
-               a.diagAt(x.Pos(), "illegal use of ellipsis")
-               return nil
-       }
-       a.diagAt(x.Pos(), "expression used as type")
-       return nil
-
-notimpl:
-       a.diagAt(x.Pos(), "compileType: %T not implemented", x)
-       return nil
-}
-
-/*
- * Type compiler interface
- */
-
-func noLateCheck() bool { return true }
-
-func (a *compiler) compileType(b *block, typ ast.Expr) Type {
-       tc := &typeCompiler{a, b, noLateCheck}
-       t := tc.compileType(typ, false)
-       if !tc.lateCheck() {
-               t = nil
-       }
-       return t
-}
-
-func (a *compiler) compileTypeDecl(b *block, decl *ast.GenDecl) bool {
-       ok := true
-       for _, spec := range decl.Specs {
-               spec := spec.(*ast.TypeSpec)
-               // Create incomplete type for this type
-               nt := b.DefineType(spec.Name.Name, spec.Name.Pos(), nil)
-               if nt != nil {
-                       nt.(*NamedType).incomplete = true
-               }
-               // Compile type
-               tc := &typeCompiler{a, b, noLateCheck}
-               t := tc.compileType(spec.Type, false)
-               if t == nil {
-                       // Create a placeholder type
-                       ok = false
-               }
-               // Fill incomplete type
-               if nt != nil {
-                       nt.(*NamedType).Complete(t)
-               }
-               // Perform late type checking with complete type
-               if !tc.lateCheck() {
-                       ok = false
-                       if nt != nil {
-                               // Make the type a placeholder
-                               nt.(*NamedType).Def = nil
-                       }
-               }
-       }
-       return ok
-}
-
-func (a *compiler) compileFuncType(b *block, typ *ast.FuncType) *FuncDecl {
-       tc := &typeCompiler{a, b, noLateCheck}
-       res := tc.compileFuncType(typ, false)
-       if res != nil {
-               if !tc.lateCheck() {
-                       res = nil
-               }
-       }
-       return res
-}
diff --git a/src/pkg/exp/eval/value.go b/src/pkg/exp/eval/value.go
deleted file mode 100644 (file)
index daa6918..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package eval
-
-import (
-       "big"
-       "fmt"
-)
-
-type Value interface {
-       String() string
-       // Assign copies another value into this one.  It should
-       // assume that the other value satisfies the same specific
-       // value interface (BoolValue, etc.), but must not assume
-       // anything about its specific type.
-       Assign(t *Thread, o Value)
-}
-
-type BoolValue interface {
-       Value
-       Get(*Thread) bool
-       Set(*Thread, bool)
-}
-
-type UintValue interface {
-       Value
-       Get(*Thread) uint64
-       Set(*Thread, uint64)
-}
-
-type IntValue interface {
-       Value
-       Get(*Thread) int64
-       Set(*Thread, int64)
-}
-
-// TODO(austin) IdealIntValue and IdealFloatValue should not exist
-// because ideals are not l-values.
-type IdealIntValue interface {
-       Value
-       Get() *big.Int
-}
-
-type FloatValue interface {
-       Value
-       Get(*Thread) float64
-       Set(*Thread, float64)
-}
-
-type IdealFloatValue interface {
-       Value
-       Get() *big.Rat
-}
-
-type StringValue interface {
-       Value
-       Get(*Thread) string
-       Set(*Thread, string)
-}
-
-type ArrayValue interface {
-       Value
-       // TODO(austin) Get() is here for uniformity, but is
-       // completely useless.  If a lot of other types have similarly
-       // useless Get methods, just special-case these uses.
-       Get(*Thread) ArrayValue
-       Elem(*Thread, int64) Value
-       // Sub returns an ArrayValue backed by the same array that
-       // starts from element i and has length len.
-       Sub(i int64, len int64) ArrayValue
-}
-
-type StructValue interface {
-       Value
-       // TODO(austin) This is another useless Get()
-       Get(*Thread) StructValue
-       Field(*Thread, int) Value
-}
-
-type PtrValue interface {
-       Value
-       Get(*Thread) Value
-       Set(*Thread, Value)
-}
-
-type Func interface {
-       NewFrame() *Frame
-       Call(*Thread)
-}
-
-type FuncValue interface {
-       Value
-       Get(*Thread) Func
-       Set(*Thread, Func)
-}
-
-type Interface struct {
-       Type  Type
-       Value Value
-}
-
-type InterfaceValue interface {
-       Value
-       Get(*Thread) Interface
-       Set(*Thread, Interface)
-}
-
-type Slice struct {
-       Base     ArrayValue
-       Len, Cap int64
-}
-
-type SliceValue interface {
-       Value
-       Get(*Thread) Slice
-       Set(*Thread, Slice)
-}
-
-type Map interface {
-       Len(*Thread) int64
-       // Retrieve an element from the map, returning nil if it does
-       // not exist.
-       Elem(t *Thread, key interface{}) Value
-       // Set an entry in the map.  If val is nil, delete the entry.
-       SetElem(t *Thread, key interface{}, val Value)
-       // TODO(austin)  Perhaps there should be an iterator interface instead.
-       Iter(func(key interface{}, val Value) bool)
-}
-
-type MapValue interface {
-       Value
-       Get(*Thread) Map
-       Set(*Thread, Map)
-}
-
-/*
- * Bool
- */
-
-type boolV bool
-
-func (v *boolV) String() string { return fmt.Sprint(*v) }
-
-func (v *boolV) Assign(t *Thread, o Value) { *v = boolV(o.(BoolValue).Get(t)) }
-
-func (v *boolV) Get(*Thread) bool { return bool(*v) }
-
-func (v *boolV) Set(t *Thread, x bool) { *v = boolV(x) }
-
-/*
- * Uint
- */
-
-type uint8V uint8
-
-func (v *uint8V) String() string { return fmt.Sprint(*v) }
-
-func (v *uint8V) Assign(t *Thread, o Value) { *v = uint8V(o.(UintValue).Get(t)) }
-
-func (v *uint8V) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uint8V) Set(t *Thread, x uint64) { *v = uint8V(x) }
-
-type uint16V uint16
-
-func (v *uint16V) String() string { return fmt.Sprint(*v) }
-
-func (v *uint16V) Assign(t *Thread, o Value) { *v = uint16V(o.(UintValue).Get(t)) }
-
-func (v *uint16V) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uint16V) Set(t *Thread, x uint64) { *v = uint16V(x) }
-
-type uint32V uint32
-
-func (v *uint32V) String() string { return fmt.Sprint(*v) }
-
-func (v *uint32V) Assign(t *Thread, o Value) { *v = uint32V(o.(UintValue).Get(t)) }
-
-func (v *uint32V) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uint32V) Set(t *Thread, x uint64) { *v = uint32V(x) }
-
-type uint64V uint64
-
-func (v *uint64V) String() string { return fmt.Sprint(*v) }
-
-func (v *uint64V) Assign(t *Thread, o Value) { *v = uint64V(o.(UintValue).Get(t)) }
-
-func (v *uint64V) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uint64V) Set(t *Thread, x uint64) { *v = uint64V(x) }
-
-type uintV uint
-
-func (v *uintV) String() string { return fmt.Sprint(*v) }
-
-func (v *uintV) Assign(t *Thread, o Value) { *v = uintV(o.(UintValue).Get(t)) }
-
-func (v *uintV) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uintV) Set(t *Thread, x uint64) { *v = uintV(x) }
-
-type uintptrV uintptr
-
-func (v *uintptrV) String() string { return fmt.Sprint(*v) }
-
-func (v *uintptrV) Assign(t *Thread, o Value) { *v = uintptrV(o.(UintValue).Get(t)) }
-
-func (v *uintptrV) Get(*Thread) uint64 { return uint64(*v) }
-
-func (v *uintptrV) Set(t *Thread, x uint64) { *v = uintptrV(x) }
-
-/*
- * Int
- */
-
-type int8V int8
-
-func (v *int8V) String() string { return fmt.Sprint(*v) }
-
-func (v *int8V) Assign(t *Thread, o Value) { *v = int8V(o.(IntValue).Get(t)) }
-
-func (v *int8V) Get(*Thread) int64 { return int64(*v) }
-
-func (v *int8V) Set(t *Thread, x int64) { *v = int8V(x) }
-
-type int16V int16
-
-func (v *int16V) String() string { return fmt.Sprint(*v) }
-
-func (v *int16V) Assign(t *Thread, o Value) { *v = int16V(o.(IntValue).Get(t)) }
-
-func (v *int16V) Get(*Thread) int64 { return int64(*v) }
-
-func (v *int16V) Set(t *Thread, x int64) { *v = int16V(x) }
-
-type int32V int32
-
-func (v *int32V) String() string { return fmt.Sprint(*v) }
-
-func (v *int32V) Assign(t *Thread, o Value) { *v = int32V(o.(IntValue).Get(t)) }
-
-func (v *int32V) Get(*Thread) int64 { return int64(*v) }
-
-func (v *int32V) Set(t *Thread, x int64) { *v = int32V(x) }
-
-type int64V int64
-
-func (v *int64V) String() string { return fmt.Sprint(*v) }
-
-func (v *int64V) Assign(t *Thread, o Value) { *v = int64V(o.(IntValue).Get(t)) }
-
-func (v *int64V) Get(*Thread) int64 { return int64(*v) }
-
-func (v *int64V) Set(t *Thread, x int64) { *v = int64V(x) }
-
-type intV int
-
-func (v *intV) String() string { return fmt.Sprint(*v) }
-
-func (v *intV) Assign(t *Thread, o Value) { *v = intV(o.(IntValue).Get(t)) }
-
-func (v *intV) Get(*Thread) int64 { return int64(*v) }
-
-func (v *intV) Set(t *Thread, x int64) { *v = intV(x) }
-
-/*
- * Ideal int
- */
-
-type idealIntV struct {
-       V *big.Int
-}
-
-func (v *idealIntV) String() string { return v.V.String() }
-
-func (v *idealIntV) Assign(t *Thread, o Value) {
-       v.V = o.(IdealIntValue).Get()
-}
-
-func (v *idealIntV) Get() *big.Int { return v.V }
-
-/*
- * Float
- */
-
-type float32V float32
-
-func (v *float32V) String() string { return fmt.Sprint(*v) }
-
-func (v *float32V) Assign(t *Thread, o Value) { *v = float32V(o.(FloatValue).Get(t)) }
-
-func (v *float32V) Get(*Thread) float64 { return float64(*v) }
-
-func (v *float32V) Set(t *Thread, x float64) { *v = float32V(x) }
-
-type float64V float64
-
-func (v *float64V) String() string { return fmt.Sprint(*v) }
-
-func (v *float64V) Assign(t *Thread, o Value) { *v = float64V(o.(FloatValue).Get(t)) }
-
-func (v *float64V) Get(*Thread) float64 { return float64(*v) }
-
-func (v *float64V) Set(t *Thread, x float64) { *v = float64V(x) }
-
-/*
- * Ideal float
- */
-
-type idealFloatV struct {
-       V *big.Rat
-}
-
-func (v *idealFloatV) String() string { return v.V.FloatString(6) }
-
-func (v *idealFloatV) Assign(t *Thread, o Value) {
-       v.V = o.(IdealFloatValue).Get()
-}
-
-func (v *idealFloatV) Get() *big.Rat { return v.V }
-
-/*
- * String
- */
-
-type stringV string
-
-func (v *stringV) String() string { return fmt.Sprint(*v) }
-
-func (v *stringV) Assign(t *Thread, o Value) { *v = stringV(o.(StringValue).Get(t)) }
-
-func (v *stringV) Get(*Thread) string { return string(*v) }
-
-func (v *stringV) Set(t *Thread, x string) { *v = stringV(x) }
-
-/*
- * Array
- */
-
-type arrayV []Value
-
-func (v *arrayV) String() string {
-       res := "{"
-       for i, e := range *v {
-               if i > 0 {
-                       res += ", "
-               }
-               res += e.String()
-       }
-       return res + "}"
-}
-
-func (v *arrayV) Assign(t *Thread, o Value) {
-       oa := o.(ArrayValue)
-       l := int64(len(*v))
-       for i := int64(0); i < l; i++ {
-               (*v)[i].Assign(t, oa.Elem(t, i))
-       }
-}
-
-func (v *arrayV) Get(*Thread) ArrayValue { return v }
-
-func (v *arrayV) Elem(t *Thread, i int64) Value {
-       return (*v)[i]
-}
-
-func (v *arrayV) Sub(i int64, len int64) ArrayValue {
-       res := (*v)[i : i+len]
-       return &res
-}
-
-/*
- * Struct
- */
-
-type structV []Value
-
-// TODO(austin) Should these methods (and arrayV's) be on structV
-// instead of *structV?
-func (v *structV) String() string {
-       res := "{"
-       for i, v := range *v {
-               if i > 0 {
-                       res += ", "
-               }
-               res += v.String()
-       }
-       return res + "}"
-}
-
-func (v *structV) Assign(t *Thread, o Value) {
-       oa := o.(StructValue)
-       l := len(*v)
-       for i := 0; i < l; i++ {
-               (*v)[i].Assign(t, oa.Field(t, i))
-       }
-}
-
-func (v *structV) Get(*Thread) StructValue { return v }
-
-func (v *structV) Field(t *Thread, i int) Value {
-       return (*v)[i]
-}
-
-/*
- * Pointer
- */
-
-type ptrV struct {
-       // nil if the pointer is nil
-       target Value
-}
-
-func (v *ptrV) String() string {
-       if v.target == nil {
-               return "<nil>"
-       }
-       return "&" + v.target.String()
-}
-
-func (v *ptrV) Assign(t *Thread, o Value) { v.target = o.(PtrValue).Get(t) }
-
-func (v *ptrV) Get(*Thread) Value { return v.target }
-
-func (v *ptrV) Set(t *Thread, x Value) { v.target = x }
-
-/*
- * Functions
- */
-
-type funcV struct {
-       target Func
-}
-
-func (v *funcV) String() string {
-       // TODO(austin) Rob wants to see the definition
-       return "func {...}"
-}
-
-func (v *funcV) Assign(t *Thread, o Value) { v.target = o.(FuncValue).Get(t) }
-
-func (v *funcV) Get(*Thread) Func { return v.target }
-
-func (v *funcV) Set(t *Thread, x Func) { v.target = x }
-
-/*
- * Interfaces
- */
-
-type interfaceV struct {
-       Interface
-}
-
-func (v *interfaceV) String() string {
-       if v.Type == nil || v.Value == nil {
-               return "<nil>"
-       }
-       return v.Value.String()
-}
-
-func (v *interfaceV) Assign(t *Thread, o Value) {
-       v.Interface = o.(InterfaceValue).Get(t)
-}
-
-func (v *interfaceV) Get(*Thread) Interface { return v.Interface }
-
-func (v *interfaceV) Set(t *Thread, x Interface) {
-       v.Interface = x
-}
-
-/*
- * Slices
- */
-
-type sliceV struct {
-       Slice
-}
-
-func (v *sliceV) String() string {
-       if v.Base == nil {
-               return "<nil>"
-       }
-       return v.Base.Sub(0, v.Len).String()
-}
-
-func (v *sliceV) Assign(t *Thread, o Value) { v.Slice = o.(SliceValue).Get(t) }
-
-func (v *sliceV) Get(*Thread) Slice { return v.Slice }
-
-func (v *sliceV) Set(t *Thread, x Slice) { v.Slice = x }
-
-/*
- * Maps
- */
-
-type mapV struct {
-       target Map
-}
-
-func (v *mapV) String() string {
-       if v.target == nil {
-               return "<nil>"
-       }
-       res := "map["
-       i := 0
-       v.target.Iter(func(key interface{}, val Value) bool {
-               if i > 0 {
-                       res += ", "
-               }
-               i++
-               res += fmt.Sprint(key) + ":" + val.String()
-               return true
-       })
-       return res + "]"
-}
-
-func (v *mapV) Assign(t *Thread, o Value) { v.target = o.(MapValue).Get(t) }
-
-func (v *mapV) Get(*Thread) Map { return v.target }
-
-func (v *mapV) Set(t *Thread, x Map) { v.target = x }
-
-type evalMap map[interface{}]Value
-
-func (m evalMap) Len(t *Thread) int64 { return int64(len(m)) }
-
-func (m evalMap) Elem(t *Thread, key interface{}) Value {
-       return m[key]
-}
-
-func (m evalMap) SetElem(t *Thread, key interface{}, val Value) {
-       if val == nil {
-               m[key] = nil, false
-       } else {
-               m[key] = val
-       }
-}
-
-func (m evalMap) Iter(cb func(key interface{}, val Value) bool) {
-       for k, v := range m {
-               if !cb(k, v) {
-                       break
-               }
-       }
-}
-
-/*
- * Multi-values
- */
-
-type multiV []Value
-
-func (v multiV) String() string {
-       res := "("
-       for i, v := range v {
-               if i > 0 {
-                       res += ", "
-               }
-               res += v.String()
-       }
-       return res + ")"
-}
-
-func (v multiV) Assign(t *Thread, o Value) {
-       omv := o.(multiV)
-       for i := range v {
-               v[i].Assign(t, omv[i])
-       }
-}
-
-/*
- * Universal constants
- */
-
-func init() {
-       s := universe
-
-       true := boolV(true)
-       s.DefineConst("true", universePos, BoolType, &true)
-       false := boolV(false)
-       s.DefineConst("false", universePos, BoolType, &false)
-}
diff --git a/src/pkg/exp/eval/world.go b/src/pkg/exp/eval/world.go
deleted file mode 100644 (file)
index a5f6ac7..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package eval is the beginning of an interpreter for Go.
-// It can run simple Go programs but does not implement
-// interface values or packages.
-package eval
-
-import (
-       "go/ast"
-       "go/parser"
-       "go/scanner"
-       "go/token"
-       "os"
-)
-
-type World struct {
-       scope *Scope
-       frame *Frame
-}
-
-func NewWorld() *World {
-       w := new(World)
-       w.scope = universe.ChildScope()
-       w.scope.global = true // this block's vars allocate directly
-       return w
-}
-
-type Code interface {
-       // The type of the value Run returns, or nil if Run returns nil.
-       Type() Type
-
-       // Run runs the code; if the code is a single expression
-       // with a value, it returns the value; otherwise it returns nil.
-       Run() (Value, os.Error)
-}
-
-type stmtCode struct {
-       w    *World
-       code code
-}
-
-func (w *World) CompileStmtList(fset *token.FileSet, stmts []ast.Stmt) (Code, os.Error) {
-       if len(stmts) == 1 {
-               if s, ok := stmts[0].(*ast.ExprStmt); ok {
-                       return w.CompileExpr(fset, s.X)
-               }
-       }
-       errors := new(scanner.ErrorVector)
-       cc := &compiler{fset, errors, 0, 0}
-       cb := newCodeBuf()
-       fc := &funcCompiler{
-               compiler:     cc,
-               fnType:       nil,
-               outVarsNamed: false,
-               codeBuf:      cb,
-               flow:         newFlowBuf(cb),
-               labels:       make(map[string]*label),
-       }
-       bc := &blockCompiler{
-               funcCompiler: fc,
-               block:        w.scope.block,
-       }
-       nerr := cc.numError()
-       for _, stmt := range stmts {
-               bc.compileStmt(stmt)
-       }
-       fc.checkLabels()
-       if nerr != cc.numError() {
-               return nil, errors.GetError(scanner.Sorted)
-       }
-       return &stmtCode{w, fc.get()}, nil
-}
-
-func (w *World) CompileDeclList(fset *token.FileSet, decls []ast.Decl) (Code, os.Error) {
-       stmts := make([]ast.Stmt, len(decls))
-       for i, d := range decls {
-               stmts[i] = &ast.DeclStmt{d}
-       }
-       return w.CompileStmtList(fset, stmts)
-}
-
-func (s *stmtCode) Type() Type { return nil }
-
-func (s *stmtCode) Run() (Value, os.Error) {
-       t := new(Thread)
-       t.f = s.w.scope.NewFrame(nil)
-       return nil, t.Try(func(t *Thread) { s.code.exec(t) })
-}
-
-type exprCode struct {
-       w    *World
-       e    *expr
-       eval func(Value, *Thread)
-}
-
-func (w *World) CompileExpr(fset *token.FileSet, e ast.Expr) (Code, os.Error) {
-       errors := new(scanner.ErrorVector)
-       cc := &compiler{fset, errors, 0, 0}
-
-       ec := cc.compileExpr(w.scope.block, false, e)
-       if ec == nil {
-               return nil, errors.GetError(scanner.Sorted)
-       }
-       var eval func(Value, *Thread)
-       switch t := ec.t.(type) {
-       case *idealIntType:
-               // nothing
-       case *idealFloatType:
-               // nothing
-       default:
-               if tm, ok := t.(*MultiType); ok && len(tm.Elems) == 0 {
-                       return &stmtCode{w, code{ec.exec}}, nil
-               }
-               eval = genAssign(ec.t, ec)
-       }
-       return &exprCode{w, ec, eval}, nil
-}
-
-func (e *exprCode) Type() Type { return e.e.t }
-
-func (e *exprCode) Run() (Value, os.Error) {
-       t := new(Thread)
-       t.f = e.w.scope.NewFrame(nil)
-       switch e.e.t.(type) {
-       case *idealIntType:
-               return &idealIntV{e.e.asIdealInt()()}, nil
-       case *idealFloatType:
-               return &idealFloatV{e.e.asIdealFloat()()}, nil
-       }
-       v := e.e.t.Zero()
-       eval := e.eval
-       err := t.Try(func(t *Thread) { eval(v, t) })
-       return v, err
-}
-
-func (w *World) Compile(fset *token.FileSet, text string) (Code, os.Error) {
-       stmts, err := parser.ParseStmtList(fset, "input", text)
-       if err == nil {
-               return w.CompileStmtList(fset, stmts)
-       }
-
-       // Otherwise try as DeclList.
-       decls, err1 := parser.ParseDeclList(fset, "input", text)
-       if err1 == nil {
-               return w.CompileDeclList(fset, decls)
-       }
-
-       // Have to pick an error.
-       // Parsing as statement list admits more forms,
-       // its error is more likely to be useful.
-       return nil, err
-}
-
-type RedefinitionError struct {
-       Name string
-       Prev Def
-}
-
-func (e *RedefinitionError) String() string {
-       res := "identifier " + e.Name + " redeclared"
-       pos := e.Prev.Pos()
-       if pos.IsValid() {
-               // TODO: fix this - currently this code is not reached by the tests
-               //       need to get a file set (fset) from somewhere
-               //res += "; previous declaration at " + fset.Position(pos).String()
-               panic(0)
-       }
-       return res
-}
-
-func (w *World) DefineConst(name string, t Type, val Value) os.Error {
-       _, prev := w.scope.DefineConst(name, token.NoPos, t, val)
-       if prev != nil {
-               return &RedefinitionError{name, prev}
-       }
-       return nil
-}
-
-func (w *World) DefineVar(name string, t Type, val Value) os.Error {
-       v, prev := w.scope.DefineVar(name, token.NoPos, t)
-       if prev != nil {
-               return &RedefinitionError{name, prev}
-       }
-       v.Init = val
-       return nil
-}
diff --git a/src/pkg/exp/ogle/Makefile b/src/pkg/exp/ogle/Makefile
deleted file mode 100644 (file)
index ef65d36..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/ogle
-GOFILES=\
-       abort.go\
-       arch.go\
-       cmd.go\
-       event.go\
-       frame.go\
-       goroutine.go\
-       rruntime.go\
-       rtype.go\
-       rvalue.go\
-       process.go\
-       vars.go\
-
-CLEANFILES+=ogle
-
-include ../../../Make.pkg
-
-main.$O: main.go package
-       $(GC) -I_obj $<
-
-ogle: main.$O
-       $(LD) -L_obj -o $@ $<
diff --git a/src/pkg/exp/ogle/abort.go b/src/pkg/exp/ogle/abort.go
deleted file mode 100644 (file)
index 311a7b3..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "os"
-       "runtime"
-)
-
-// An aborter aborts the thread's current computation, usually
-// passing the error to a waiting thread.
-type aborter interface {
-       Abort(err os.Error)
-}
-
-type ogleAborter chan os.Error
-
-func (a ogleAborter) Abort(err os.Error) {
-       a <- err
-       runtime.Goexit()
-}
-
-// try executes a computation; if the computation Aborts, try returns
-// the error passed to abort.
-func try(f func(a aborter)) os.Error {
-       a := make(ogleAborter)
-       go func() {
-               f(a)
-               a <- nil
-       }()
-       err := <-a
-       return err
-}
diff --git a/src/pkg/exp/ogle/arch.go b/src/pkg/exp/ogle/arch.go
deleted file mode 100644 (file)
index 52b1c97..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "math"
-)
-
-type Arch interface {
-       // ToWord converts an array of up to 8 bytes in memory order
-       // to a word.
-       ToWord(data []byte) proc.Word
-       // FromWord converts a word to an array of up to 8 bytes in
-       // memory order.
-       FromWord(v proc.Word, out []byte)
-       // ToFloat32 converts a word to a float.  The order of this
-       // word will be the order returned by ToWord on the memory
-       // representation of a float, and thus may require reversing.
-       ToFloat32(bits uint32) float32
-       // FromFloat32 converts a float to a word.  This should return
-       // a word that can be passed to FromWord to get the memory
-       // representation of a float on this architecture.
-       FromFloat32(f float32) uint32
-       // ToFloat64 is to float64 as ToFloat32 is to float32.
-       ToFloat64(bits uint64) float64
-       // FromFloat64 is to float64 as FromFloat32 is to float32.
-       FromFloat64(f float64) uint64
-
-       // IntSize returns the number of bytes in an 'int'.
-       IntSize() int
-       // PtrSize returns the number of bytes in a 'uintptr'.
-       PtrSize() int
-       // FloatSize returns the number of bytes in a 'float'.
-       FloatSize() int
-       // Align rounds offset up to the appropriate offset for a
-       // basic type with the given width.
-       Align(offset, width int) int
-
-       // G returns the current G pointer.
-       G(regs proc.Regs) proc.Word
-
-       // ClosureSize returns the number of bytes expected by
-       // ParseClosure.
-       ClosureSize() int
-       // ParseClosure takes ClosureSize bytes read from a return PC
-       // in a remote process, determines if the code is a closure,
-       // and returns the frame size of the closure if it is.
-       ParseClosure(data []byte) (frame int, ok bool)
-}
-
-type ArchLSB struct{}
-
-func (ArchLSB) ToWord(data []byte) proc.Word {
-       var v proc.Word
-       for i, b := range data {
-               v |= proc.Word(b) << (uint(i) * 8)
-       }
-       return v
-}
-
-func (ArchLSB) FromWord(v proc.Word, out []byte) {
-       for i := range out {
-               out[i] = byte(v)
-               v >>= 8
-       }
-}
-
-func (ArchLSB) ToFloat32(bits uint32) float32 {
-       // TODO(austin) Do these definitions depend on my current
-       // architecture?
-       return math.Float32frombits(bits)
-}
-
-func (ArchLSB) FromFloat32(f float32) uint32 { return math.Float32bits(f) }
-
-func (ArchLSB) ToFloat64(bits uint64) float64 { return math.Float64frombits(bits) }
-
-func (ArchLSB) FromFloat64(f float64) uint64 { return math.Float64bits(f) }
-
-type ArchAlignedMultiple struct{}
-
-func (ArchAlignedMultiple) Align(offset, width int) int {
-       return ((offset - 1) | (width - 1)) + 1
-}
-
-type amd64 struct {
-       ArchLSB
-       ArchAlignedMultiple
-       gReg int
-}
-
-func (a *amd64) IntSize() int { return 4 }
-
-func (a *amd64) PtrSize() int { return 8 }
-
-func (a *amd64) FloatSize() int { return 4 }
-
-func (a *amd64) G(regs proc.Regs) proc.Word {
-       // See src/pkg/runtime/mkasmh
-       if a.gReg == -1 {
-               ns := regs.Names()
-               for i, n := range ns {
-                       if n == "r15" {
-                               a.gReg = i
-                               break
-                       }
-               }
-       }
-
-       return regs.Get(a.gReg)
-}
-
-func (a *amd64) ClosureSize() int { return 8 }
-
-func (a *amd64) ParseClosure(data []byte) (int, bool) {
-       if data[0] == 0x48 && data[1] == 0x81 && data[2] == 0xc4 && data[7] == 0xc3 {
-               return int(a.ToWord(data[3:7]) + 8), true
-       }
-       return 0, false
-}
-
-var Amd64 = &amd64{gReg: -1}
diff --git a/src/pkg/exp/ogle/cmd.go b/src/pkg/exp/ogle/cmd.go
deleted file mode 100644 (file)
index ff0d24c..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ogle is the beginning of a debugger for Go.
-package ogle
-
-import (
-       "bufio"
-       "debug/elf"
-       "debug/proc"
-       "exp/eval"
-       "fmt"
-       "go/scanner"
-       "go/token"
-       "os"
-       "strconv"
-       "strings"
-)
-
-var fset = token.NewFileSet()
-var world *eval.World
-var curProc *Process
-
-func Main() {
-       world = eval.NewWorld()
-       defineFuncs()
-       r := bufio.NewReader(os.Stdin)
-       for {
-               print("; ")
-               line, err := r.ReadSlice('\n')
-               if err != nil {
-                       break
-               }
-
-               // Try line as a command
-               cmd, rest := getCmd(line)
-               if cmd != nil {
-                       err := cmd.handler(rest)
-                       if err != nil {
-                               scanner.PrintError(os.Stderr, err)
-                       }
-                       continue
-               }
-
-               // Try line as code
-               code, err := world.Compile(fset, string(line))
-               if err != nil {
-                       scanner.PrintError(os.Stderr, err)
-                       continue
-               }
-               v, err := code.Run()
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, err.String())
-                       continue
-               }
-               if v != nil {
-                       println(v.String())
-               }
-       }
-}
-
-// newScanner creates a new scanner that scans that given input bytes.
-func newScanner(input []byte) (*scanner.Scanner, *scanner.ErrorVector) {
-       sc := new(scanner.Scanner)
-       ev := new(scanner.ErrorVector)
-       file := fset.AddFile("input", fset.Base(), len(input))
-       sc.Init(file, input, ev, 0)
-       return sc, ev
-}
-
-/*
- * Commands
- */
-
-// A UsageError occurs when a command is called with illegal arguments.
-type UsageError string
-
-func (e UsageError) String() string { return string(e) }
-
-// A cmd represents a single command with a handler.
-type cmd struct {
-       cmd     string
-       handler func([]byte) os.Error
-}
-
-var cmds = []cmd{
-       {"load", cmdLoad},
-       {"bt", cmdBt},
-}
-
-// getCmd attempts to parse an input line as a registered command.  If
-// successful, it returns the command and the bytes remaining after
-// the command, which should be passed to the command.
-func getCmd(line []byte) (*cmd, []byte) {
-       sc, _ := newScanner(line)
-       pos, tok, lit := sc.Scan()
-       if sc.ErrorCount != 0 || tok != token.IDENT {
-               return nil, nil
-       }
-
-       slit := string(lit)
-       for i := range cmds {
-               if cmds[i].cmd == slit {
-                       return &cmds[i], line[fset.Position(pos).Offset+len(lit):]
-               }
-       }
-       return nil, nil
-}
-
-// cmdLoad starts or attaches to a process.  Its form is similar to
-// import:
-//
-//  load [sym] "path" [;]
-//
-// sym specifies the name to give to the process.  If not given, the
-// name is derived from the path of the process.  If ".", then the
-// packages from the remote process are defined into the current
-// namespace.  If given, this symbol is defined as a package
-// containing the process' packages.
-//
-// path gives the path of the process to start or attach to.  If it is
-// "pid:<num>", then attach to the given PID.  Otherwise, treat it as
-// a file path and space-separated arguments and start a new process.
-//
-// load always sets the current process to the loaded process.
-func cmdLoad(args []byte) os.Error {
-       ident, path, err := parseLoad(args)
-       if err != nil {
-               return err
-       }
-       if curProc != nil {
-               return UsageError("multiple processes not implemented")
-       }
-       if ident != "." {
-               return UsageError("process identifiers not implemented")
-       }
-
-       // Parse argument and start or attach to process
-       var fname string
-       var tproc proc.Process
-       if len(path) >= 4 && path[0:4] == "pid:" {
-               pid, err := strconv.Atoi(path[4:])
-               if err != nil {
-                       return err
-               }
-               fname, err = os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
-               if err != nil {
-                       return err
-               }
-               tproc, err = proc.Attach(pid)
-               if err != nil {
-                       return err
-               }
-               println("Attached to", pid)
-       } else {
-               parts := strings.Split(path, " ")
-               if len(parts) == 0 {
-                       fname = ""
-               } else {
-                       fname = parts[0]
-               }
-               tproc, err = proc.StartProcess(fname, parts, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
-               if err != nil {
-                       return err
-               }
-               println("Started", path)
-               // TODO(austin) If we fail after this point, kill tproc
-               // before detaching.
-       }
-
-       // Get symbols
-       f, err := os.Open(fname)
-       if err != nil {
-               tproc.Detach()
-               return err
-       }
-       defer f.Close()
-       elf, err := elf.NewFile(f)
-       if err != nil {
-               tproc.Detach()
-               return err
-       }
-       curProc, err = NewProcessElf(tproc, elf)
-       if err != nil {
-               tproc.Detach()
-               return err
-       }
-
-       // Prepare new process
-       curProc.OnGoroutineCreate().AddHandler(EventPrint)
-       curProc.OnGoroutineExit().AddHandler(EventPrint)
-
-       err = curProc.populateWorld(world)
-       if err != nil {
-               tproc.Detach()
-               return err
-       }
-
-       return nil
-}
-
-func parseLoad(args []byte) (ident string, path string, err os.Error) {
-       err = UsageError("Usage: load [sym] \"path\"")
-       sc, ev := newScanner(args)
-
-       var toks [4]token.Token
-       var lits [4]string
-       for i := range toks {
-               _, toks[i], lits[i] = sc.Scan()
-       }
-       if sc.ErrorCount != 0 {
-               err = ev.GetError(scanner.NoMultiples)
-               return
-       }
-
-       i := 0
-       switch toks[i] {
-       case token.PERIOD, token.IDENT:
-               ident = string(lits[i])
-               i++
-       }
-
-       if toks[i] != token.STRING {
-               return
-       }
-       path, uerr := strconv.Unquote(string(lits[i]))
-       if uerr != nil {
-               err = uerr
-               return
-       }
-       i++
-
-       if toks[i] == token.SEMICOLON {
-               i++
-       }
-       if toks[i] != token.EOF {
-               return
-       }
-
-       return ident, path, nil
-}
-
-// cmdBt prints a backtrace for the current goroutine.  It takes no
-// arguments.
-func cmdBt(args []byte) os.Error {
-       err := parseNoArgs(args, "Usage: bt")
-       if err != nil {
-               return err
-       }
-
-       if curProc == nil || curProc.curGoroutine == nil {
-               return NoCurrentGoroutine{}
-       }
-
-       f := curProc.curGoroutine.frame
-       if f == nil {
-               fmt.Println("No frames on stack")
-               return nil
-       }
-
-       for f.Inner() != nil {
-               f = f.Inner()
-       }
-
-       for i := 0; i < 100; i++ {
-               if f == curProc.curGoroutine.frame {
-                       fmt.Printf("=> ")
-               } else {
-                       fmt.Printf("   ")
-               }
-               fmt.Printf("%8x %v\n", f.pc, f)
-               f, err = f.Outer()
-               if err != nil {
-                       return err
-               }
-               if f == nil {
-                       return nil
-               }
-       }
-
-       fmt.Println("...")
-       return nil
-}
-
-func parseNoArgs(args []byte, usage string) os.Error {
-       sc, ev := newScanner(args)
-       _, tok, _ := sc.Scan()
-       if sc.ErrorCount != 0 {
-               return ev.GetError(scanner.NoMultiples)
-       }
-       if tok != token.EOF {
-               return UsageError(usage)
-       }
-       return nil
-}
-
-/*
- * Functions
- */
-
-// defineFuncs populates world with the built-in functions.
-func defineFuncs() {
-       t, v := eval.FuncFromNativeTyped(fnOut, fnOutSig)
-       world.DefineConst("Out", t, v)
-       t, v = eval.FuncFromNativeTyped(fnContWait, fnContWaitSig)
-       world.DefineConst("ContWait", t, v)
-       t, v = eval.FuncFromNativeTyped(fnBpSet, fnBpSetSig)
-       world.DefineConst("BpSet", t, v)
-}
-
-// printCurFrame prints the current stack frame, as it would appear in
-// a backtrace.
-func printCurFrame() {
-       if curProc == nil || curProc.curGoroutine == nil {
-               return
-       }
-       f := curProc.curGoroutine.frame
-       if f == nil {
-               return
-       }
-       fmt.Printf("=> %8x %v\n", f.pc, f)
-}
-
-// fnOut moves the current frame to the caller of the current frame.
-func fnOutSig() {}
-func fnOut(t *eval.Thread, args []eval.Value, res []eval.Value) {
-       if curProc == nil {
-               t.Abort(NoCurrentGoroutine{})
-       }
-       err := curProc.Out()
-       if err != nil {
-               t.Abort(err)
-       }
-       // TODO(austin) Only in the command form
-       printCurFrame()
-}
-
-// fnContWait continues the current process and waits for a stopping event.
-func fnContWaitSig() {}
-func fnContWait(t *eval.Thread, args []eval.Value, res []eval.Value) {
-       if curProc == nil {
-               t.Abort(NoCurrentGoroutine{})
-       }
-       err := curProc.ContWait()
-       if err != nil {
-               t.Abort(err)
-       }
-       // TODO(austin) Only in the command form
-       ev := curProc.Event()
-       if ev != nil {
-               fmt.Printf("%v\n", ev)
-       }
-       printCurFrame()
-}
-
-// fnBpSet sets a breakpoint at the entry to the named function.
-func fnBpSetSig(string) {}
-func fnBpSet(t *eval.Thread, args []eval.Value, res []eval.Value) {
-       // TODO(austin) This probably shouldn't take a symbol name.
-       // Perhaps it should take an interface that provides PC's.
-       // Functions and instructions can implement that interface and
-       // we can have something to translate file:line pairs.
-       if curProc == nil {
-               t.Abort(NoCurrentGoroutine{})
-       }
-       name := args[0].(eval.StringValue).Get(t)
-       fn := curProc.syms.LookupFunc(name)
-       if fn == nil {
-               t.Abort(UsageError("no such function " + name))
-       }
-       curProc.OnBreakpoint(proc.Word(fn.Entry)).AddHandler(EventStop)
-}
diff --git a/src/pkg/exp/ogle/event.go b/src/pkg/exp/ogle/event.go
deleted file mode 100644 (file)
index d7092de..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "fmt"
-       "os"
-)
-
-/*
- * Hooks and events
- */
-
-// An EventHandler is a function that takes an event and returns a
-// response to that event and possibly an error.  If an event handler
-// returns an error, the process stops and no other handlers for that
-// event are executed.
-type EventHandler func(e Event) (EventAction, os.Error)
-
-// An EventAction is an event handler's response to an event.  If all
-// of an event's handlers execute without returning errors, their
-// results are combined as follows: If any handler returned
-// EAContinue, then the process resumes (without returning from
-// WaitStop); otherwise, if any handler returned EAStop, the process
-// remains stopped; otherwise, if all handlers returned EADefault, the
-// process resumes.  A handler may return EARemoveSelf bit-wise or'd
-// with any other action to indicate that the handler should be
-// removed from the hook.
-type EventAction int
-
-const (
-       EARemoveSelf EventAction = 0x100
-       EADefault    EventAction = iota
-       EAStop
-       EAContinue
-)
-
-// A EventHook allows event handlers to be added and removed.
-type EventHook interface {
-       AddHandler(EventHandler)
-       RemoveHandler(EventHandler)
-       NumHandler() int
-       handle(e Event) (EventAction, os.Error)
-       String() string
-}
-
-// EventHook is almost, but not quite, suitable for user-defined
-// events.  If we want user-defined events, make EventHook a struct,
-// special-case adding and removing handlers in breakpoint hooks, and
-// provide a public interface for posting events to hooks.
-
-type Event interface {
-       Process() *Process
-       Goroutine() *Goroutine
-       String() string
-}
-
-type commonHook struct {
-       // Head of handler chain
-       head *handler
-       // Number of non-internal handlers
-       len int
-}
-
-type handler struct {
-       eh EventHandler
-       // True if this handler must be run before user-defined
-       // handlers in order to ensure correctness.
-       internal bool
-       // True if this handler has been removed from the chain.
-       removed bool
-       next    *handler
-}
-
-func (h *commonHook) AddHandler(eh EventHandler) {
-       h.addHandler(eh, false)
-}
-
-func (h *commonHook) addHandler(eh EventHandler, internal bool) {
-       // Ensure uniqueness of handlers
-       h.RemoveHandler(eh)
-
-       if !internal {
-               h.len++
-       }
-       // Add internal handlers to the beginning
-       if internal || h.head == nil {
-               h.head = &handler{eh, internal, false, h.head}
-               return
-       }
-       // Add handler after internal handlers
-       // TODO(austin) This should probably go on the end instead
-       prev := h.head
-       for prev.next != nil && prev.internal {
-               prev = prev.next
-       }
-       prev.next = &handler{eh, internal, false, prev.next}
-}
-
-func (h *commonHook) RemoveHandler(eh EventHandler) {
-       plink := &h.head
-       for l := *plink; l != nil; plink, l = &l.next, l.next {
-               if l.eh == eh {
-                       if !l.internal {
-                               h.len--
-                       }
-                       l.removed = true
-                       *plink = l.next
-                       break
-               }
-       }
-}
-
-func (h *commonHook) NumHandler() int { return h.len }
-
-func (h *commonHook) handle(e Event) (EventAction, os.Error) {
-       action := EADefault
-       plink := &h.head
-       for l := *plink; l != nil; plink, l = &l.next, l.next {
-               if l.removed {
-                       continue
-               }
-               a, err := l.eh(e)
-               if a&EARemoveSelf == EARemoveSelf {
-                       if !l.internal {
-                               h.len--
-                       }
-                       l.removed = true
-                       *plink = l.next
-                       a &^= EARemoveSelf
-               }
-               if err != nil {
-                       return EAStop, err
-               }
-               if a > action {
-                       action = a
-               }
-       }
-       return action, nil
-}
-
-type commonEvent struct {
-       // The process of this event
-       p *Process
-       // The goroutine of this event.
-       t *Goroutine
-}
-
-func (e *commonEvent) Process() *Process { return e.p }
-
-func (e *commonEvent) Goroutine() *Goroutine { return e.t }
-
-/*
- * Standard event handlers
- */
-
-// EventPrint is a standard event handler that prints events as they
-// occur.  It will not cause the process to stop.
-func EventPrint(ev Event) (EventAction, os.Error) {
-       // TODO(austin) Include process name here?
-       fmt.Fprintf(os.Stderr, "*** %v\n", ev.String())
-       return EADefault, nil
-}
-
-// EventStop is a standard event handler that causes the process to stop.
-func EventStop(ev Event) (EventAction, os.Error) {
-       return EAStop, nil
-}
-
-/*
- * Breakpoints
- */
-
-type breakpointHook struct {
-       commonHook
-       p  *Process
-       pc proc.Word
-}
-
-// A Breakpoint event occurs when a process reaches a particular
-// program counter.  When this event is handled, the current goroutine
-// will be the goroutine that reached the program counter.
-type Breakpoint struct {
-       commonEvent
-       osThread proc.Thread
-       pc       proc.Word
-}
-
-func (h *breakpointHook) AddHandler(eh EventHandler) {
-       h.addHandler(eh, false)
-}
-
-func (h *breakpointHook) addHandler(eh EventHandler, internal bool) {
-       // We register breakpoint events lazily to avoid holding
-       // references to breakpoints without handlers.  Be sure to use
-       // the "canonical" breakpoint if there is one.
-       if cur, ok := h.p.breakpointHooks[h.pc]; ok {
-               h = cur
-       }
-       oldhead := h.head
-       h.commonHook.addHandler(eh, internal)
-       if oldhead == nil && h.head != nil {
-               h.p.proc.AddBreakpoint(h.pc)
-               h.p.breakpointHooks[h.pc] = h
-       }
-}
-
-func (h *breakpointHook) RemoveHandler(eh EventHandler) {
-       oldhead := h.head
-       h.commonHook.RemoveHandler(eh)
-       if oldhead != nil && h.head == nil {
-               h.p.proc.RemoveBreakpoint(h.pc)
-               h.p.breakpointHooks[h.pc] = nil, false
-       }
-}
-
-func (h *breakpointHook) String() string {
-       // TODO(austin) Include process name?
-       // TODO(austin) Use line:pc or at least sym+%#x
-       return fmt.Sprintf("breakpoint at %#x", h.pc)
-}
-
-func (b *Breakpoint) PC() proc.Word { return b.pc }
-
-func (b *Breakpoint) String() string {
-       // TODO(austin) Include process name and goroutine
-       // TODO(austin) Use line:pc or at least sym+%#x
-       return fmt.Sprintf("breakpoint at %#x", b.pc)
-}
-
-/*
- * Goroutine create/exit
- */
-
-type goroutineCreateHook struct {
-       commonHook
-}
-
-func (h *goroutineCreateHook) String() string { return "goroutine create" }
-
-// A GoroutineCreate event occurs when a process creates a new
-// goroutine.  When this event is handled, the current goroutine will
-// be the newly created goroutine.
-type GoroutineCreate struct {
-       commonEvent
-       parent *Goroutine
-}
-
-// Parent returns the goroutine that created this goroutine.  May be
-// nil if this event is the creation of the first goroutine.
-func (e *GoroutineCreate) Parent() *Goroutine { return e.parent }
-
-func (e *GoroutineCreate) String() string {
-       // TODO(austin) Include process name
-       if e.parent == nil {
-               return fmt.Sprintf("%v created", e.t)
-       }
-       return fmt.Sprintf("%v created by %v", e.t, e.parent)
-}
-
-type goroutineExitHook struct {
-       commonHook
-}
-
-func (h *goroutineExitHook) String() string { return "goroutine exit" }
-
-// A GoroutineExit event occurs when a Go goroutine exits.
-type GoroutineExit struct {
-       commonEvent
-}
-
-func (e *GoroutineExit) String() string {
-       // TODO(austin) Include process name
-       //return fmt.Sprintf("%v exited", e.t);
-       // For debugging purposes
-       return fmt.Sprintf("goroutine %#x exited", e.t.g.addr().base)
-}
diff --git a/src/pkg/exp/ogle/frame.go b/src/pkg/exp/ogle/frame.go
deleted file mode 100644 (file)
index 1538362..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/gosym"
-       "debug/proc"
-       "fmt"
-       "os"
-)
-
-// A Frame represents a single frame on a remote call stack.
-type Frame struct {
-       // pc is the PC of the next instruction that will execute in
-       // this frame.  For lower frames, this is the instruction
-       // following the CALL instruction.
-       pc, sp, fp proc.Word
-       // The runtime.Stktop of the active stack segment
-       stk remoteStruct
-       // The function this stack frame is in
-       fn *gosym.Func
-       // The path and line of the CALL or current instruction.  Note
-       // that this differs slightly from the meaning of Frame.pc.
-       path string
-       line int
-       // The inner and outer frames of this frame.  outer is filled
-       // in lazily.
-       inner, outer *Frame
-}
-
-// newFrame returns the top-most Frame of the given g's thread.
-func newFrame(g remoteStruct) (*Frame, os.Error) {
-       var f *Frame
-       err := try(func(a aborter) { f = aNewFrame(a, g) })
-       return f, err
-}
-
-func aNewFrame(a aborter, g remoteStruct) *Frame {
-       p := g.r.p
-       var pc, sp proc.Word
-
-       // Is this G alive?
-       switch g.field(p.f.G.Status).(remoteInt).aGet(a) {
-       case p.runtime.Gidle, p.runtime.Gmoribund, p.runtime.Gdead:
-               return nil
-       }
-
-       // Find the OS thread for this G
-
-       // TODO(austin) Ideally, we could look at the G's state and
-       // figure out if it's on an OS thread or not.  However, this
-       // is difficult because the state isn't updated atomically
-       // with scheduling changes.
-       for _, t := range p.proc.Threads() {
-               regs, err := t.Regs()
-               if err != nil {
-                       // TODO(austin) What to do?
-                       continue
-               }
-               thisg := p.G(regs)
-               if thisg == g.addr().base {
-                       // Found this G's OS thread
-                       pc = regs.PC()
-                       sp = regs.SP()
-
-                       // If this thread crashed, try to recover it
-                       if pc == 0 {
-                               pc = p.peekUintptr(a, pc)
-                               sp += 8
-                       }
-
-                       break
-               }
-       }
-
-       if pc == 0 && sp == 0 {
-               // G is not mapped to an OS thread.  Use the
-               // scheduler's stored PC and SP.
-               sched := g.field(p.f.G.Sched).(remoteStruct)
-               pc = proc.Word(sched.field(p.f.Gobuf.Pc).(remoteUint).aGet(a))
-               sp = proc.Word(sched.field(p.f.Gobuf.Sp).(remoteUint).aGet(a))
-       }
-
-       // Get Stktop
-       stk := g.field(p.f.G.Stackbase).(remotePtr).aGet(a).(remoteStruct)
-
-       return prepareFrame(a, pc, sp, stk, nil)
-}
-
-// prepareFrame creates a Frame from the PC and SP within that frame,
-// as well as the active stack segment.  This function takes care of
-// traversing stack breaks and unwinding closures.
-func prepareFrame(a aborter, pc, sp proc.Word, stk remoteStruct, inner *Frame) *Frame {
-       // Based on src/pkg/runtime/amd64/traceback.c:traceback
-       p := stk.r.p
-       top := inner == nil
-
-       // Get function
-       var path string
-       var line int
-       var fn *gosym.Func
-
-       for i := 0; i < 100; i++ {
-               // Traverse segmented stack breaks
-               if p.sys.lessstack != nil && pc == proc.Word(p.sys.lessstack.Value) {
-                       // Get stk->gobuf.pc
-                       pc = proc.Word(stk.field(p.f.Stktop.Gobuf).(remoteStruct).field(p.f.Gobuf.Pc).(remoteUint).aGet(a))
-                       // Get stk->gobuf.sp
-                       sp = proc.Word(stk.field(p.f.Stktop.Gobuf).(remoteStruct).field(p.f.Gobuf.Sp).(remoteUint).aGet(a))
-                       // Get stk->stackbase
-                       stk = stk.field(p.f.Stktop.Stackbase).(remotePtr).aGet(a).(remoteStruct)
-                       continue
-               }
-
-               // Get the PC of the call instruction
-               callpc := pc
-               if !top && (p.sys.goexit == nil || pc != proc.Word(p.sys.goexit.Value)) {
-                       callpc--
-               }
-
-               // Look up function
-               path, line, fn = p.syms.PCToLine(uint64(callpc))
-               if fn != nil {
-                       break
-               }
-
-               // Closure?
-               var buf = make([]byte, p.ClosureSize())
-               if _, err := p.Peek(pc, buf); err != nil {
-                       break
-               }
-               spdelta, ok := p.ParseClosure(buf)
-               if ok {
-                       sp += proc.Word(spdelta)
-                       pc = p.peekUintptr(a, sp-proc.Word(p.PtrSize()))
-               }
-       }
-       if fn == nil {
-               return nil
-       }
-
-       // Compute frame pointer
-       var fp proc.Word
-       if fn.FrameSize < p.PtrSize() {
-               fp = sp + proc.Word(p.PtrSize())
-       } else {
-               fp = sp + proc.Word(fn.FrameSize)
-       }
-       // TODO(austin) To really figure out if we're in the prologue,
-       // we need to disassemble the function and look for the call
-       // to morestack.  For now, just special case the entry point.
-       //
-       // TODO(austin) What if we're in the call to morestack in the
-       // prologue?  Then top == false.
-       if top && pc == proc.Word(fn.Entry) {
-               // We're in the function prologue, before SP
-               // has been adjusted for the frame.
-               fp -= proc.Word(fn.FrameSize - p.PtrSize())
-       }
-
-       return &Frame{pc, sp, fp, stk, fn, path, line, inner, nil}
-}
-
-// Outer returns the Frame that called this Frame, or nil if this is
-// the outermost frame.
-func (f *Frame) Outer() (*Frame, os.Error) {
-       var fr *Frame
-       err := try(func(a aborter) { fr = f.aOuter(a) })
-       return fr, err
-}
-
-func (f *Frame) aOuter(a aborter) *Frame {
-       // Is there a cached outer frame
-       if f.outer != nil {
-               return f.outer
-       }
-
-       p := f.stk.r.p
-
-       sp := f.fp
-       if f.fn == p.sys.newproc && f.fn == p.sys.deferproc {
-               // TODO(rsc) The compiler inserts two push/pop's
-               // around calls to go and defer.  Russ says this
-               // should get fixed in the compiler, but we account
-               // for it for now.
-               sp += proc.Word(2 * p.PtrSize())
-       }
-
-       pc := p.peekUintptr(a, f.fp-proc.Word(p.PtrSize()))
-       if pc < 0x1000 {
-               return nil
-       }
-
-       // TODO(austin) Register this frame for shoot-down.
-
-       f.outer = prepareFrame(a, pc, sp, f.stk, f)
-       return f.outer
-}
-
-// Inner returns the Frame called by this Frame, or nil if this is the
-// innermost frame.
-func (f *Frame) Inner() *Frame { return f.inner }
-
-func (f *Frame) String() string {
-       res := f.fn.Name
-       if f.pc > proc.Word(f.fn.Value) {
-               res += fmt.Sprintf("+%#x", f.pc-proc.Word(f.fn.Entry))
-       }
-       return res + fmt.Sprintf(" %s:%d", f.path, f.line)
-}
diff --git a/src/pkg/exp/ogle/goroutine.go b/src/pkg/exp/ogle/goroutine.go
deleted file mode 100644 (file)
index 5104ec6..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "exp/eval"
-       "fmt"
-       "os"
-)
-
-// A Goroutine represents a goroutine in a remote process.
-type Goroutine struct {
-       g     remoteStruct
-       frame *Frame
-       dead  bool
-}
-
-func (t *Goroutine) String() string {
-       if t.dead {
-               return "<dead thread>"
-       }
-       // TODO(austin) Give threads friendly ID's, possibly including
-       // the name of the entry function.
-       return fmt.Sprintf("thread %#x", t.g.addr().base)
-}
-
-// isG0 returns true if this thread if the internal idle thread
-func (t *Goroutine) isG0() bool { return t.g.addr().base == t.g.r.p.sys.g0.addr().base }
-
-func (t *Goroutine) resetFrame() (err os.Error) {
-       // TODO(austin) Reuse any live part of the current frame stack
-       // so existing references to Frame's keep working.
-       t.frame, err = newFrame(t.g)
-       return
-}
-
-// Out selects the caller frame of the current frame.
-func (t *Goroutine) Out() os.Error {
-       f, err := t.frame.Outer()
-       if f != nil {
-               t.frame = f
-       }
-       return err
-}
-
-// In selects the frame called by the current frame.
-func (t *Goroutine) In() os.Error {
-       f := t.frame.Inner()
-       if f != nil {
-               t.frame = f
-       }
-       return nil
-}
-
-func readylockedBP(ev Event) (EventAction, os.Error) {
-       b := ev.(*Breakpoint)
-       p := b.Process()
-
-       // The new g is the only argument to this function, so the
-       // stack will have the return address, then the G*.
-       regs, err := b.osThread.Regs()
-       if err != nil {
-               return EAStop, err
-       }
-       sp := regs.SP()
-       addr := sp + proc.Word(p.PtrSize())
-       arg := remotePtr{remote{addr, p}, p.runtime.G}
-       var gp eval.Value
-       err = try(func(a aborter) { gp = arg.aGet(a) })
-       if err != nil {
-               return EAStop, err
-       }
-       if gp == nil {
-               return EAStop, UnknownGoroutine{b.osThread, 0}
-       }
-       gs := gp.(remoteStruct)
-       g := &Goroutine{gs, nil, false}
-       p.goroutines[gs.addr().base] = g
-
-       // Enqueue goroutine creation event
-       parent := b.Goroutine()
-       if parent.isG0() {
-               parent = nil
-       }
-       p.postEvent(&GoroutineCreate{commonEvent{p, g}, parent})
-
-       // If we don't have any thread selected, select this one
-       if p.curGoroutine == nil {
-               p.curGoroutine = g
-       }
-
-       return EADefault, nil
-}
-
-func goexitBP(ev Event) (EventAction, os.Error) {
-       b := ev.(*Breakpoint)
-       p := b.Process()
-
-       g := b.Goroutine()
-       g.dead = true
-
-       addr := g.g.addr().base
-       p.goroutines[addr] = nil, false
-
-       // Enqueue thread exit event
-       p.postEvent(&GoroutineExit{commonEvent{p, g}})
-
-       // If we just exited our selected goroutine, selected another
-       if p.curGoroutine == g {
-               p.selectSomeGoroutine()
-       }
-
-       return EADefault, nil
-}
diff --git a/src/pkg/exp/ogle/main.go b/src/pkg/exp/ogle/main.go
deleted file mode 100644 (file)
index 1999ecc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "exp/ogle"
-
-func main() { ogle.Main() }
diff --git a/src/pkg/exp/ogle/process.go b/src/pkg/exp/ogle/process.go
deleted file mode 100644 (file)
index 7c803b3..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/elf"
-       "debug/gosym"
-       "debug/proc"
-       "exp/eval"
-       "fmt"
-       "log"
-       "os"
-       "reflect"
-)
-
-// A FormatError indicates a failure to process information in or
-// about a remote process, such as unexpected or missing information
-// in the object file or runtime structures.
-type FormatError string
-
-func (e FormatError) String() string { return string(e) }
-
-// An UnknownArchitecture occurs when trying to load an object file
-// that indicates an architecture not supported by the debugger.
-type UnknownArchitecture elf.Machine
-
-func (e UnknownArchitecture) String() string {
-       return "unknown architecture: " + elf.Machine(e).String()
-}
-
-// A ProcessNotStopped error occurs when attempting to read or write
-// memory or registers of a process that is not stopped.
-type ProcessNotStopped struct{}
-
-func (e ProcessNotStopped) String() string { return "process not stopped" }
-
-// An UnknownGoroutine error is an internal error representing an
-// unrecognized G structure pointer.
-type UnknownGoroutine struct {
-       OSThread  proc.Thread
-       Goroutine proc.Word
-}
-
-func (e UnknownGoroutine) String() string {
-       return fmt.Sprintf("internal error: unknown goroutine (G %#x)", e.Goroutine)
-}
-
-// A NoCurrentGoroutine error occurs when no goroutine is currently
-// selected in a process (or when there are no goroutines in a
-// process).
-type NoCurrentGoroutine struct{}
-
-func (e NoCurrentGoroutine) String() string { return "no current goroutine" }
-
-// A Process represents a remote attached process.
-type Process struct {
-       Arch
-       proc proc.Process
-
-       // The symbol table of this process
-       syms *gosym.Table
-
-       // A possibly-stopped OS thread, or nil
-       threadCache proc.Thread
-
-       // Types parsed from the remote process
-       types map[proc.Word]*remoteType
-
-       // Types and values from the remote runtime package
-       runtime runtimeValues
-
-       // Runtime field indexes
-       f runtimeIndexes
-
-       // Globals from the sys package (or from no package)
-       sys struct {
-               lessstack, goexit, newproc, deferproc, newprocreadylocked *gosym.Func
-               allg                                                      remotePtr
-               g0                                                        remoteStruct
-       }
-
-       // Event queue
-       posted  []Event
-       pending []Event
-       event   Event
-
-       // Event hooks
-       breakpointHooks     map[proc.Word]*breakpointHook
-       goroutineCreateHook *goroutineCreateHook
-       goroutineExitHook   *goroutineExitHook
-
-       // Current goroutine, or nil if there are no goroutines
-       curGoroutine *Goroutine
-
-       // Goroutines by the address of their G structure
-       goroutines map[proc.Word]*Goroutine
-}
-
-/*
- * Process creation
- */
-
-// NewProcess constructs a new remote process around a traced
-// process, an architecture, and a symbol table.
-func NewProcess(tproc proc.Process, arch Arch, syms *gosym.Table) (*Process, os.Error) {
-       p := &Process{
-               Arch:                arch,
-               proc:                tproc,
-               syms:                syms,
-               types:               make(map[proc.Word]*remoteType),
-               breakpointHooks:     make(map[proc.Word]*breakpointHook),
-               goroutineCreateHook: new(goroutineCreateHook),
-               goroutineExitHook:   new(goroutineExitHook),
-               goroutines:          make(map[proc.Word]*Goroutine),
-       }
-
-       // Fill in remote runtime
-       p.bootstrap()
-
-       switch {
-       case p.sys.allg.addr().base == 0:
-               return nil, FormatError("failed to find runtime symbol 'allg'")
-       case p.sys.g0.addr().base == 0:
-               return nil, FormatError("failed to find runtime symbol 'g0'")
-       case p.sys.newprocreadylocked == nil:
-               return nil, FormatError("failed to find runtime symbol 'newprocreadylocked'")
-       case p.sys.goexit == nil:
-               return nil, FormatError("failed to find runtime symbol 'sys.goexit'")
-       }
-
-       // Get current goroutines
-       p.goroutines[p.sys.g0.addr().base] = &Goroutine{p.sys.g0, nil, false}
-       err := try(func(a aborter) {
-               g := p.sys.allg.aGet(a)
-               for g != nil {
-                       gs := g.(remoteStruct)
-                       fmt.Printf("*** Found goroutine at %#x\n", gs.addr().base)
-                       p.goroutines[gs.addr().base] = &Goroutine{gs, nil, false}
-                       g = gs.field(p.f.G.Alllink).(remotePtr).aGet(a)
-               }
-       })
-       if err != nil {
-               return nil, err
-       }
-
-       // Create internal breakpoints to catch new and exited goroutines
-       p.OnBreakpoint(proc.Word(p.sys.newprocreadylocked.Entry)).(*breakpointHook).addHandler(readylockedBP, true)
-       p.OnBreakpoint(proc.Word(p.sys.goexit.Entry)).(*breakpointHook).addHandler(goexitBP, true)
-
-       // Select current frames
-       for _, g := range p.goroutines {
-               g.resetFrame()
-       }
-
-       p.selectSomeGoroutine()
-
-       return p, nil
-}
-
-func elfGoSyms(f *elf.File) (*gosym.Table, os.Error) {
-       text := f.Section(".text")
-       symtab := f.Section(".gosymtab")
-       pclntab := f.Section(".gopclntab")
-       if text == nil || symtab == nil || pclntab == nil {
-               return nil, nil
-       }
-
-       symdat, err := symtab.Data()
-       if err != nil {
-               return nil, err
-       }
-       pclndat, err := pclntab.Data()
-       if err != nil {
-               return nil, err
-       }
-
-       pcln := gosym.NewLineTable(pclndat, text.Addr)
-       tab, err := gosym.NewTable(symdat, pcln)
-       if err != nil {
-               return nil, err
-       }
-
-       return tab, nil
-}
-
-// NewProcessElf constructs a new remote process around a traced
-// process and the process' ELF object.
-func NewProcessElf(tproc proc.Process, f *elf.File) (*Process, os.Error) {
-       syms, err := elfGoSyms(f)
-       if err != nil {
-               return nil, err
-       }
-       if syms == nil {
-               return nil, FormatError("Failed to find symbol table")
-       }
-       var arch Arch
-       switch f.Machine {
-       case elf.EM_X86_64:
-               arch = Amd64
-       default:
-               return nil, UnknownArchitecture(f.Machine)
-       }
-       return NewProcess(tproc, arch, syms)
-}
-
-// bootstrap constructs the runtime structure of a remote process.
-func (p *Process) bootstrap() {
-       // Manually construct runtime types
-       p.runtime.String = newManualType(eval.TypeOfNative(rt1String{}), p.Arch)
-       p.runtime.Slice = newManualType(eval.TypeOfNative(rt1Slice{}), p.Arch)
-       p.runtime.Eface = newManualType(eval.TypeOfNative(rt1Eface{}), p.Arch)
-
-       p.runtime.Type = newManualType(eval.TypeOfNative(rt1Type{}), p.Arch)
-       p.runtime.CommonType = newManualType(eval.TypeOfNative(rt1CommonType{}), p.Arch)
-       p.runtime.UncommonType = newManualType(eval.TypeOfNative(rt1UncommonType{}), p.Arch)
-       p.runtime.StructField = newManualType(eval.TypeOfNative(rt1StructField{}), p.Arch)
-       p.runtime.StructType = newManualType(eval.TypeOfNative(rt1StructType{}), p.Arch)
-       p.runtime.PtrType = newManualType(eval.TypeOfNative(rt1PtrType{}), p.Arch)
-       p.runtime.ArrayType = newManualType(eval.TypeOfNative(rt1ArrayType{}), p.Arch)
-       p.runtime.SliceType = newManualType(eval.TypeOfNative(rt1SliceType{}), p.Arch)
-
-       p.runtime.Stktop = newManualType(eval.TypeOfNative(rt1Stktop{}), p.Arch)
-       p.runtime.Gobuf = newManualType(eval.TypeOfNative(rt1Gobuf{}), p.Arch)
-       p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch)
-
-       // Get addresses of type.*runtime.XType for discrimination.
-       rtv := reflect.Indirect(reflect.ValueOf(&p.runtime))
-       rtvt := rtv.Type()
-       for i := 0; i < rtv.NumField(); i++ {
-               n := rtvt.Field(i).Name
-               if n[0] != 'P' || n[1] < 'A' || n[1] > 'Z' {
-                       continue
-               }
-               sym := p.syms.LookupSym("type.*runtime." + n[1:])
-               if sym == nil {
-                       continue
-               }
-               rtv.Field(i).SetUint(sym.Value)
-       }
-
-       // Get runtime field indexes
-       fillRuntimeIndexes(&p.runtime, &p.f)
-
-       // Fill G status
-       p.runtime.runtimeGStatus = rt1GStatus
-
-       // Get globals
-       p.sys.lessstack = p.syms.LookupFunc("sys.lessstack")
-       p.sys.goexit = p.syms.LookupFunc("goexit")
-       p.sys.newproc = p.syms.LookupFunc("sys.newproc")
-       p.sys.deferproc = p.syms.LookupFunc("sys.deferproc")
-       p.sys.newprocreadylocked = p.syms.LookupFunc("newprocreadylocked")
-       if allg := p.syms.LookupSym("allg"); allg != nil {
-               p.sys.allg = remotePtr{remote{proc.Word(allg.Value), p}, p.runtime.G}
-       }
-       if g0 := p.syms.LookupSym("g0"); g0 != nil {
-               p.sys.g0 = p.runtime.G.mk(remote{proc.Word(g0.Value), p}).(remoteStruct)
-       }
-}
-
-func (p *Process) selectSomeGoroutine() {
-       // Once we have friendly goroutine ID's, there might be a more
-       // reasonable behavior for this.
-       p.curGoroutine = nil
-       for _, g := range p.goroutines {
-               if !g.isG0() && g.frame != nil {
-                       p.curGoroutine = g
-                       return
-               }
-       }
-}
-
-/*
- * Process memory
- */
-
-func (p *Process) someStoppedOSThread() proc.Thread {
-       if p.threadCache != nil {
-               if _, err := p.threadCache.Stopped(); err == nil {
-                       return p.threadCache
-               }
-       }
-
-       for _, t := range p.proc.Threads() {
-               if _, err := t.Stopped(); err == nil {
-                       p.threadCache = t
-                       return t
-               }
-       }
-       return nil
-}
-
-func (p *Process) Peek(addr proc.Word, out []byte) (int, os.Error) {
-       thr := p.someStoppedOSThread()
-       if thr == nil {
-               return 0, ProcessNotStopped{}
-       }
-       return thr.Peek(addr, out)
-}
-
-func (p *Process) Poke(addr proc.Word, b []byte) (int, os.Error) {
-       thr := p.someStoppedOSThread()
-       if thr == nil {
-               return 0, ProcessNotStopped{}
-       }
-       return thr.Poke(addr, b)
-}
-
-func (p *Process) peekUintptr(a aborter, addr proc.Word) proc.Word {
-       return proc.Word(mkUintptr(remote{addr, p}).(remoteUint).aGet(a))
-}
-
-/*
- * Events
- */
-
-// OnBreakpoint returns the hook that is run when the program reaches
-// the given program counter.
-func (p *Process) OnBreakpoint(pc proc.Word) EventHook {
-       if bp, ok := p.breakpointHooks[pc]; ok {
-               return bp
-       }
-       // The breakpoint will register itself when a handler is added
-       return &breakpointHook{commonHook{nil, 0}, p, pc}
-}
-
-// OnGoroutineCreate returns the hook that is run when a goroutine is created.
-func (p *Process) OnGoroutineCreate() EventHook {
-       return p.goroutineCreateHook
-}
-
-// OnGoroutineExit returns the hook that is run when a goroutine exits.
-func (p *Process) OnGoroutineExit() EventHook { return p.goroutineExitHook }
-
-// osThreadToGoroutine looks up the goroutine running on an OS thread.
-func (p *Process) osThreadToGoroutine(t proc.Thread) (*Goroutine, os.Error) {
-       regs, err := t.Regs()
-       if err != nil {
-               return nil, err
-       }
-       g := p.G(regs)
-       gt, ok := p.goroutines[g]
-       if !ok {
-               return nil, UnknownGoroutine{t, g}
-       }
-       return gt, nil
-}
-
-// causesToEvents translates the stop causes of the underlying process
-// into an event queue.
-func (p *Process) causesToEvents() ([]Event, os.Error) {
-       // Count causes we're interested in
-       nev := 0
-       for _, t := range p.proc.Threads() {
-               if c, err := t.Stopped(); err == nil {
-                       switch c := c.(type) {
-                       case proc.Breakpoint:
-                               nev++
-                       case proc.Signal:
-                               // TODO(austin)
-                               //nev++;
-                       }
-               }
-       }
-
-       // Translate causes to events
-       events := make([]Event, nev)
-       i := 0
-       for _, t := range p.proc.Threads() {
-               if c, err := t.Stopped(); err == nil {
-                       switch c := c.(type) {
-                       case proc.Breakpoint:
-                               gt, err := p.osThreadToGoroutine(t)
-                               if err != nil {
-                                       return nil, err
-                               }
-                               events[i] = &Breakpoint{commonEvent{p, gt}, t, proc.Word(c)}
-                               i++
-                       case proc.Signal:
-                               // TODO(austin)
-                       }
-               }
-       }
-
-       return events, nil
-}
-
-// postEvent appends an event to the posted queue.  These events will
-// be processed before any currently pending events.
-func (p *Process) postEvent(ev Event) {
-       p.posted = append(p.posted, ev)
-}
-
-// processEvents processes events in the event queue until no events
-// remain, a handler returns EAStop, or a handler returns an error.
-// It returns either EAStop or EAContinue and possibly an error.
-func (p *Process) processEvents() (EventAction, os.Error) {
-       var ev Event
-       for len(p.posted) > 0 {
-               ev, p.posted = p.posted[0], p.posted[1:]
-               action, err := p.processEvent(ev)
-               if action == EAStop {
-                       return action, err
-               }
-       }
-
-       for len(p.pending) > 0 {
-               ev, p.pending = p.pending[0], p.pending[1:]
-               action, err := p.processEvent(ev)
-               if action == EAStop {
-                       return action, err
-               }
-       }
-
-       return EAContinue, nil
-}
-
-// processEvent processes a single event, without manipulating the
-// event queues.  It returns either EAStop or EAContinue and possibly
-// an error.
-func (p *Process) processEvent(ev Event) (EventAction, os.Error) {
-       p.event = ev
-
-       var action EventAction
-       var err os.Error
-       switch ev := p.event.(type) {
-       case *Breakpoint:
-               hook, ok := p.breakpointHooks[ev.pc]
-               if !ok {
-                       break
-               }
-               p.curGoroutine = ev.Goroutine()
-               action, err = hook.handle(ev)
-
-       case *GoroutineCreate:
-               p.curGoroutine = ev.Goroutine()
-               action, err = p.goroutineCreateHook.handle(ev)
-
-       case *GoroutineExit:
-               action, err = p.goroutineExitHook.handle(ev)
-
-       default:
-               log.Panicf("Unknown event type %T in queue", p.event)
-       }
-
-       if err != nil {
-               return EAStop, err
-       } else if action == EAStop {
-               return EAStop, nil
-       }
-       return EAContinue, nil
-}
-
-// Event returns the last event that caused the process to stop.  This
-// may return nil if the process has never been stopped by an event.
-//
-// TODO(austin) Return nil if the user calls p.Stop()?
-func (p *Process) Event() Event { return p.event }
-
-/*
- * Process control
- */
-
-// TODO(austin) Cont, WaitStop, and Stop.  Need to figure out how
-// event handling works with these.  Originally I did it only in
-// WaitStop, but if you Cont and there are pending events, then you
-// have to not actually continue and wait until a WaitStop to process
-// them, even if the event handlers will tell you to continue.  We
-// could handle them in both Cont and WaitStop to avoid this problem,
-// but it's still weird if an event happens after the Cont and before
-// the WaitStop that the handlers say to continue from.  Or we could
-// handle them on a separate thread.  Then obviously you get weird
-// asynchronous things, like prints while the user it typing a command,
-// but that's not necessarily a bad thing.
-
-// ContWait resumes process execution and waits for an event to occur
-// that stops the process.
-func (p *Process) ContWait() os.Error {
-       for {
-               a, err := p.processEvents()
-               if err != nil {
-                       return err
-               } else if a == EAStop {
-                       break
-               }
-               err = p.proc.Continue()
-               if err != nil {
-                       return err
-               }
-               err = p.proc.WaitStop()
-               if err != nil {
-                       return err
-               }
-               for _, g := range p.goroutines {
-                       g.resetFrame()
-               }
-               p.pending, err = p.causesToEvents()
-               if err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-// Out selects the caller frame of the current frame.
-func (p *Process) Out() os.Error {
-       if p.curGoroutine == nil {
-               return NoCurrentGoroutine{}
-       }
-       return p.curGoroutine.Out()
-}
-
-// In selects the frame called by the current frame.
-func (p *Process) In() os.Error {
-       if p.curGoroutine == nil {
-               return NoCurrentGoroutine{}
-       }
-       return p.curGoroutine.In()
-}
diff --git a/src/pkg/exp/ogle/rruntime.go b/src/pkg/exp/ogle/rruntime.go
deleted file mode 100644 (file)
index 950418b..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "exp/eval"
-       "reflect"
-)
-
-// This file contains remote runtime definitions.  Using reflection,
-// we convert all of these to interpreter types and layout their
-// remote representations using the architecture rules.
-//
-// We could get most of these definitions from our own runtime
-// package; however, some of them differ in convenient ways, some of
-// them are not defined or exported by the runtime, and having our own
-// definitions makes it easy to support multiple remote runtime
-// versions.  This may turn out to be overkill.
-//
-// All of these structures are prefixed with rt1 to indicate the
-// runtime version and to mark them as types used only as templates
-// for remote types.
-
-/*
- * Runtime data headers
- *
- * See $GOROOT/src/pkg/runtime/runtime.h
- */
-
-type rt1String struct {
-       str uintptr
-       len int
-}
-
-type rt1Slice struct {
-       array uintptr
-       len   int
-       cap   int
-}
-
-type rt1Eface struct {
-       typ uintptr
-       ptr uintptr
-}
-
-/*
- * Runtime type structures
- *
- * See $GOROOT/src/pkg/runtime/type.h and $GOROOT/src/pkg/runtime/type.go
- */
-
-type rt1UncommonType struct {
-       name    *string
-       pkgPath *string
-       //methods []method;
-}
-
-type rt1CommonType struct {
-       size                   uintptr
-       hash                   uint32
-       alg, align, fieldAlign uint8
-       string                 *string
-       uncommonType           *rt1UncommonType
-}
-
-type rt1Type struct {
-       // While Type is technically an Eface, treating the
-       // discriminator as an opaque pointer and taking advantage of
-       // the commonType prologue on all Type's makes type parsing
-       // much simpler.
-       typ uintptr
-       ptr *rt1CommonType
-}
-
-type rt1StructField struct {
-       name    *string
-       pkgPath *string
-       typ     *rt1Type
-       tag     *string
-       offset  uintptr
-}
-
-type rt1StructType struct {
-       rt1CommonType
-       fields []rt1StructField
-}
-
-type rt1PtrType struct {
-       rt1CommonType
-       elem *rt1Type
-}
-
-type rt1SliceType struct {
-       rt1CommonType
-       elem *rt1Type
-}
-
-type rt1ArrayType struct {
-       rt1CommonType
-       elem *rt1Type
-       len  uintptr
-}
-
-/*
- * Runtime scheduler structures
- *
- * See $GOROOT/src/pkg/runtime/runtime.h
- */
-
-// Fields beginning with _ are only for padding
-
-type rt1Stktop struct {
-       stackguard uintptr
-       stackbase  *rt1Stktop
-       gobuf      rt1Gobuf
-       _args      uint32
-       _fp        uintptr
-}
-
-type rt1Gobuf struct {
-       sp uintptr
-       pc uintptr
-       g  *rt1G
-       r0 uintptr
-}
-
-type rt1G struct {
-       _stackguard uintptr
-       stackbase   *rt1Stktop
-       _defer      uintptr
-       sched       rt1Gobuf
-       _stack0     uintptr
-       _entry      uintptr
-       alllink     *rt1G
-       _param      uintptr
-       status      int16
-       // Incomplete
-}
-
-var rt1GStatus = runtimeGStatus{
-       Gidle:     0,
-       Grunnable: 1,
-       Grunning:  2,
-       Gsyscall:  3,
-       Gwaiting:  4,
-       Gmoribund: 5,
-       Gdead:     6,
-}
-
-// runtimeIndexes stores the indexes of fields in the runtime
-// structures.  It is filled in using reflection, so the name of the
-// fields must match the names of the remoteType's in runtimeValues
-// exactly and the names of the index fields must be the capitalized
-// version of the names of the fields in the runtime structures above.
-type runtimeIndexes struct {
-       String struct {
-               Str, Len int
-       }
-       Slice struct {
-               Array, Len, Cap int
-       }
-       Eface struct {
-               Typ, Ptr int
-       }
-
-       UncommonType struct {
-               Name, PkgPath int
-       }
-       CommonType struct {
-               Size, Hash, Alg, Align, FieldAlign, String, UncommonType int
-       }
-       Type struct {
-               Typ, Ptr int
-       }
-       StructField struct {
-               Name, PkgPath, Typ, Tag, Offset int
-       }
-       StructType struct {
-               Fields int
-       }
-       PtrType struct {
-               Elem int
-       }
-       SliceType struct {
-               Elem int
-       }
-       ArrayType struct {
-               Elem, Len int
-       }
-
-       Stktop struct {
-               Stackguard, Stackbase, Gobuf int
-       }
-       Gobuf struct {
-               Sp, Pc, G int
-       }
-       G struct {
-               Stackbase, Sched, Status, Alllink int
-       }
-}
-
-// Values of G status codes
-type runtimeGStatus struct {
-       Gidle, Grunnable, Grunning, Gsyscall, Gwaiting, Gmoribund, Gdead int64
-}
-
-// runtimeValues stores the types and values that correspond to those
-// in the remote runtime package.
-type runtimeValues struct {
-       // Runtime data headers
-       String, Slice, Eface *remoteType
-       // Runtime type structures
-       Type, CommonType, UncommonType, StructField, StructType, PtrType,
-       ArrayType, SliceType *remoteType
-       // Runtime scheduler structures
-       Stktop, Gobuf, G *remoteType
-       // Addresses of *runtime.XType types.  These are the
-       // discriminators on the runtime.Type interface.  We use local
-       // reflection to fill these in from the remote symbol table,
-       // so the names must match the runtime names.
-       PBoolType,
-       PUint8Type, PUint16Type, PUint32Type, PUint64Type, PUintType, PUintptrType,
-       PInt8Type, PInt16Type, PInt32Type, PInt64Type, PIntType,
-       PFloat32Type, PFloat64Type, PFloatType,
-       PArrayType, PStringType, PStructType, PPtrType, PFuncType,
-       PInterfaceType, PSliceType, PMapType, PChanType,
-       PDotDotDotType, PUnsafePointerType proc.Word
-       // G status values
-       runtimeGStatus
-}
-
-// fillRuntimeIndexes fills a runtimeIndexes structure will the field
-// indexes gathered from the remoteTypes recorded in a runtimeValues
-// structure.
-func fillRuntimeIndexes(runtime *runtimeValues, out *runtimeIndexes) {
-       outv := reflect.Indirect(reflect.ValueOf(out))
-       outt := outv.Type()
-       runtimev := reflect.Indirect(reflect.ValueOf(runtime))
-
-       // out contains fields corresponding to each runtime type
-       for i := 0; i < outt.NumField(); i++ {
-               // Find the interpreter type for this runtime type
-               name := outt.Field(i).Name
-               et := runtimev.FieldByName(name).Interface().(*remoteType).Type.(*eval.StructType)
-
-               // Get the field indexes of the interpreter struct type
-               indexes := make(map[string]int, len(et.Elems))
-               for j, f := range et.Elems {
-                       if f.Anonymous {
-                               continue
-                       }
-                       name := f.Name
-                       if name[0] >= 'a' && name[0] <= 'z' {
-                               name = string(name[0]+'A'-'a') + name[1:]
-                       }
-                       indexes[name] = j
-               }
-
-               // Fill this field of out
-               outStructv := outv.Field(i)
-               outStructt := outStructv.Type()
-               for j := 0; j < outStructt.NumField(); j++ {
-                       f := outStructv.Field(j)
-                       name := outStructt.Field(j).Name
-                       f.SetInt(int64(indexes[name]))
-               }
-       }
-}
diff --git a/src/pkg/exp/ogle/rtype.go b/src/pkg/exp/ogle/rtype.go
deleted file mode 100644 (file)
index b3c3557..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "exp/eval"
-       "fmt"
-       "log"
-)
-
-const debugParseRemoteType = false
-
-// A remoteType is the local representation of a type in a remote process.
-type remoteType struct {
-       eval.Type
-       // The size of values of this type in bytes.
-       size int
-       // The field alignment of this type.  Only used for
-       // manually-constructed types.
-       fieldAlign int
-       // The maker function to turn a remote address of a value of
-       // this type into an interpreter Value.
-       mk maker
-}
-
-var manualTypes = make(map[Arch]map[eval.Type]*remoteType)
-
-// newManualType constructs a remote type from an interpreter Type
-// using the size and alignment properties of the given architecture.
-// Most types are parsed directly out of the remote process, but to do
-// so we need to layout the structures that describe those types ourselves.
-func newManualType(t eval.Type, arch Arch) *remoteType {
-       if nt, ok := t.(*eval.NamedType); ok {
-               t = nt.Def
-       }
-
-       // Get the type map for this architecture
-       typeMap := manualTypes[arch]
-       if typeMap == nil {
-               typeMap = make(map[eval.Type]*remoteType)
-               manualTypes[arch] = typeMap
-
-               // Construct basic types for this architecture
-               basicType := func(t eval.Type, mk maker, size int, fieldAlign int) {
-                       t = t.(*eval.NamedType).Def
-                       if fieldAlign == 0 {
-                               fieldAlign = size
-                       }
-                       typeMap[t] = &remoteType{t, size, fieldAlign, mk}
-               }
-               basicType(eval.Uint8Type, mkUint8, 1, 0)
-               basicType(eval.Uint32Type, mkUint32, 4, 0)
-               basicType(eval.UintptrType, mkUintptr, arch.PtrSize(), 0)
-               basicType(eval.Int16Type, mkInt16, 2, 0)
-               basicType(eval.Int32Type, mkInt32, 4, 0)
-               basicType(eval.IntType, mkInt, arch.IntSize(), 0)
-               basicType(eval.StringType, mkString, arch.PtrSize()+arch.IntSize(), arch.PtrSize())
-       }
-
-       if rt, ok := typeMap[t]; ok {
-               return rt
-       }
-
-       var rt *remoteType
-       switch t := t.(type) {
-       case *eval.PtrType:
-               var elem *remoteType
-               mk := func(r remote) eval.Value { return remotePtr{r, elem} }
-               rt = &remoteType{t, arch.PtrSize(), arch.PtrSize(), mk}
-               // Construct the element type after registering the
-               // type to break cycles.
-               typeMap[eval.Type(t)] = rt
-               elem = newManualType(t.Elem, arch)
-
-       case *eval.ArrayType:
-               elem := newManualType(t.Elem, arch)
-               mk := func(r remote) eval.Value { return remoteArray{r, t.Len, elem} }
-               rt = &remoteType{t, elem.size * int(t.Len), elem.fieldAlign, mk}
-
-       case *eval.SliceType:
-               elem := newManualType(t.Elem, arch)
-               mk := func(r remote) eval.Value { return remoteSlice{r, elem} }
-               rt = &remoteType{t, arch.PtrSize() + 2*arch.IntSize(), arch.PtrSize(), mk}
-
-       case *eval.StructType:
-               layout := make([]remoteStructField, len(t.Elems))
-               offset := 0
-               fieldAlign := 0
-               for i, f := range t.Elems {
-                       elem := newManualType(f.Type, arch)
-                       if fieldAlign == 0 {
-                               fieldAlign = elem.fieldAlign
-                       }
-                       offset = arch.Align(offset, elem.fieldAlign)
-                       layout[i].offset = offset
-                       layout[i].fieldType = elem
-                       offset += elem.size
-               }
-               mk := func(r remote) eval.Value { return remoteStruct{r, layout} }
-               rt = &remoteType{t, offset, fieldAlign, mk}
-
-       default:
-               log.Panicf("cannot manually construct type %T", t)
-       }
-
-       typeMap[t] = rt
-       return rt
-}
-
-var prtIndent = ""
-
-// parseRemoteType parses a Type structure in a remote process to
-// construct the corresponding interpreter type and remote type.
-func parseRemoteType(a aborter, rs remoteStruct) *remoteType {
-       addr := rs.addr().base
-       p := rs.addr().p
-
-       // We deal with circular types by discovering cycles at
-       // NamedTypes.  If a type cycles back to something other than
-       // a named type, we're guaranteed that there will be a named
-       // type somewhere in that cycle.  Thus, we continue down,
-       // re-parsing types until we reach the named type in the
-       // cycle.  In order to still create one remoteType per remote
-       // type, we insert an empty remoteType in the type map the
-       // first time we encounter the type and re-use that structure
-       // the second time we encounter it.
-
-       rt, ok := p.types[addr]
-       if ok && rt.Type != nil {
-               return rt
-       } else if !ok {
-               rt = &remoteType{}
-               p.types[addr] = rt
-       }
-
-       if debugParseRemoteType {
-               sym := p.syms.SymByAddr(uint64(addr))
-               name := "<unknown>"
-               if sym != nil {
-                       name = sym.Name
-               }
-               log.Printf("%sParsing type at %#x (%s)", prtIndent, addr, name)
-               prtIndent += " "
-               defer func() { prtIndent = prtIndent[0 : len(prtIndent)-1] }()
-       }
-
-       // Get Type header
-       itype := proc.Word(rs.field(p.f.Type.Typ).(remoteUint).aGet(a))
-       typ := rs.field(p.f.Type.Ptr).(remotePtr).aGet(a).(remoteStruct)
-
-       // Is this a named type?
-       var nt *eval.NamedType
-       uncommon := typ.field(p.f.CommonType.UncommonType).(remotePtr).aGet(a)
-       if uncommon != nil {
-               name := uncommon.(remoteStruct).field(p.f.UncommonType.Name).(remotePtr).aGet(a)
-               if name != nil {
-                       // TODO(austin) Declare type in appropriate remote package
-                       nt = eval.NewNamedType(name.(remoteString).aGet(a))
-                       rt.Type = nt
-               }
-       }
-
-       // Create type
-       var t eval.Type
-       var mk maker
-       switch itype {
-       case p.runtime.PBoolType:
-               t = eval.BoolType
-               mk = mkBool
-       case p.runtime.PUint8Type:
-               t = eval.Uint8Type
-               mk = mkUint8
-       case p.runtime.PUint16Type:
-               t = eval.Uint16Type
-               mk = mkUint16
-       case p.runtime.PUint32Type:
-               t = eval.Uint32Type
-               mk = mkUint32
-       case p.runtime.PUint64Type:
-               t = eval.Uint64Type
-               mk = mkUint64
-       case p.runtime.PUintType:
-               t = eval.UintType
-               mk = mkUint
-       case p.runtime.PUintptrType:
-               t = eval.UintptrType
-               mk = mkUintptr
-       case p.runtime.PInt8Type:
-               t = eval.Int8Type
-               mk = mkInt8
-       case p.runtime.PInt16Type:
-               t = eval.Int16Type
-               mk = mkInt16
-       case p.runtime.PInt32Type:
-               t = eval.Int32Type
-               mk = mkInt32
-       case p.runtime.PInt64Type:
-               t = eval.Int64Type
-               mk = mkInt64
-       case p.runtime.PIntType:
-               t = eval.IntType
-               mk = mkInt
-       case p.runtime.PFloat32Type:
-               t = eval.Float32Type
-               mk = mkFloat32
-       case p.runtime.PFloat64Type:
-               t = eval.Float64Type
-               mk = mkFloat64
-       case p.runtime.PStringType:
-               t = eval.StringType
-               mk = mkString
-
-       case p.runtime.PArrayType:
-               // Cast to an ArrayType
-               typ := p.runtime.ArrayType.mk(typ.addr()).(remoteStruct)
-               len := int64(typ.field(p.f.ArrayType.Len).(remoteUint).aGet(a))
-               elem := parseRemoteType(a, typ.field(p.f.ArrayType.Elem).(remotePtr).aGet(a).(remoteStruct))
-               t = eval.NewArrayType(len, elem.Type)
-               mk = func(r remote) eval.Value { return remoteArray{r, len, elem} }
-
-       case p.runtime.PStructType:
-               // Cast to a StructType
-               typ := p.runtime.StructType.mk(typ.addr()).(remoteStruct)
-               fs := typ.field(p.f.StructType.Fields).(remoteSlice).aGet(a)
-
-               fields := make([]eval.StructField, fs.Len)
-               layout := make([]remoteStructField, fs.Len)
-               for i := range fields {
-                       f := fs.Base.(remoteArray).elem(int64(i)).(remoteStruct)
-                       elemrs := f.field(p.f.StructField.Typ).(remotePtr).aGet(a).(remoteStruct)
-                       elem := parseRemoteType(a, elemrs)
-                       fields[i].Type = elem.Type
-                       name := f.field(p.f.StructField.Name).(remotePtr).aGet(a)
-                       if name == nil {
-                               fields[i].Anonymous = true
-                       } else {
-                               fields[i].Name = name.(remoteString).aGet(a)
-                       }
-                       layout[i].offset = int(f.field(p.f.StructField.Offset).(remoteUint).aGet(a))
-                       layout[i].fieldType = elem
-               }
-
-               t = eval.NewStructType(fields)
-               mk = func(r remote) eval.Value { return remoteStruct{r, layout} }
-
-       case p.runtime.PPtrType:
-               // Cast to a PtrType
-               typ := p.runtime.PtrType.mk(typ.addr()).(remoteStruct)
-               elem := parseRemoteType(a, typ.field(p.f.PtrType.Elem).(remotePtr).aGet(a).(remoteStruct))
-               t = eval.NewPtrType(elem.Type)
-               mk = func(r remote) eval.Value { return remotePtr{r, elem} }
-
-       case p.runtime.PSliceType:
-               // Cast to a SliceType
-               typ := p.runtime.SliceType.mk(typ.addr()).(remoteStruct)
-               elem := parseRemoteType(a, typ.field(p.f.SliceType.Elem).(remotePtr).aGet(a).(remoteStruct))
-               t = eval.NewSliceType(elem.Type)
-               mk = func(r remote) eval.Value { return remoteSlice{r, elem} }
-
-       case p.runtime.PMapType, p.runtime.PChanType, p.runtime.PFuncType, p.runtime.PInterfaceType, p.runtime.PUnsafePointerType, p.runtime.PDotDotDotType:
-               // TODO(austin)
-               t = eval.UintptrType
-               mk = mkUintptr
-
-       default:
-               sym := p.syms.SymByAddr(uint64(itype))
-               name := "<unknown symbol>"
-               if sym != nil {
-                       name = sym.Name
-               }
-               err := fmt.Sprintf("runtime type at %#x has unexpected type %#x (%s)", addr, itype, name)
-               a.Abort(FormatError(err))
-       }
-
-       // Fill in the remote type
-       if nt != nil {
-               nt.Complete(t)
-       } else {
-               rt.Type = t
-       }
-       rt.size = int(typ.field(p.f.CommonType.Size).(remoteUint).aGet(a))
-       rt.mk = mk
-
-       return rt
-}
diff --git a/src/pkg/exp/ogle/rvalue.go b/src/pkg/exp/ogle/rvalue.go
deleted file mode 100644 (file)
index 3d630f9..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/proc"
-       "exp/eval"
-       "fmt"
-)
-
-// A RemoteMismatchError occurs when an operation that requires two
-// identical remote processes is given different process.  For
-// example, this occurs when trying to set a pointer in one process to
-// point to something in another process.
-type RemoteMismatchError string
-
-func (e RemoteMismatchError) String() string { return string(e) }
-
-// A ReadOnlyError occurs when attempting to set or assign to a
-// read-only value.
-type ReadOnlyError string
-
-func (e ReadOnlyError) String() string { return string(e) }
-
-// A maker is a function that converts a remote address into an
-// interpreter Value.
-type maker func(remote) eval.Value
-
-type remoteValue interface {
-       addr() remote
-}
-
-// remote represents an address in a remote process.
-type remote struct {
-       base proc.Word
-       p    *Process
-}
-
-func (v remote) Get(a aborter, size int) uint64 {
-       // TODO(austin) This variable might temporarily be in a
-       // register.  We could trace the assembly back from the
-       // current PC, looking for the beginning of the function or a
-       // call (both of which guarantee that the variable is in
-       // memory), or an instruction that loads the variable into a
-       // register.
-       //
-       // TODO(austin) If this is a local variable, it might not be
-       // live at this PC.  In fact, because the compiler reuses
-       // slots, there might even be a different local variable at
-       // this location right now.  A simple solution to both
-       // problems is to include the range of PC's over which a local
-       // variable is live in the symbol table.
-       //
-       // TODO(austin) We need to prevent the remote garbage
-       // collector from collecting objects out from under us.
-       var arr [8]byte
-       buf := arr[0:size]
-       _, err := v.p.Peek(v.base, buf)
-       if err != nil {
-               a.Abort(err)
-       }
-       return uint64(v.p.ToWord(buf))
-}
-
-func (v remote) Set(a aborter, size int, x uint64) {
-       var arr [8]byte
-       buf := arr[0:size]
-       v.p.FromWord(proc.Word(x), buf)
-       _, err := v.p.Poke(v.base, buf)
-       if err != nil {
-               a.Abort(err)
-       }
-}
-
-func (v remote) plus(x proc.Word) remote { return remote{v.base + x, v.p} }
-
-func tryRVString(f func(a aborter) string) string {
-       var s string
-       err := try(func(a aborter) { s = f(a) })
-       if err != nil {
-               return fmt.Sprintf("<error: %v>", err)
-       }
-       return s
-}
-
-/*
- * Bool
- */
-
-type remoteBool struct {
-       r remote
-}
-
-func (v remoteBool) String() string {
-       return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
-}
-
-func (v remoteBool) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.BoolValue).Get(t))
-}
-
-func (v remoteBool) Get(t *eval.Thread) bool { return v.aGet(t) }
-
-func (v remoteBool) aGet(a aborter) bool { return v.r.Get(a, 1) != 0 }
-
-func (v remoteBool) Set(t *eval.Thread, x bool) {
-       v.aSet(t, x)
-}
-
-func (v remoteBool) aSet(a aborter, x bool) {
-       if x {
-               v.r.Set(a, 1, 1)
-       } else {
-               v.r.Set(a, 1, 0)
-       }
-}
-
-func (v remoteBool) addr() remote { return v.r }
-
-func mkBool(r remote) eval.Value { return remoteBool{r} }
-
-/*
- * Uint
- */
-
-type remoteUint struct {
-       r    remote
-       size int
-}
-
-func (v remoteUint) String() string {
-       return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
-}
-
-func (v remoteUint) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.UintValue).Get(t))
-}
-
-func (v remoteUint) Get(t *eval.Thread) uint64 {
-       return v.aGet(t)
-}
-
-func (v remoteUint) aGet(a aborter) uint64 { return v.r.Get(a, v.size) }
-
-func (v remoteUint) Set(t *eval.Thread, x uint64) {
-       v.aSet(t, x)
-}
-
-func (v remoteUint) aSet(a aborter, x uint64) { v.r.Set(a, v.size, x) }
-
-func (v remoteUint) addr() remote { return v.r }
-
-func mkUint8(r remote) eval.Value { return remoteUint{r, 1} }
-
-func mkUint16(r remote) eval.Value { return remoteUint{r, 2} }
-
-func mkUint32(r remote) eval.Value { return remoteUint{r, 4} }
-
-func mkUint64(r remote) eval.Value { return remoteUint{r, 8} }
-
-func mkUint(r remote) eval.Value { return remoteUint{r, r.p.IntSize()} }
-
-func mkUintptr(r remote) eval.Value { return remoteUint{r, r.p.PtrSize()} }
-
-/*
- * Int
- */
-
-type remoteInt struct {
-       r    remote
-       size int
-}
-
-func (v remoteInt) String() string {
-       return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
-}
-
-func (v remoteInt) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.IntValue).Get(t))
-}
-
-func (v remoteInt) Get(t *eval.Thread) int64 { return v.aGet(t) }
-
-func (v remoteInt) aGet(a aborter) int64 { return int64(v.r.Get(a, v.size)) }
-
-func (v remoteInt) Set(t *eval.Thread, x int64) {
-       v.aSet(t, x)
-}
-
-func (v remoteInt) aSet(a aborter, x int64) { v.r.Set(a, v.size, uint64(x)) }
-
-func (v remoteInt) addr() remote { return v.r }
-
-func mkInt8(r remote) eval.Value { return remoteInt{r, 1} }
-
-func mkInt16(r remote) eval.Value { return remoteInt{r, 2} }
-
-func mkInt32(r remote) eval.Value { return remoteInt{r, 4} }
-
-func mkInt64(r remote) eval.Value { return remoteInt{r, 8} }
-
-func mkInt(r remote) eval.Value { return remoteInt{r, r.p.IntSize()} }
-
-/*
- * Float
- */
-
-type remoteFloat struct {
-       r    remote
-       size int
-}
-
-func (v remoteFloat) String() string {
-       return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
-}
-
-func (v remoteFloat) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.FloatValue).Get(t))
-}
-
-func (v remoteFloat) Get(t *eval.Thread) float64 {
-       return v.aGet(t)
-}
-
-func (v remoteFloat) aGet(a aborter) float64 {
-       bits := v.r.Get(a, v.size)
-       switch v.size {
-       case 4:
-               return float64(v.r.p.ToFloat32(uint32(bits)))
-       case 8:
-               return v.r.p.ToFloat64(bits)
-       }
-       panic("Unexpected float size")
-}
-
-func (v remoteFloat) Set(t *eval.Thread, x float64) {
-       v.aSet(t, x)
-}
-
-func (v remoteFloat) aSet(a aborter, x float64) {
-       var bits uint64
-       switch v.size {
-       case 4:
-               bits = uint64(v.r.p.FromFloat32(float32(x)))
-       case 8:
-               bits = v.r.p.FromFloat64(x)
-       default:
-               panic("Unexpected float size")
-       }
-       v.r.Set(a, v.size, bits)
-}
-
-func (v remoteFloat) addr() remote { return v.r }
-
-func mkFloat32(r remote) eval.Value { return remoteFloat{r, 4} }
-
-func mkFloat64(r remote) eval.Value { return remoteFloat{r, 8} }
-
-func mkFloat(r remote) eval.Value { return remoteFloat{r, r.p.FloatSize()} }
-
-/*
- * String
- */
-
-type remoteString struct {
-       r remote
-}
-
-func (v remoteString) String() string {
-       return tryRVString(func(a aborter) string { return v.aGet(a) })
-}
-
-func (v remoteString) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.StringValue).Get(t))
-}
-
-func (v remoteString) Get(t *eval.Thread) string {
-       return v.aGet(t)
-}
-
-func (v remoteString) aGet(a aborter) string {
-       rs := v.r.p.runtime.String.mk(v.r).(remoteStruct)
-       str := proc.Word(rs.field(v.r.p.f.String.Str).(remoteUint).aGet(a))
-       len := rs.field(v.r.p.f.String.Len).(remoteInt).aGet(a)
-
-       bytes := make([]uint8, len)
-       _, err := v.r.p.Peek(str, bytes)
-       if err != nil {
-               a.Abort(err)
-       }
-       return string(bytes)
-}
-
-func (v remoteString) Set(t *eval.Thread, x string) {
-       v.aSet(t, x)
-}
-
-func (v remoteString) aSet(a aborter, x string) {
-       // TODO(austin) This isn't generally possible without the
-       // ability to allocate remote memory.
-       a.Abort(ReadOnlyError("remote strings cannot be assigned to"))
-}
-
-func mkString(r remote) eval.Value { return remoteString{r} }
-
-/*
- * Array
- */
-
-type remoteArray struct {
-       r        remote
-       len      int64
-       elemType *remoteType
-}
-
-func (v remoteArray) String() string {
-       res := "{"
-       for i := int64(0); i < v.len; i++ {
-               if i > 0 {
-                       res += ", "
-               }
-               res += v.elem(i).String()
-       }
-       return res + "}"
-}
-
-func (v remoteArray) Assign(t *eval.Thread, o eval.Value) {
-       // TODO(austin) Could do a bigger memcpy if o is a
-       // remoteArray in the same Process.
-       oa := o.(eval.ArrayValue)
-       for i := int64(0); i < v.len; i++ {
-               v.Elem(t, i).Assign(t, oa.Elem(t, i))
-       }
-}
-
-func (v remoteArray) Get(t *eval.Thread) eval.ArrayValue {
-       return v
-}
-
-func (v remoteArray) Elem(t *eval.Thread, i int64) eval.Value {
-       return v.elem(i)
-}
-
-func (v remoteArray) elem(i int64) eval.Value {
-       return v.elemType.mk(v.r.plus(proc.Word(int64(v.elemType.size) * i)))
-}
-
-func (v remoteArray) Sub(i int64, len int64) eval.ArrayValue {
-       return remoteArray{v.r.plus(proc.Word(int64(v.elemType.size) * i)), len, v.elemType}
-}
-
-/*
- * Struct
- */
-
-type remoteStruct struct {
-       r      remote
-       layout []remoteStructField
-}
-
-type remoteStructField struct {
-       offset    int
-       fieldType *remoteType
-}
-
-func (v remoteStruct) String() string {
-       res := "{"
-       for i := range v.layout {
-               if i > 0 {
-                       res += ", "
-               }
-               res += v.field(i).String()
-       }
-       return res + "}"
-}
-
-func (v remoteStruct) Assign(t *eval.Thread, o eval.Value) {
-       // TODO(austin) Could do a bigger memcpy.
-       oa := o.(eval.StructValue)
-       l := len(v.layout)
-       for i := 0; i < l; i++ {
-               v.Field(t, i).Assign(t, oa.Field(t, i))
-       }
-}
-
-func (v remoteStruct) Get(t *eval.Thread) eval.StructValue {
-       return v
-}
-
-func (v remoteStruct) Field(t *eval.Thread, i int) eval.Value {
-       return v.field(i)
-}
-
-func (v remoteStruct) field(i int) eval.Value {
-       f := &v.layout[i]
-       return f.fieldType.mk(v.r.plus(proc.Word(f.offset)))
-}
-
-func (v remoteStruct) addr() remote { return v.r }
-
-/*
- * Pointer
- */
-
-// TODO(austin) Comparing two remote pointers for equality in the
-// interpreter will crash it because the Value's returned from
-// remotePtr.Get() will be structs.
-
-type remotePtr struct {
-       r        remote
-       elemType *remoteType
-}
-
-func (v remotePtr) String() string {
-       return tryRVString(func(a aborter) string {
-               e := v.aGet(a)
-               if e == nil {
-                       return "<nil>"
-               }
-               return "&" + e.String()
-       })
-}
-
-func (v remotePtr) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.PtrValue).Get(t))
-}
-
-func (v remotePtr) Get(t *eval.Thread) eval.Value {
-       return v.aGet(t)
-}
-
-func (v remotePtr) aGet(a aborter) eval.Value {
-       addr := proc.Word(v.r.Get(a, v.r.p.PtrSize()))
-       if addr == 0 {
-               return nil
-       }
-       return v.elemType.mk(remote{addr, v.r.p})
-}
-
-func (v remotePtr) Set(t *eval.Thread, x eval.Value) {
-       v.aSet(t, x)
-}
-
-func (v remotePtr) aSet(a aborter, x eval.Value) {
-       if x == nil {
-               v.r.Set(a, v.r.p.PtrSize(), 0)
-               return
-       }
-       xr, ok := x.(remoteValue)
-       if !ok || v.r.p != xr.addr().p {
-               a.Abort(RemoteMismatchError("remote pointer must point within the same process"))
-       }
-       v.r.Set(a, v.r.p.PtrSize(), uint64(xr.addr().base))
-}
-
-func (v remotePtr) addr() remote { return v.r }
-
-/*
- * Slice
- */
-
-type remoteSlice struct {
-       r        remote
-       elemType *remoteType
-}
-
-func (v remoteSlice) String() string {
-       return tryRVString(func(a aborter) string {
-               b := v.aGet(a).Base
-               if b == nil {
-                       return "<nil>"
-               }
-               return b.String()
-       })
-}
-
-func (v remoteSlice) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.SliceValue).Get(t))
-}
-
-func (v remoteSlice) Get(t *eval.Thread) eval.Slice {
-       return v.aGet(t)
-}
-
-func (v remoteSlice) aGet(a aborter) eval.Slice {
-       rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct)
-       base := proc.Word(rs.field(v.r.p.f.Slice.Array).(remoteUint).aGet(a))
-       nel := rs.field(v.r.p.f.Slice.Len).(remoteInt).aGet(a)
-       cap := rs.field(v.r.p.f.Slice.Cap).(remoteInt).aGet(a)
-       if base == 0 {
-               return eval.Slice{nil, nel, cap}
-       }
-       return eval.Slice{remoteArray{remote{base, v.r.p}, nel, v.elemType}, nel, cap}
-}
-
-func (v remoteSlice) Set(t *eval.Thread, x eval.Slice) {
-       v.aSet(t, x)
-}
-
-func (v remoteSlice) aSet(a aborter, x eval.Slice) {
-       rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct)
-       if x.Base == nil {
-               rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, 0)
-       } else {
-               ar, ok := x.Base.(remoteArray)
-               if !ok || v.r.p != ar.r.p {
-                       a.Abort(RemoteMismatchError("remote slice must point within the same process"))
-               }
-               rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, uint64(ar.r.base))
-       }
-       rs.field(v.r.p.f.Slice.Len).(remoteInt).aSet(a, x.Len)
-       rs.field(v.r.p.f.Slice.Cap).(remoteInt).aSet(a, x.Cap)
-}
diff --git a/src/pkg/exp/ogle/vars.go b/src/pkg/exp/ogle/vars.go
deleted file mode 100644 (file)
index 8a3a147..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
-       "debug/gosym"
-       "debug/proc"
-       "exp/eval"
-       "log"
-       "os"
-)
-
-/*
- * Remote frame pointers
- */
-
-// A NotOnStack error occurs when attempting to access a variable in a
-// remote frame where that remote frame is not on the current stack.
-type NotOnStack struct {
-       Fn        *gosym.Func
-       Goroutine *Goroutine
-}
-
-func (e NotOnStack) String() string {
-       return "function " + e.Fn.Name + " not on " + e.Goroutine.String() + "'s stack"
-}
-
-// A remoteFramePtr is an implementation of eval.PtrValue that
-// represents a pointer to a function frame in a remote process.  When
-// accessed, this locates the function on the current goroutine's
-// stack and returns a structure containing the local variables of
-// that function.
-type remoteFramePtr struct {
-       p  *Process
-       fn *gosym.Func
-       rt *remoteType
-}
-
-func (v remoteFramePtr) String() string {
-       // TODO(austin): This could be a really awesome string method
-       return "<remote frame>"
-}
-
-func (v remoteFramePtr) Assign(t *eval.Thread, o eval.Value) {
-       v.Set(t, o.(eval.PtrValue).Get(t))
-}
-
-func (v remoteFramePtr) Get(t *eval.Thread) eval.Value {
-       g := v.p.curGoroutine
-       if g == nil || g.frame == nil {
-               t.Abort(NoCurrentGoroutine{})
-       }
-
-       for f := g.frame; f != nil; f = f.aOuter(t) {
-               if f.fn != v.fn {
-                       continue
-               }
-
-               // TODO(austin): Register for shootdown with f
-               return v.rt.mk(remote{f.fp, v.p})
-       }
-
-       t.Abort(NotOnStack{v.fn, g})
-       panic("fail")
-}
-
-func (v remoteFramePtr) Set(t *eval.Thread, x eval.Value) {
-       // Theoretically this could be a static error.  If remote
-       // packages were packages, remote frames could just be defined
-       // as constants.
-       t.Abort(ReadOnlyError("remote frames cannot be assigned to"))
-}
-
-/*
- * Remote packages
- */
-
-// TODO(austin): Remote packages are implemented as structs right now,
-// which has some weird consequences.  You can attempt to assign to a
-// remote package.  It also produces terrible error messages.
-// Ideally, these would actually be packages, but somehow first-class
-// so they could be assigned to other names.
-
-// A remotePackage is an implementation of eval.StructValue that
-// represents a package in a remote process.  It's essentially a
-// regular struct, except it cannot be assigned to.
-type remotePackage struct {
-       defs []eval.Value
-}
-
-func (v remotePackage) String() string { return "<remote package>" }
-
-func (v remotePackage) Assign(t *eval.Thread, o eval.Value) {
-       t.Abort(ReadOnlyError("remote packages cannot be assigned to"))
-}
-
-func (v remotePackage) Get(t *eval.Thread) eval.StructValue {
-       return v
-}
-
-func (v remotePackage) Field(t *eval.Thread, i int) eval.Value {
-       return v.defs[i]
-}
-
-/*
- * Remote variables
- */
-
-// populateWorld defines constants in the given world for each package
-// in this process.  These packages are structs that, in turn, contain
-// fields for each global and function in that package.
-func (p *Process) populateWorld(w *eval.World) os.Error {
-       type def struct {
-               t eval.Type
-               v eval.Value
-       }
-       packages := make(map[string]map[string]def)
-
-       for _, s := range p.syms.Syms {
-               if s.ReceiverName() != "" {
-                       // TODO(austin)
-                       continue
-               }
-
-               // Package
-               pkgName := s.PackageName()
-               switch pkgName {
-               case "", "type", "extratype", "string", "go":
-                       // "go" is really "go.string"
-                       continue
-               }
-               pkg, ok := packages[pkgName]
-               if !ok {
-                       pkg = make(map[string]def)
-                       packages[pkgName] = pkg
-               }
-
-               // Symbol name
-               name := s.BaseName()
-               if _, ok := pkg[name]; ok {
-                       log.Printf("Multiple definitions of symbol %s", s.Name)
-                       continue
-               }
-
-               // Symbol type
-               rt, err := p.typeOfSym(&s)
-               if err != nil {
-                       return err
-               }
-
-               // Definition
-               switch s.Type {
-               case 'D', 'd', 'B', 'b':
-                       // Global variable
-                       if rt == nil {
-                               continue
-                       }
-                       pkg[name] = def{rt.Type, rt.mk(remote{proc.Word(s.Value), p})}
-
-               case 'T', 't', 'L', 'l':
-                       // Function
-                       s := s.Func
-                       // TODO(austin): Ideally, this would *also* be
-                       // callable.  How does that interact with type
-                       // conversion syntax?
-                       rt, err := p.makeFrameType(s)
-                       if err != nil {
-                               return err
-                       }
-                       pkg[name] = def{eval.NewPtrType(rt.Type), remoteFramePtr{p, s, rt}}
-               }
-       }
-
-       // TODO(austin): Define remote types
-
-       // Define packages
-       for pkgName, defs := range packages {
-               fields := make([]eval.StructField, len(defs))
-               vals := make([]eval.Value, len(defs))
-               i := 0
-               for name, def := range defs {
-                       fields[i].Name = name
-                       fields[i].Type = def.t
-                       vals[i] = def.v
-                       i++
-               }
-               pkgType := eval.NewStructType(fields)
-               pkgVal := remotePackage{vals}
-
-               err := w.DefineConst(pkgName, pkgType, pkgVal)
-               if err != nil {
-                       log.Printf("while defining package %s: %v", pkgName, err)
-               }
-       }
-
-       return nil
-}
-
-// typeOfSym returns the type associated with a symbol.  If the symbol
-// has no type, returns nil.
-func (p *Process) typeOfSym(s *gosym.Sym) (*remoteType, os.Error) {
-       if s.GoType == 0 {
-               return nil, nil
-       }
-       addr := proc.Word(s.GoType)
-       var rt *remoteType
-       err := try(func(a aborter) { rt = parseRemoteType(a, p.runtime.Type.mk(remote{addr, p}).(remoteStruct)) })
-       if err != nil {
-               return nil, err
-       }
-       return rt, nil
-}
-
-// makeFrameType constructs a struct type for the frame of a function.
-// The offsets in this struct type are such that the struct can be
-// instantiated at this function's frame pointer.
-func (p *Process) makeFrameType(s *gosym.Func) (*remoteType, os.Error) {
-       n := len(s.Params) + len(s.Locals)
-       fields := make([]eval.StructField, n)
-       layout := make([]remoteStructField, n)
-       i := 0
-
-       // TODO(austin): There can be multiple locals/parameters with
-       // the same name.  We probably need liveness information to do
-       // anything about this.  Once we have that, perhaps we give
-       // such fields interface{} type?  Or perhaps we disambiguate
-       // the names with numbers.  Disambiguation is annoying for
-       // things like "i", where there's an obvious right answer.
-
-       for _, param := range s.Params {
-               rt, err := p.typeOfSym(param)
-               if err != nil {
-                       return nil, err
-               }
-               if rt == nil {
-                       //fmt.Printf(" (no type)\n");
-                       continue
-               }
-               // TODO(austin): Why do local variables carry their
-               // package name?
-               fields[i].Name = param.BaseName()
-               fields[i].Type = rt.Type
-               // Parameters have positive offsets from FP
-               layout[i].offset = int(param.Value)
-               layout[i].fieldType = rt
-               i++
-       }
-
-       for _, local := range s.Locals {
-               rt, err := p.typeOfSym(local)
-               if err != nil {
-                       return nil, err
-               }
-               if rt == nil {
-                       continue
-               }
-               fields[i].Name = local.BaseName()
-               fields[i].Type = rt.Type
-               // Locals have negative offsets from FP - PtrSize
-               layout[i].offset = -int(local.Value) - p.PtrSize()
-               layout[i].fieldType = rt
-               i++
-       }
-
-       fields = fields[0:i]
-       layout = layout[0:i]
-       t := eval.NewStructType(fields)
-       mk := func(r remote) eval.Value { return remoteStruct{r, layout} }
-       return &remoteType{t, 0, 0, mk}, nil
-}
index d125fd4540ce987f14efe8b2fc9d5d7e4fbcc863..ae79a0cec3fbb398eb84068046b3953970d4505e 100755 (executable)
@@ -69,11 +69,6 @@ gomake clean
 gotest
 ) || exit $?
 
-(xcd pkg/exp/ogle
-gomake clean
-time gomake ogle
-) || exit $?
-
 (xcd ../doc/progs
 time ./run
 ) || exit $?