github.com/tardisgo/tardisgo@v0.0.0-20161119180838-e0dd9a7e46b5/haxe/hxpseudofuncs.go (about) 1 package haxe 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "strconv" 8 "strings" 9 10 "go/constant" 11 12 "golang.org/x/tools/go/ssa" 13 14 "github.com/tardisgo/tardisgo/tgoutil" 15 ) 16 17 var pseudoFnPrefix = tgoutil.MakeID("github.com/tardisgo/tardisgo/haxe/hx_") 18 19 func (l langType) hxPseudoFuncs(fnToCall string, args []ssa.Value, errorInfo string) string { 20 //fmt.Println("DEBUG l.hxPseudoFuncs()", fnToCall, args, errorInfo) 21 fnToCall = strings.TrimPrefix(fnToCall, pseudoFnPrefix) 22 23 switch fnToCall { 24 case "SSource": 25 fn := strings.Trim(args[0].(*ssa.Const).Value.String(), "\"") 26 fn = l.hc.langEntry.TgtDir + string(os.PathSeparator) + fn + ".hx" 27 code := strings.Trim(args[1].(*ssa.Const).Value.String(), "\"") 28 code = strings.Replace(code, "\\n", "\n", -1) 29 code = strings.Replace(code, "\\t", "\t", -1) 30 code = strings.Replace(code, "\\\"", "\"", -1) 31 //println("DEBUG fn: " + fn + "\nCode: " + code) 32 err := ioutil.WriteFile(fn, []byte(code), 0666) 33 if err != nil { 34 l.PogoComp().LogError(errorInfo, "Haxe", err) 35 } 36 return "" 37 case "init": 38 return "" // no need to generate code for the go init function 39 case "RResource": 40 return "Slice.fromResource(" + l.IndirectValue(args[0], errorInfo) + ");" 41 case "MMalloc": 42 return "Pointer.make(Object.make(Force.toInt(" + l.IndirectValue(args[0], errorInfo) + ")));" 43 case "IIsNNull": 44 return l.IndirectValue(args[0], errorInfo) + "==null;" 45 case "NNull": 46 return "null;" 47 case "CComplex": 48 return "cast(" + l.IndirectValue(args[0], errorInfo) + ",Complex);" 49 case "IInt64": 50 return "new GOint64(" + l.IndirectValue(args[0], errorInfo) + ");" 51 case "CCallbackFFunc": 52 // NOTE there will be a preceeding MakeInterface call that is made redundant by this code 53 if len(args) == 1 { 54 goMI, ok := args[0].(*ssa.MakeInterface) 55 if ok { 56 goFn, ok := (*(goMI.Operands(nil)[0])).(*ssa.Function) 57 if ok { 58 return "new Interface(-1," + l.IndirectValue(args[0], errorInfo) + ".val.buildCallbackFn()); // Go_" + l.FuncName(goFn) 59 } 60 _, ok = (*(goMI.Operands(nil)[0])).(*ssa.MakeClosure) 61 if ok { 62 return "new Interface(-1," + l.IndirectValue(args[0], errorInfo) + ".val.buildCallbackFn());" 63 } 64 con, ok := (*(goMI.Operands(nil)[0])).(*ssa.Const) 65 if ok { 66 return "new Interface(-1," + l.tgoString(l.IndirectValue(con, errorInfo), errorInfo) + ");" 67 } 68 } 69 } 70 l.PogoComp().LogError(errorInfo, "Haxe", fmt.Errorf("hx.Func() argument is not a function constant")) 71 return "" 72 } 73 74 argOff := 1 // because of the ifLogic 75 wrapStart := "" 76 wrapEnd := "" 77 usesArgs := true 78 79 ifLogic := l.IndirectValue(args[0], errorInfo) 80 //fmt.Println("DEBUG:ifLogic=", ifLogic, "AT", errorInfo) 81 ifLogic = l.tgoString(ifLogic, errorInfo) 82 if len(ifLogic) > 0 { 83 wrapStart = " #if (" + ifLogic + ") " 84 defVal := "null" 85 if strings.HasSuffix(fnToCall, "Bool") { 86 defVal = "false" 87 } 88 if strings.HasSuffix(fnToCall, "Int") { 89 defVal = "0" 90 } 91 if strings.HasSuffix(fnToCall, "Float") { 92 defVal = "0.0" 93 } 94 if strings.HasSuffix(fnToCall, "String") { 95 defVal = `""` 96 } 97 wrapEnd = " #else " + defVal + "; #end " 98 } 99 100 if strings.HasSuffix(fnToCall, "SString") && 101 !strings.HasPrefix(fnToCall, "CCode") && 102 !strings.HasPrefix(fnToCall, "FFset") && 103 !strings.HasPrefix(fnToCall, "SSet") { 104 wrapStart += " Force.fromHaxeString({" 105 wrapEnd = "});" + wrapEnd 106 } 107 108 if strings.HasSuffix(fnToCall, "IIface") { 109 argOff = 2 110 wrapStart += "new Interface(TypeInfo.getId(" + l.IndirectValue(args[1], errorInfo) + "),{" 111 wrapEnd = "});" + wrapEnd 112 } 113 code := "" 114 if strings.HasPrefix(fnToCall, "NNew") { 115 code = "new " 116 } 117 if strings.HasPrefix(fnToCall, "CCode") || strings.HasPrefix(fnToCall, "GGet") { 118 givenConst, givenConstOK := args[argOff].(*ssa.Const) 119 if givenConstOK { 120 if givenConst.Value.Kind() == constant.String { 121 goto codeOK 122 } 123 } 124 l.PogoComp().LogError(errorInfo, "Haxe", 125 fmt.Errorf("hx.???() code is not a usable string constant: %s", args[argOff].String())) 126 return "" 127 codeOK: 128 tcode := strings.Trim(givenConst.Value.String(), `"`) // trim quotes 129 tcode = strings.Replace(tcode, "\\\"", "\"", -1) // replace backslash quote with quote 130 //println("DEBUG string=", tcode) 131 code += tcode 132 } else { 133 code += strings.Trim(l.IndirectValue(args[argOff], errorInfo), `"`) // trim quotes if it has any 134 } 135 if strings.HasPrefix(fnToCall, "CCall") || 136 strings.HasPrefix(fnToCall, "MMeth") || strings.HasPrefix(fnToCall, "NNew") { 137 argOff++ 138 if strings.HasPrefix(fnToCall, "MMeth") { 139 haxeType := l.tgoString(l.IndirectValue(args[argOff], errorInfo), errorInfo) 140 if len(haxeType) > 0 { 141 code = "cast(" + code + "," + haxeType + ")" 142 } 143 argOff++ 144 obj := l.IndirectValue(args[argOff], errorInfo) 145 code += "." + strings.Trim(obj, `"`) + "(" 146 argOff++ 147 } else { 148 code += "(" 149 } 150 textLen := l.IndirectValue(args[argOff], errorInfo) // see Const() for format 151 aLen, err := strconv.ParseUint(textLen, 0, 64) 152 if err != nil { 153 code += " ERROR Go ParseUint on number of arguments to hx.Meth() or hx.Call() - " + err.Error() + "! " 154 } else { 155 if aLen == 0 { 156 usesArgs = false 157 } 158 for i := uint64(0); i < aLen; i++ { 159 if i > 0 { 160 code += "," 161 } 162 //code += fmt.Sprintf("Force.toHaxeParam(_a.itemAddr(%d).load())", i) 163 code += fmt.Sprintf("Force.toHaxeParam(_a.param(%d))", i) 164 } 165 } 166 code += ");" 167 } 168 if strings.HasPrefix(fnToCall, "GGet") { 169 code += ";" 170 usesArgs = false 171 } 172 if strings.HasPrefix(fnToCall, "SSet") { 173 argOff++ 174 code = code + "=" + l.IndirectValue(args[argOff], errorInfo) + ";" 175 usesArgs = false 176 } 177 if strings.HasPrefix(fnToCall, "FFget") { 178 argOff++ 179 if l.IndirectValue(args[argOff], errorInfo) != `""` { 180 code = "cast(" + code + "," + l.tgoString(l.IndirectValue(args[argOff], errorInfo), errorInfo) + ")" 181 } 182 code += "." + l.tgoString(l.IndirectValue(args[argOff+1], errorInfo), errorInfo) + "; " 183 usesArgs = false 184 } 185 if strings.HasPrefix(fnToCall, "FFset") { 186 argOff++ 187 if l.IndirectValue(args[argOff], errorInfo) != `""` { 188 code = "cast(" + code + "," + l.tgoString(l.IndirectValue(args[argOff], errorInfo), errorInfo) + ")" 189 } 190 code += "." + l.tgoString(l.IndirectValue(args[argOff+1], errorInfo), errorInfo) + 191 "=Force.toHaxeParam(" + l.IndirectValue(args[argOff+2], errorInfo) + "); " 192 usesArgs = false 193 } 194 195 ret := "{" 196 if usesArgs { 197 ret += "var _a=" + l.IndirectValue(args[argOff+1], errorInfo) + "; " 198 } 199 return ret + wrapStart + code + wrapEnd + " }" 200 } 201 202 func (l langType) tgoString(s, errorInfo string) string { 203 bits := strings.Split(s, `"`) 204 if len(bits) < 2 { 205 l.PogoComp().LogError(errorInfo, "Haxe", fmt.Errorf("hx.() argument is not a usable string constant")) 206 return "" 207 } 208 return bits[1] 209 }