// 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); }