Ejemplo n.º 1
0
func BuildTypeHaxe() string {

	buildTBI()
	for i, t := range typesByID {
		if i > 0 {
			synthTypesFor(t)
		}
	}
	buildTBI()

	ret := "class Tgotypes {\n"

	for i, t := range typesByID {
		if i > 0 {
			ret += typeBuild(i, t)
		}
	}

	ret += "public static function setup() {\nvar a=Go.haxegoruntime_TTypeTTable.load();\n"
	ret += "var b=a.baseArray.obj;\nvar f=a.baseArray.off+a.itemOff(0);\nvar s=a.itemOff(1)-a.itemOff(0);\n"
	for i := range typesByID {
		if i > 0 {
			//fmt.Println("DEBUG setup",i,t)
			ret += fmt.Sprintf(
				"b.set((%d*s)+f,type%d());\n",
				i, i)
		}
	}

	ret += "}\n" + "}\n"

	pogo.WriteAsClass("Tgotypes", ret)

	//fmt.Println("DEBUG generated Haxe code:", ret)

	return ret
}
Ejemplo n.º 2
0
// Type definitions are only carried through to Haxe to allow access to objects as if they were native Haxe classes.
// TODO consider renaming
func (l langType) TypeStart(nt *types.Named, err string) string {
	typName := "GoType" + l.LangName("", nt.String())
	hxTyp := l.LangType(nt.Obj().Type(), false, nt.String())
	ret := ""
	switch hxTyp {
	case "Object":
		ret += "class " + typName
		ret += " extends " + hxTyp + " {\n"
	default:
		ret += "abstract " + typName + "(" + hxTyp + ") from " + hxTyp + " to " + hxTyp + " {\n"
	}
	switch nt.Underlying().(type) {
	case *types.Struct:
		str := nt.Underlying().(*types.Struct)
		ret += "inline public function new(){ super new(" + strconv.Itoa(int(haxeStdSizes.Sizeof(nt.Obj().Type()))) + "); }\n"
		flds := []string{}
		for f := 0; f < str.NumFields(); f++ {
			fName := str.Field(f).Name()
			if len(fName) > 0 {
				if unicode.IsUpper(rune(fName[0])) {
					flds = append(flds, fName)
				}
			}
		}
		sort.Strings(flds) // make sure the fields are always in the same order in the file
		for _, fName := range flds {
			for f := 0; f < str.NumFields(); f++ {
				if fName == str.Field(f).Name() {
					haxeTyp := l.LangType(str.Field(f).Type(), false, nt.String())
					fOff := fieldOffset(str, f)
					sfx := loadStoreSuffix(str.Field(f).Type(), true)
					ret += fmt.Sprintf("public var _%s(get,set):%s;\n", fName, haxeTyp)
					ret += fmt.Sprintf("function get__%s():%s { return get%s%d); }\n",
						fName, haxeTyp, sfx, fOff)
					ret += fmt.Sprintf("function set__%s(v:%s):%s { return set%s%d,v); }\n",
						fName, haxeTyp, haxeTyp, sfx, fOff)
					break
				}
			}
		}
	case *types.Array:
		ret += "inline public function new(){ super new(" + strconv.Itoa(int(haxeStdSizes.Sizeof(nt.Obj().Type()))) + "); }\n"
	default: // TODO not yet sure how to handle named types that are not structs
		ret += "inline public function new(v:" + hxTyp + ") { this = v; }\n"
	}

	meths := []string{}
	for m := 0; m < nt.NumMethods(); m++ {
		mName := nt.Method(m).Name()
		if len(mName) > 0 {
			if unicode.IsUpper(rune(mName[0])) {
				meths = append(meths, mName)
			}
		}
	}
	sort.Strings(meths) // make sure the methods always appear in the same order in the file
	for _, mName := range meths {
		for m := 0; m < nt.NumMethods(); m++ {
			meth := nt.Method(m)
			if mName == meth.Name() {
				sig := meth.Type().(*types.Signature)
				ret += "// " + mName + " " + sig.String() + "\n"
				ret += "public function _" + mName + "("
				for p := 0; p < sig.Params().Len(); p++ {
					if p > 0 {
						ret += ","
					}
					ret += "_" + sig.Params().At(p).Name() + ":" + l.LangType(sig.Params().At(p).Type(), false, nt.String())
				}
				ret += ")"
				switch sig.Results().Len() {
				case 0:
					ret += ":Void "
				case 1:
					ret += ":" + l.LangType(sig.Results().At(0).Type(), false, nt.String())
				default:
					ret += ":{"
					for r := 0; r < sig.Results().Len(); r++ {
						if r > 0 {
							ret += ","
						}
						ret += fmt.Sprintf("r%d:%s", r, l.LangType(sig.Results().At(r).Type(), false, nt.String()))
					}
					ret += "}"
				}
				ret += "{\n\t"
				if sig.Results().Len() > 0 {
					ret += "return "
				}
				fnToCall := l.LangName(
					nt.Obj().Pkg().Name()+":"+sig.Recv().Type().String(),
					meth.Name())
				ret += `Go_` + fnToCall + `.hx(this`
				for p := 0; p < sig.Params().Len(); p++ {
					ret += ", _" + sig.Params().At(p).Name()
				}
				ret += ");\n}\n"
			}
		}
	}

	pogo.WriteAsClass(typName, ret+"}\n")

	return "" //ret
}
Ejemplo n.º 3
0
func (l langType) EmitTypeInfo() string {

	BuildTypeHaxe() // generate the code to emulate compiler reflect data output

	var ret string
	ret += "\nclass TypeInfo{\n\n"

	ret += fmt.Sprintf("public static var nextTypeID=%d;\n", pogo.NextTypeID) // must be last as will change during processing

	// TODO review if this is required
	ret += "public static function isHaxeClass(id:Int):Bool {\nswitch(id){" + "\n"
	for k := range pteKeys {
		v := pte.At(pteKeys[k])
		goType := pteKeys[k].String()
		//fmt.Println("DEBUG full goType", goType)
		haxeClass := getHaxeClass(goType)
		if haxeClass != "" {
			ret += "case " + fmt.Sprintf("%d", v) + `: return true; // ` + goType + "\n"
		}
	}
	ret += `default: return false;}}` + "\n"

	ret += "public static function getName(id:Int):String {\n"
	ret += "\tif(id<0||id>=nextTypeID)return \"reflect.CREATED\"+Std.string(id);\n"
	ret += "\tif(id==0)return \"(haxeTypeID=0)\";" + "\n"
	ret += "\t#if (js || php || node) if(id==null)return \"(haxeTypeID=null)\"; #end\n"
	ret += "\t" + `return Go_haxegoruntime_getTTypeSString.callFromRT(0,id);` + "\n}\n"
	ret += "public static function typeString(i:Interface):String {\nreturn getName(i.typ);\n}\n"
	/*
		ret += "static var typIDs:Map<String,Int> = ["
		deDup := make(map[string]bool)
		for k := range pteKeys {
			v := pte.At(pteKeys[k])
			nam := haxeStringConst("`"+preprocessTypeName(pteKeys[k].String())+"`", "CompilerInternal:haxe.EmitTypeInfo()")
			if len(nam) != 0 {
				if deDup[nam] { // have one already!!
					nam = fmt.Sprintf("%s (duplicate type name! this id=%d)\"", nam[:len(nam)-1], v)
				} else {
					deDup[nam] = true
				}
				ret += ` ` + nam + ` => ` + fmt.Sprintf("%d", v) + `,` + "\n"
			}
		}
		ret += "];\n"
	*/
	ret += "public static function getId(name:String):Int {\n"
	ret += "\tvar t:Int;\n"
	//ret += "\ttry { t=typIDs[name];\n"
	//ret += "\t} catch(x:Dynamic) { Scheduler.panicFromHaxe(\"TraceInfo.getId() not found:\"+name+x); t=-1; } ;\n"
	ret += "\t" + `t = Go_haxegoruntime_getTTypeIIDD.callFromRT(0,name);` + "\n"
	ret += "\treturn t;\n}\n"

	//function to answer the question is the type a concrete value?
	ret += "public static function isConcrete(t:Int):Bool {\nswitch(t){" + "\n"
	for T := range pteKeys {
		t := pte.At(pteKeys[T])
		switch pteKeys[T].Underlying().(type) {
		case *types.Interface:
			ret += `case ` + fmt.Sprintf("%d", t) + `: return false;` + "\n"
		}
	}
	ret += "default: return true;}}\n"

	//emulation of: func IsIdentical(x, y Type) bool
	ret += "public static function isIdentical(v:Int,t:Int):Bool {\nif(v==t) return true;\nswitch(v){" + "\n"
	for V := range pteKeys {
		v := pte.At(pteKeys[V])
		ret0 := ""
		for T := range pteKeys {
			t := pte.At(pteKeys[T])
			if v != t && types.Identical(pteKeys[V], pteKeys[T]) {
				ret0 += `case ` + fmt.Sprintf("%d", t) + `: return true;` + "\n"
			}
		}
		if ret0 != "" {
			ret += `case ` + fmt.Sprintf("%d", v) + `: switch(t){` + "\n"
			ret += ret0
			ret += "default: return false;}\n"
		}
	}
	ret += "default: return false;}}\n"

	ret += "}\n"

	pogo.WriteAsClass("TypeInfo", ret)

	ret = "class TypeAssign {"

	//emulation of: func IsAssignableTo(V, T Type) bool
	ret += "public static function isAssignableTo(v:Int,t:Int):Bool {\n\tif(v==t) return true;\n"
	ret += "\tfor(ae in isAsssignableToArray) if(ae==(v<<16|t)) return true;\n"
	ret += "\treturn false;\n}\n"

	ret += "static var isAsssignableToArray:Array<Int> = ["
	for V := range pteKeys {
		v := pte.At(pteKeys[V])
		for T := range pteKeys {
			t := pte.At(pteKeys[T])
			if v != t && types.AssignableTo(pteKeys[V], pteKeys[T]) {
				ret += fmt.Sprintf("%d,", v.(int)<<16|t.(int))
			}
		}
		ret += "\n"
	}
	ret += "];\n"

	ret += "}\n"

	pogo.WriteAsClass("TypeAssign", ret)

	/*
		ret = "class TypeAssert {"

		//emulation of: func type.AsertableTo(V *Interface, T Type) bool
		ret += "public static function assertableTo(v:Int,t:Int):Bool {\n"
		//ret += "trace(\"DEBUG assertableTo()\",v,t);\n"
		ret += "\tif(v==t) return true;\n"
		ret += "\tfor(ae in isAssertableToArray) if(ae==(v<<16|t)) return true;\n"
		ret += "return false;\n}\n"
		ret += "static var isAssertableToArray:Array<Int> = [ "
		for tid, typ := range typesByID {
			ret0 := ""
			if typ != nil {
				for iid, ityp := range typesByID {
					if ityp != nil {
						iface, isIface := ityp.Underlying().(*types.Interface)
						if isIface {
							if tid != iid && types.AssertableTo(iface, typ) {
								ret0 += fmt.Sprintf("0x%08X,", (tid<<16)|iid)
							}
						}
					}
				}
			}
			if ret0 != "" {
				ret += ret0
				ret += "\n"
			}
		}
		ret += "];\n"

		ret += "}\n"

		pogo.WriteAsClass("TypeAssert", ret)
	*/

	ret = "class TypeZero {"

	// function to give the zero value for each type
	ret += "public static function zeroValue(t:Int):Dynamic {\nswitch(t){" + "\n"
	for T := range pteKeys {
		t := pte.At(pteKeys[T])
		z := l.LangType(pteKeys[T], true, "EmitTypeInfo()")
		if z == "" {
			z = "null"
		}
		if z != "null" {
			ret += `case ` + fmt.Sprintf("%d", t) + `: return `
			ret += z + ";\n"
		}
	}
	ret += "default: return null;}}\n"

	ret += "}\n"

	pogo.WriteAsClass("TypeZero", ret)
	/*
		ret = "class MethodTypeInfo {"

		ret += "public static function method(t:Int,m:String):Dynamic {\nswitch(t){" + "\n"

		tta := pogo.TypesWithMethodSets() //[]types.Type
		sort.Sort(pogo.TypeSorter(tta))
		for T := range tta {
			t := pte.At(tta[T])
			if t != nil { // it is used?
				ret += `case ` + fmt.Sprintf("%d", t) + `: switch(m){` + "\n"
				ms := types.NewMethodSet(tta[T])
				msNames := []string{}
				for m := 0; m < ms.Len(); m++ {
					msNames = append(msNames, ms.At(m).String())
				}
				sort.Strings(msNames)
				deDup := make(map[string][]int) // TODO check this logic, required for non-public methods
				for pass := 1; pass <= 2; pass++ {
					for _, msString := range msNames {
						for m := 0; m < ms.Len(); m++ {
							if ms.At(m).String() == msString { // ensure we do this in a repeatable order
								funcObj, ok := ms.At(m).Obj().(*types.Func)
								pkgName := "unknown"
								if ok && funcObj.Pkg() != nil && ms.At(m).Recv() == tta[T] {
									line := ""
									ss := strings.Split(funcObj.Pkg().Name(), "/")
									pkgName = ss[len(ss)-1]
									if strings.HasPrefix(pkgName, "_") { // exclude functions in haxe for now
										// TODO NoOp for now... so haxe types cant be "Involked" when held in interface types
										// *** need to deal with getters and setters
										// *** also with calling parameters which are different for a Haxe API
									} else {
										switch pass {
										case 1:
											idx, exists := deDup[funcObj.Name()]
											if exists {
												if len(idx) > len(ms.At(m).Index()) {
													deDup[funcObj.Name()] = ms.At(m).Index()
												}
											} else {
												deDup[funcObj.Name()] = ms.At(m).Index()
											}
										case 2:
											idx, _ := deDup[funcObj.Name()]
											if len(idx) != len(ms.At(m).Index()) {
												line += "// Duplicate unused: "
											}
											line += `case "` + funcObj.Name() + `": return `
											fnToCall := l.LangName(
												ms.At(m).Obj().Pkg().Name()+":"+ms.At(m).Recv().String(),
												funcObj.Name())
											line += `Go_` + fnToCall + `.call` + "; "
										}
									}
									ret += line
								}
								if pass == 2 {
									ret += fmt.Sprintf("// %v %v %v %v\n",
										ms.At(m).Obj().Name(),
										ms.At(m).Kind(),
										ms.At(m).Index(),
										ms.At(m).Indirect())
								}
							}
						}
					}
				}
				ret += "default:}\n"
			}
		}

		// TODO look for overloaded types at this point

		ret += "default:}\n Scheduler.panicFromHaxe( " + `"no method found!"` + "); return null;}\n" // TODO improve error

		pogo.WriteAsClass("MethodTypeInfo", ret+"}\n")
	*/
	return ""
}