func (l langType) LangType(t types.Type, retInitVal bool, errorInfo string) string { if pogo.IsValidInPogo(t, errorInfo) { switch t.(type) { case *types.Basic: switch t.(*types.Basic).Kind() { case types.Bool, types.UntypedBool: if retInitVal { return "false" } return "Bool" case types.String, types.UntypedString: if retInitVal { return `""` } return "String" case types.Float64, types.Float32, types.UntypedFloat: if retInitVal { return "0.0" } return "Float" case types.Complex64, types.Complex128, types.UntypedComplex: if retInitVal { return "new Complex(0.0,0.0)" } return "Complex" case types.Int, types.Int8, types.Int16, types.Int32, types.UntypedRune, types.Uint8, types.Uint16, types.Uint, types.Uint32: // NOTE: untyped integers default to Int without a warning if retInitVal { return "0" } return "Int" case types.Int64, types.Uint64: if retInitVal { return "GOint64.make(0,0)" } return "GOint64" case types.UntypedInt: // TODO: investigate further the situations in which this warning is generated pogo.LogWarning(errorInfo, "Haxe", fmt.Errorf("haxe.LangType() types.UntypedInt is ambiguous")) return "UNTYPED_INT" // NOTE: if this value were ever to be used, it would cause a Haxe compilation error case types.UnsafePointer: if retInitVal { return "new UnsafePointer(null)" // TODO is this correct? or should it be null } return "UnsafePointer" case types.Uintptr: // Uintptr sometimes used as an integer type, sometimes as a container for another type if retInitVal { return "null" } return "Dynamic" default: pogo.LogWarning(errorInfo, "Haxe", fmt.Errorf("haxe.LangType() unrecognised basic type, Dynamic assumed")) if retInitVal { return "null" } return "Dynamic" } case *types.Interface: if retInitVal { return `null` } return "Interface" case *types.Named: return l.LangType(t.(*types.Named).Underlying(), retInitVal, errorInfo) case *types.Chan: if retInitVal { return "new Channel<" + l.LangType(t.(*types.Chan).Elem(), false, errorInfo) + ">(1)" } return "Channel<" + l.LangType(t.(*types.Chan).Elem(), false, errorInfo) + ">" case *types.Map: if retInitVal { return "new Map<" + l.LangType(t.(*types.Map).Key(), false, errorInfo) + "," + l.LangType(t.(*types.Map).Elem(), false, errorInfo) + ">()" } return "Map<" + l.LangType(t.(*types.Map).Key(), false, errorInfo) + "," + l.LangType(t.(*types.Map).Elem(), false, errorInfo) + ">" case *types.Slice: if retInitVal { return "new Slice(new Pointer(new Array<" + l.LangType(t.(*types.Slice).Elem(), false, errorInfo) + ">()),0,0" + ")" } return "Slice" case *types.Array: // TODO consider using Vector rather than Array, if faster and can be made to work if retInitVal { return "{var _v=new Array<" + l.LangType(t.(*types.Array).Elem(), false, errorInfo) + fmt.Sprintf(">();for(_vi in 0...%d){_v[_vi]=%s;}; _v;}", t.(*types.Array).Len(), l.LangType(t.(*types.Array).Elem(), true, errorInfo)) } return "Array<" + l.LangType(t.(*types.Array).Elem(), false, errorInfo) + ">" case *types.Struct: // TODO as this is fixed-length, should it be a Vector, like types.Array ? // TODO consider if it is possible to change from Array<Dynamic> to individual named elements - requires considerable work to do this if retInitVal { ret := "{var _v=new Array<Dynamic>();_v=[" for ele := 0; ele < t.(*types.Struct).NumFields(); ele++ { if ele != 0 { ret += "," } ret += l.LangType(t.(*types.Struct).Field(ele).Type().Underlying(), true, errorInfo) } return ret + "]; _v;}" } return "Array<Dynamic>" case *types.Tuple: // what is returned by a call and some other instructions, not in the Go language spec! tup := t.(*types.Tuple) switch tup.Len() { case 0: return "" case 1: return l.LangType(tup.At(0).Type().Underlying(), retInitVal, errorInfo) default: ret := "{" for ele := 0; ele < tup.Len(); ele++ { if ele != 0 { ret += "," } ret += pogo.MakeId("r"+fmt.Sprintf("%d", ele)) + ":" + l.LangType(tup.At(ele).Type().Underlying(), retInitVal, errorInfo) } return ret + "}" } case *types.Pointer: if retInitVal { // NOTE pointer declarations create endless recursion for self-referencing structures unless initialized with null return "null" //rather than: + l.LangType(t.(*types.Pointer).Elem(), retInitVal, errorInfo) + ")" } return "Pointer" case *types.Signature: if retInitVal { return "null" } ret := "Closure" return ret default: rTyp := reflect.TypeOf(t).String() if rTyp == "*ssa.opaqueType" { // NOTE the type for map itterators, not in the Go language spec! if retInitVal { // use dynamic type, brief tests seem OK, but may not always work on static hosts return "null" } return "Dynamic" } pogo.LogError(errorInfo, "Haxe", fmt.Errorf("haxe.LangType() internal error, unhandled non-basic type: %s", rTyp)) } } return "UNKNOWN_LANGTYPE" // this should generate a Haxe compiler error }
func (l langType) LangType(t types.Type, retInitVal bool, errorInfo string) string { if pogo.IsValidInPogo(t, errorInfo) { switch t.(type) { case *types.Basic: switch t.(*types.Basic).Kind() { case types.Bool, types.UntypedBool: if retInitVal { return "false" } return "Bool" case types.String, types.UntypedString: if retInitVal { return `""` } return "String" case types.Float64, types.Float32, types.UntypedFloat: if retInitVal { return "0.0" } return "Float" case types.Complex64, types.Complex128, types.UntypedComplex: if retInitVal { return "new Complex(0.0,0.0)" } return "Complex" case types.Int, types.Int8, types.Int16, types.Int32, types.UntypedRune, types.Uint8, types.Uint16, types.Uint, types.Uint32: // NOTE: untyped runes default to Int without a warning if retInitVal { return "0" } return "Int" case types.Int64, types.Uint64: if retInitVal { return "GOint64.ofInt(0)" } return "GOint64" case types.UntypedInt: // TODO: investigate further the situations in which this warning is generated if retInitVal { return "0" } return "UNTYPED_INT" // NOTE: if this value were ever to be used, it would cause a Haxe compilation error case types.UnsafePointer: if retInitVal { return "null" // NOTE ALL pointers are unsafe } return "Pointer" case types.Uintptr: // Uintptr sometimes used as an integer type, sometimes as a container for another type if retInitVal { return "null" } return "Dynamic" default: pogo.LogWarning(errorInfo, "Haxe", fmt.Errorf("haxe.LangType() unrecognised basic type, Dynamic assumed")) if retInitVal { return "null" } return "Dynamic" } case *types.Interface: if retInitVal { return `null` } return "Interface" case *types.Named: haxeName := getHaxeClass(t.(*types.Named).String()) //fmt.Println("DEBUG Go named type -> Haxe type :", t.(*types.Named).String(), "->", haxeName) if haxeName != "" { if retInitVal { return `null` // NOTE code to the right does not work in openfl/flash: `Type.createEmptyInstance(` + haxeName + ")" } return haxeName } return l.LangType(t.(*types.Named).Underlying(), retInitVal, errorInfo) case *types.Chan: if retInitVal { return "new Channel(1)" //waa: <" + l.LangType(t.(*types.Chan).Elem(), false, errorInfo) + ">(1)" } return "Channel" //was: <" + l.LangType(t.(*types.Chan).Elem(), false, errorInfo) + ">" case *types.Map: if retInitVal { k := t.(*types.Map).Key().Underlying() kv := l.LangType(k, true, errorInfo) e := t.(*types.Map).Elem().Underlying() ev := "null" // TODO review, required for encode/gob to stop recursion if _, isMap := e.(*types.Map); !isMap { ev = l.LangType(e, true, errorInfo) } return "new GOmap(" + kv + "," + ev + ")" } return "GOmap" case *types.Slice: if retInitVal { return "new Slice(Pointer.make(" + "Object.make(0)" + "),0,0,0," + "1" + arrayOffsetCalc(t.(*types.Slice).Elem().Underlying()) + ")" } return "Slice" case *types.Array: if retInitVal { return fmt.Sprintf("Object.make(%d)", haxeStdSizes.Sizeof(t)) } return "Object" case *types.Struct: if retInitVal { return fmt.Sprintf("Object.make(%d)", haxeStdSizes.Sizeof(t.(*types.Struct).Underlying())) } return "Object" case *types.Tuple: // what is returned by a call and some other instructions, not in the Go language spec! tup := t.(*types.Tuple) switch tup.Len() { case 0: return "" case 1: return l.LangType(tup.At(0).Type().Underlying(), retInitVal, errorInfo) default: ret := "{" for ele := 0; ele < tup.Len(); ele++ { if ele != 0 { ret += "," } ret += pogo.MakeID("r"+fmt.Sprintf("%d", ele)) + ":" if !retInitVal { ret += "Null<" } ret += l.LangType(tup.At(ele).Type().Underlying(), retInitVal, errorInfo) if !retInitVal { ret += ">" } } return ret + "}" } case *types.Pointer: if retInitVal { // NOTE pointer declarations create endless recursion for self-referencing structures unless initialized with null return "null" //rather than: + l.LangType(t.(*types.Pointer).Elem(), retInitVal, errorInfo) + ")" } return "Pointer" case *types.Signature: if retInitVal { return "null" } ret := "Closure" return ret default: rTyp := reflect.TypeOf(t).String() if rTyp == "*ssa.opaqueType" { // NOTE the type for map itterators, not in the Go language spec! if retInitVal { // use dynamic type, brief tests seem OK, but may not always work on static hosts return "null" } return "Dynamic" } pogo.LogError(errorInfo, "Haxe", fmt.Errorf("haxe.LangType() internal error, unhandled non-basic type: %s", rTyp)) } } return "UNKNOWN_LANGTYPE" // this should generate a Haxe compiler error }