summaryrefslogtreecommitdiff
path: root/src/pkg/exp/eval/bridge.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-10-14 18:10:43 -0700
committerRuss Cox <rsc@golang.org>2009-10-14 18:10:43 -0700
commit8f49b30671161bc5425c4f2f56cee96ad11befeb (patch)
treea545d9b275fbbc2346c40d8ea51b2c741ba9faa2 /src/pkg/exp/eval/bridge.go
parent9615b0b1cfb8bbfc2b963b471bf9ac2afb7c8662 (diff)
downloadgolang-8f49b30671161bc5425c4f2f56cee96ad11befeb.tar.gz
move austin/eval and austin/ogle to exp/eval and exp/ogle
R=r OCL=35736 CL=35746
Diffstat (limited to 'src/pkg/exp/eval/bridge.go')
-rw-r--r--src/pkg/exp/eval/bridge.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/pkg/exp/eval/bridge.go b/src/pkg/exp/eval/bridge.go
new file mode 100644
index 000000000..da2dd52a9
--- /dev/null
+++ b/src/pkg/exp/eval/bridge.go
@@ -0,0 +1,170 @@
+// 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.Position{}, name, nil, true, make(map[string] Method)};
+ evalTypes[t] = nt;
+ }
+
+ var et Type;
+ switch t := t.(type) {
+ case *reflect.BoolType:
+ et = BoolType;
+ case *reflect.Float32Type:
+ et = Float32Type;
+ case *reflect.Float64Type:
+ et = Float64Type;
+ case *reflect.FloatType:
+ et = FloatType;
+ case *reflect.Int16Type:
+ et = Int16Type;
+ case *reflect.Int32Type:
+ et = Int32Type;
+ case *reflect.Int64Type:
+ et = Int64Type;
+ case *reflect.Int8Type:
+ et = Int8Type;
+ case *reflect.IntType:
+ et = IntType;
+ case *reflect.StringType:
+ et = StringType;
+ case *reflect.Uint16Type:
+ et = Uint16Type;
+ case *reflect.Uint32Type:
+ et = Uint32Type;
+ case *reflect.Uint64Type:
+ et = Uint64Type;
+ case *reflect.Uint8Type:
+ et = Uint8Type;
+ case *reflect.UintType:
+ et = UintType;
+ case *reflect.UintptrType:
+ et = UintptrType;
+
+ case *reflect.ArrayType:
+ et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem()));
+ case *reflect.ChanType:
+ log.Crashf("%T not implemented", t);
+ case *reflect.FuncType:
+ nin := t.NumIn();
+ // Variadic functions have DotDotDotType at the end
+ varidic := false;
+ if nin > 0 {
+ if _, ok := t.In(nin - 1).(*reflect.DotDotDotType); ok {
+ varidic = true;
+ 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, varidic, out);
+ case *reflect.InterfaceType:
+ log.Crashf("%T not implemented", t);
+ case *reflect.MapType:
+ log.Crashf("%T not implemented", t);
+ case *reflect.PtrType:
+ et = NewPtrType(TypeFromNative(t.Elem()));
+ case *reflect.SliceType:
+ et = NewSliceType(TypeFromNative(t.Elem()));
+ case *reflect.StructType:
+ 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.UnsafePointerType:
+ log.Crashf("%T not implemented", t);
+ default:
+ log.Crashf("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);
+}