func loc(l string) string { _, file, line, ok := runtime.Caller(2) if !ok { return "???" } return file + ":" + hx.CallString("", "Std.string", 1, line) + " " + l }
func (f *Func) FileLine(pc uintptr) (file string, line int) { //FileLine returns the file name and line number of the source code corresponding to the program counter pc. The result will not be accurate if pc is not a program counter within f. detail := hx.CallString("", "Go.CPos", 1, pc) if len(detail) == 0 { return "", 0 } if detail[0] == '(' { // error return return "", 0 } if detail[0:5] == "near " { detail = detail[5:] } for i, c := range detail { if c == ':' { file = detail[:i] x := hx.CallIface("", "int", "Std.parseInt", 1, detail[i+1:]) if x == nil { return "", 0 } line = x.(int) return file, line } } // should never get here return "", 0 }
// interfaceToDynamic - limited runtime conversion of Go->Haxe types // TODO consider making public func interfaceToDynamic(a interface{}) uintptr { //fmt.Printf("DEBUG interfaceToDynamic a= %v:%T\n", a, a) if a == nil { return hx.Null() } switch a.(type) { case []interface{}: //println("DEBUG []interface{}") ret := hx.New("", "Array<Dynamic>", 0) for _, aa := range a.([]interface{}) { //fmt.Printf("DEBUG aa= %v:%T\n", aa, aa) val := interfaceToDynamic(aa) //fmt.Println("DEBUG val=" + hx.CallString("", "Std.string", 1, val)) hx.Code("", "_a.param(0).val.push(_a.param(1).val);", ret, val) } return ret case bool, string, int, float64: return hx.CodeDynamic("", "_a.param(0).val;", a) case []byte: return hx.CodeDynamic("", "Slice.toBytes(cast(_a.param(0).val,Slice));", a) default: panic("Unhandled Go interface{} to Haxe Dynamic: " + hx.CallString("", "Std.string", 1, a)) } return hx.Null() }
// dynamicToInterface - limited runtime conversion of Haxe->Go types // with URL un-escaping of strings // TODO consider making public func dynamicToInterface(dyn uintptr) interface{} { switch { case hx.CodeBool("", "Std.is(_a.param(0).val,Array);", dyn): l := hx.CodeInt("", "_a.param(0).val.length;", dyn) ret := make([]interface{}, l) for i := 0; i < l; i++ { ret[i] = dynamicToInterface(hx.CodeDynamic("", "_a.param(0).val[_a.param(1).val];", dyn, i)) } return ret case hx.IsNull(dyn): return nil case hx.CodeBool("", "Std.is(_a.param(0).val,Bool);", dyn): return hx.CodeBool("", "_a.param(0).val;", dyn) case hx.CodeBool("", "Std.is(_a.param(0).val,Int);", dyn): return hx.CodeInt("", "_a.param(0).val;", dyn) case hx.CodeBool("", "Std.is(_a.param(0).val,Float);", dyn): return hx.CodeFloat("", "_a.param(0).val;", dyn) case hx.CodeBool("", "Std.is(_a.param(0).val,String);", dyn): return hx.CodeString("", "_a.param(0).val;", dyn) case hx.CodeBool("", "Std.is(_a.param(0).val,haxe.io.Bytes);", dyn): return hx.CodeIface("", "[]byte", "Slice.fromBytes(_a.param(0).val);", dyn) default: panic("unhandled haxe Dynamic to Go interface{} :" + hx.CallString("", "Std.string", 1, dyn)) } return nil }
func Sprint(a ...interface{}) string { ret := "" for i := range a { ret += hx.CallString("", "Std.string", 1, a[i]) ret += " " } return ret }
func naclSeek(fd int, off *int64, whence int) (err error) { //_, _, e1 := Syscall(sys_lseek, uintptr(fd), uintptr(unsafe.Pointer(off)), uintptr(whence)) //if e1 != 0 { // err = e1 //} panic("syscall.naclSeek(" + hx.CallString("", "Std.string", 1, fd) + ")") return }
func naclFstat(fd int, stat *Stat_t) (err error) { //_, _, e1 := Syscall(sys_fstat, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) //if e1 != 0 { // err = e1 //} panic("syscall.naclFstat(" + hx.CallString("", "Std.string", 1, fd) + ")") return }
func naclClose(fd int) (err error) { //_, _, e1 := Syscall(sys_close, uintptr(fd), 0, 0) //if e1 != 0 { // err = e1 //} panic("syscall.naclClose(" + hx.CallString("", "Std.string", 1, fd) + ")") return }
// implemented in package runtime, to add time header on playground func naclWrite(fd int, b []byte) int { switch fd { case 1, 2: // stdout,stderr hx.Call("", "Console.naclWrite", 1, string(b)) return len(b) default: panic("syscall.naclWrite(" + hx.CallString("", "Std.string", 1, fd) + "," + string(b) + ")") return 0 } }
func Stack(buf []byte, all bool) int { // TODO: use the all flag! s := hx.CallString("", "Scheduler.stackDump", 0) if len(s) > len(buf) { return 0 } for i := 0; i < len(s); i++ { buf[i] = s[i] } return len(s) }
func naclRead(fd int, b []byte) (n int, err error) { //var _p0 unsafe.Pointer //if len(b) > 0 { // _p0 = unsafe.Pointer(&b[0]) //} else { // _p0 = unsafe.Pointer(&_zero) //} //r0, _, e1 := Syscall(sys_read, uintptr(fd), uintptr(_p0), uintptr(len(b))) //n = int(r0) //if e1 != 0 { // err = e1 //} if fd == 0 { panic("syscall.naclRead(stdin," + hx.CallString("", "Std.string", 1, len(b)) + ")") return } panic("syscall.naclRead(" + hx.CallString("", "Std.string", 1, fd) + "," + hx.CallString("", "Std.string", 1, len(b)) + ")") return }
func Exit(code int) (err error) { //_, _, e1 := Syscall(sys_exit, uintptr(code), 0, 0) //if e1 != 0 { // err = e1 //} hx.Call("(cpp || cs || java || macro || neko || php || python)", "Sys.exit", 1, code) if code == 0 { hx.Code("js", "untyped __js__('process.exit(0)');") // only works on Node } else { // all non-zero values return as 1 hx.Code("js", "untyped __js__('process.exit(1)');") // only works on Node } panic("syscall.Exit(" + hx.CallString("", "Std.string", 1, code) + ")") return }
"github.com/tardisgo/tardisgo/haxe/hx" ) func init() { } // Haxe specific func UnzipTestFS() { // this will be overwritten by the compiler println("DEBUG runtime:UnzipTestFS()") } // Constant values const Compiler = "gc" //"TARDISgo" // this is checked by the proper runtime, so might need to be "gc" var GOARCH string = hx.CallString("", "Go.Platform", 0) const GOOS string = "nacl" // of course it is only an emulation of nacl... var MemProfileRate int = 512 * 1024 // TODO not currently used // NOT YET IMPLEMENTED type BlockProfileRecord struct { Count int64 Cycles int64 StackRecord } func BlockProfile(p []BlockProfileRecord) (n int, ok bool) { panic("TODO:runtime.BlockProfile")
func (c Conn) Go(serviceMethod string, args, reply interface{}, done chan *Call) *Call { call := &Call{ ServiceMethod: serviceMethod, Args: args, Reply: reply, Error: nil, Done: done, } c.mutex.Lock() hx.Meth("", c.conn, "TgoConnect", "setErrorHandler", 1, func(e uintptr) { call.Error = errors.New(hx.CallString("", "Std.string", 1, e)) done <- call c.mutex.Unlock() }) //fmt.Printf("DEBUG args=%v:%T\n", args, args) var networkOut bytes.Buffer enc := gob.NewEncoder(&networkOut) err := enc.Encode(args) if err != nil { call.Error = err done <- call c.mutex.Unlock() return call } var networkOut2 bytes.Buffer enc2 := gob.NewEncoder(&networkOut2) err = enc2.Encode(reply) if err != nil { call.Error = err done <- call c.mutex.Unlock() return call } ifa := []interface{}{serviceMethod, base64.StdEncoding.EncodeToString(networkOut.Bytes()), base64.StdEncoding.EncodeToString(networkOut2.Bytes())} //fmt.Printf("DEBUG ifa %#v:%T\n", ifa, ifa) haxeArgs := interfaceToDynamic(ifa) //fmt.Println("DEBUG haxe ifa", hx.CallString("", "Std.string", 1, haxeArgs)) hx.Meth("", c.conn, "TgoConnect", "call", 2, haxeArgs, func(r uintptr) { c.mutex.Unlock() // another call can begin before processing what's below //hx.Call("", "trace", 1, r) rA, ok := dynamicToInterface(r).([]interface{}) if !ok { call.Error = errors.New("returned value not an []interface{} in tgocall") } else { errMsg, ok := rA[1].(string) if !ok { call.Error = errors.New("returned error message not a string in tgocall") } else { if errMsg != "" { call.Error = errors.New(errMsg) } else { back64, ok := rA[0].(string) //println("back64: " + back64) if !ok { call.Error = errors.New("returned encoded data not a string in tgocall") } else { backBuf, err64 := base64.StdEncoding.DecodeString(back64) if err64 != nil { //println("DEBUG TgoConnect returned base64 string " + // back64 + " has error " + err64.Error()) call.Error = err64 } else { networkBack := bytes.NewBuffer(backBuf) dec := gob.NewDecoder(networkBack) err = dec.Decode(call.Reply) if err != nil { call.Error = err } } } } } } done <- call }) return call }