// 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 StartTimer(up unsafe.Pointer) { // function body is an Haxe addition StopTimer(up) // just in case it is still running rt := (*runtimeTimer)(up) for !hx.IsNull(rt.seq) { // wait for the timer to stop -- NOTE potential for deadlock? //println("DEBUG Wait for timer to stop") runtime.Gosched() } go HaxeTimer(up) }
func getMethod(tid int, path, name string) uintptr { //println("DEBUG getMethod:", tid, path, name) if tid < 1 || tid >= len(TypeTable) { // entry 0 is always nil hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() type id out of range") } rt := TypeTable[tid] ut := (*uncommonType)(rt.uncommonType) if ut == nil { hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() type has no uncommonType record") } if name == "" { hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() no method name") } exported := false if name[0] >= 'A' && name[0] <= 'Z' { exported = true // exported name, so path should be "" path = "" } if path != "" { for _, m := range ut.methods { // TODO these should be in order, so could use sort.search to speed up? mname := "" if m.name != nil { mname = *m.name } mpath := "" if m.pkgPath != nil { mpath = *m.pkgPath } //println("DEBUG check:", getTypeString(tid), mname, name, mpath, path) if mname == name && mpath == path { ret := m.ifn // is ifn the right one? if hx.IsNull(ret) { hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() null method for "+ getTypeString(tid)+"."+name+" called from "+path) } //println("DEBUG found:", getTypeString(tid), path, name, ret) return ret } } } else { // no path so find the method without the path, but only if it is unique when not exported found := -1 for f, m := range ut.methods { // TODO these should be in order, so could use sort.search to speed up? mname := "" if m.name != nil { mname = *m.name } //println("DEBUG check (ignore path):", getTypeString(tid), mname, name) if mname == name { //println("DEBUG found (ignore path):", getTypeString(tid), name) if found == -1 { found = f if exported { break } } else { hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() duplicates method found (ignoring path) for "+ getTypeString(tid)+"."+name+" called from "+path) } } } if found >= 0 { ret := ut.methods[found].ifn // is ifn the right one? if hx.IsNull(ret) { hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() null method for "+ getTypeString(tid)+"."+name+" called from "+path) } return ret } } //println("DEBUG not found:", getTypeString(tid), path, name) hx.Call("", "Scheduler.panicFromHaxe", 1, "haxegoruntime.method() no method found for "+ getTypeString(tid)+"."+name+" called from "+path) return 0 }
func (p *pp) handleMethods(verb rune, depth int) (handled bool) { if p.erroring { return } // Is it a Formatter? if formatter, ok := p.arg.(Formatter); ok { handled = true defer p.restoreSpecialFlags(p.clearSpecialFlags()) defer p.catchPanic(p.arg, verb) if hx.IsNull(hx.CodeDynamic("", "_a.itemAddr(0).load().val;", formatter)) { panic("<nil>") } formatter.Format(p, verb) return } // If we're doing Go syntax and the argument knows how to supply it, take care of it now. if p.fmt.sharpV { if stringer, ok := p.arg.(GoStringer); ok { handled = true defer p.catchPanic(p.arg, verb) if hx.IsNull(hx.CodeDynamic("", "_a.itemAddr(0).load().val;", stringer)) { panic("<nil>") } // Print the result of GoString unadorned. p.fmt.fmt_s(stringer.GoString()) return } } else { // If a string is acceptable according to the format, see if // the value satisfies one of the string-valued interfaces. // Println etc. set verb to %v, which is "stringable". switch verb { case 'v', 's', 'x', 'X', 'q': // Is it an error or Stringer? // The duplication in the bodies is necessary: // setting handled and deferring catchPanic // must happen before calling the method. switch v := p.arg.(type) { case error: handled = true defer p.catchPanic(p.arg, verb) if hx.IsNull(hx.CodeDynamic("", "_a.itemAddr(0).load().val;", v)) { panic("<nil>") } p.printArg(v.Error(), verb, depth) return case Stringer: handled = true defer p.catchPanic(p.arg, verb) if hx.IsNull(hx.CodeDynamic("", "_a.itemAddr(0).load().val;", v)) { panic("<nil>") } p.printArg(v.String(), verb, depth) return } } } return false }