compile_exports.mx raw
1 package main
2
3 import (
4 "runtime"
5 "unsafe"
6 )
7
8 var irResults []string
9 var importRegistry map[string]*TCPackage
10
11 func ensureImportRegistry() {
12 if importRegistry == nil {
13 importRegistry = map[string]*TCPackage{}
14 }
15 }
16
17 //export moxie_compile_to_ir
18 func moxie_compile_to_ir(srcPtr unsafe.Pointer, srcLen int32, namePtr unsafe.Pointer, nameLen int32, triplePtr unsafe.Pointer, tripleLen int32) int32 {
19 runtime.InitCShared()
20 src := unsafe.Slice((*byte)(srcPtr), srcLen)
21 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
22 triple := string(unsafe.Slice((*byte)(triplePtr), tripleLen))
23
24 ir := CompileToIR(src, name, triple)
25
26 idx := int32(len(irResults))
27 irResults = append(irResults, ir)
28 return idx
29 }
30
31 //export moxie_compile_ir_len
32 func moxie_compile_ir_len(h int32) int32 {
33 runtime.InitCShared()
34 if h < 0 || int32(h) >= len(irResults) {
35 return 0
36 }
37 return int32(len(irResults[h]))
38 }
39
40 //export moxie_compile_ir_copy
41 func moxie_compile_ir_copy(h int32, dst unsafe.Pointer, cap int32) int32 {
42 runtime.InitCShared()
43 if h < 0 || int32(h) >= len(irResults) {
44 return 0
45 }
46 ir := irResults[h]
47 n := int32(len(ir))
48 if n > cap {
49 n = cap
50 }
51 if n > 0 {
52 buf := unsafe.Slice((*byte)(dst), n)
53 copy(buf, ir[:n])
54 }
55 return n
56 }
57
58 //export moxie_compile_ir_free
59 func moxie_compile_ir_free(h int32) {
60 runtime.InitCShared()
61 if h >= 0 && int32(h) < len(irResults) {
62 irResults[h] = ""
63 }
64 }
65
66 //export moxie_register_package
67 func moxie_register_package(pathPtr unsafe.Pointer, pathLen int32, namePtr unsafe.Pointer, nameLen int32) {
68 runtime.InitCShared()
69 ensureImportRegistry()
70 path := string(unsafe.Slice((*byte)(pathPtr), pathLen))
71 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
72 importRegistry[path] = NewTCPackage(path, name)
73 }
74
75 //export moxie_register_func
76 func moxie_register_func(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, sigPtr unsafe.Pointer, sigLen int32) {
77 runtime.InitCShared()
78 ensureImportRegistry()
79 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
80 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
81 sigDesc := string(unsafe.Slice((*byte)(sigPtr), sigLen))
82 pkg := importRegistry[pkgPath]
83 if pkg == nil {
84 return
85 }
86 sig := parseSignatureDesc(sigDesc)
87 pkg.Scope().Insert(NewTCFunc(pkg, name, sig))
88 }
89
90 //export moxie_register_var
91 func moxie_register_var(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, typDescPtr unsafe.Pointer, typDescLen int32) {
92 runtime.InitCShared()
93 ensureImportRegistry()
94 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
95 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
96 typDesc := string(unsafe.Slice((*byte)(typDescPtr), typDescLen))
97 pkg := importRegistry[pkgPath]
98 if pkg == nil {
99 return
100 }
101 typ := parseTypeDesc(typDesc)
102 pkg.Scope().Insert(NewTCVar(pkg, name, typ))
103 }
104
105 //export moxie_register_const
106 func moxie_register_const(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, typDescPtr unsafe.Pointer, typDescLen int32, val int64) {
107 runtime.InitCShared()
108 ensureImportRegistry()
109 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
110 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
111 typDesc := string(unsafe.Slice((*byte)(typDescPtr), typDescLen))
112 pkg := importRegistry[pkgPath]
113 if pkg == nil {
114 return
115 }
116 typ := parseTypeDesc(typDesc)
117 pkg.Scope().Insert(NewTCConst(pkg, name, typ, constInt{val}))
118 }
119
120 //export moxie_register_const_string
121 func moxie_register_const_string(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, valPtr unsafe.Pointer, valLen int32) {
122 runtime.InitCShared()
123 ensureImportRegistry()
124 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
125 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
126 val := string(unsafe.Slice((*byte)(valPtr), valLen))
127 pkg := importRegistry[pkgPath]
128 if pkg == nil {
129 return
130 }
131 pkg.Scope().Insert(NewTCConst(pkg, name, Typ[UntypedString], constStr{val}))
132 }
133
134 //export moxie_register_iface
135 func moxie_register_iface(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, methodsPtr unsafe.Pointer, methodsLen int32) {
136 runtime.InitCShared()
137 ensureImportRegistry()
138 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
139 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
140 methodsDesc := string(unsafe.Slice((*byte)(methodsPtr), methodsLen))
141 pkg := importRegistry[pkgPath]
142 if pkg == nil {
143 return
144 }
145 var methods []*IfaceMethod
146 if methodsDesc != "" {
147 parts := splitSemicolon(methodsDesc)
148 for _, p := range parts {
149 eqIdx := -1
150 for i := 0; i < len(p); i++ {
151 if p[i] == '=' {
152 eqIdx = i
153 break
154 }
155 }
156 if eqIdx < 0 {
157 continue
158 }
159 mname := p[:eqIdx]
160 msig := parseSignatureDesc(p[eqIdx+1:])
161 methods = append(methods, NewTCIfaceMethod(mname, msig))
162 }
163 }
164 iface := NewTCInterface(methods, nil)
165 iface.Complete()
166 tn := NewTypeName(pkg, name, iface)
167 pkg.Scope().Insert(tn)
168 }
169
170 //export moxie_register_type
171 func moxie_register_type(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, underlyingPtr unsafe.Pointer, underlyingLen int32) {
172 runtime.InitCShared()
173 ensureImportRegistry()
174 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
175 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
176 pkg := importRegistry[pkgPath]
177 if pkg == nil {
178 return
179 }
180 var underlying Type
181 if underlyingLen > 0 {
182 desc := string(unsafe.Slice((*byte)(underlyingPtr), underlyingLen))
183 underlying = parseTypeDesc(desc)
184 } else {
185 underlying = NewTCStruct(nil, nil)
186 }
187 tn := NewTypeName(pkg, name, nil)
188 NewNamed(tn, underlying)
189 pkg.Scope().Insert(tn)
190 }
191
192 //export moxie_register_method
193 func moxie_register_method(pkgPathPtr unsafe.Pointer, pkgPathLen int32, typeNamePtr unsafe.Pointer, typeNameLen int32, methodNamePtr unsafe.Pointer, methodNameLen int32, sigPtr unsafe.Pointer, sigLen int32, ptrRecv int32) {
194 runtime.InitCShared()
195 ensureImportRegistry()
196 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
197 typeName := string(unsafe.Slice((*byte)(typeNamePtr), typeNameLen))
198 methodName := string(unsafe.Slice((*byte)(methodNamePtr), methodNameLen))
199 sigDesc := string(unsafe.Slice((*byte)(sigPtr), sigLen))
200 pkg := importRegistry[pkgPath]
201 if pkg == nil {
202 return
203 }
204 obj := pkg.Scope().Lookup(typeName)
205 if obj == nil {
206 return
207 }
208 tn, ok := obj.(*TypeName)
209 if !ok {
210 return
211 }
212 named, ok := tn.typ.(*Named)
213 if !ok {
214 return
215 }
216 sig := parseSignatureDesc(sigDesc)
217 fn := NewTCFunc(pkg, methodName, sig)
218 if ptrRecv != 0 {
219 fn.hasPtrRecv = true
220 }
221 named.AddMethod(fn)
222 }
223
224 func splitSemicolon(s string) []string {
225 var parts []string
226 start := 0
227 for i := 0; i < len(s); i++ {
228 if s[i] == ';' {
229 parts = append(parts, s[start:i])
230 start = i + 1
231 }
232 }
233 parts = append(parts, s[start:])
234 return parts
235 }
236
237 //export moxie_clear_imports
238 func moxie_clear_imports() {
239 runtime.InitCShared()
240 ensureImportRegistry()
241 importRegistry = map[string]*TCPackage{}
242 }
243
244 func parseTypeDesc(desc string) Type {
245 switch desc {
246 case "bool":
247 return Typ[Bool]
248 case "int8":
249 return Typ[Int8]
250 case "int16":
251 return Typ[Int16]
252 case "int32", "int32":
253 return Typ[Int32]
254 case "int64":
255 return Typ[Int64]
256 case "uint8", "byte":
257 return Typ[Uint8]
258 case "uint16":
259 return Typ[Uint16]
260 case "uint32", "uint32":
261 return Typ[Uint32]
262 case "uint64":
263 return Typ[Uint64]
264 case "float32":
265 return Typ[Float32]
266 case "float64":
267 return Typ[Float64]
268 case "string":
269 return Typ[TCString]
270 case "ptr":
271 return Typ[UnsafePointer]
272 case "error":
273 errorSig := NewSignature(nil, nil, NewTuple(NewTCVar(nil, "", Typ[TCString])), false)
274 errorIface := NewTCInterface([]*IfaceMethod{NewTCIfaceMethod("Error", errorSig)}, nil)
275 errorIface.Complete()
276 return errorIface
277 case "interface{}":
278 emptyIface := NewTCInterface(nil, nil)
279 emptyIface.Complete()
280 return emptyIface
281 }
282 if len(desc) > 2 && desc[0] == '[' && desc[1] == ']' {
283 elem := parseTypeDesc(desc[2:])
284 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
285 return Typ[TCString]
286 }
287 return NewSlice(elem)
288 }
289 if len(desc) > 1 && desc[0] == '*' {
290 return NewPointer(parseTypeDesc(desc[1:]))
291 }
292 return Typ[Int32]
293 }
294
295 func parseSignatureDesc(desc string) *Signature {
296 // format: "param1,param2->result1,result2" or "param1,param2" (void) or "->result" (no params)
297 arrow := -1
298 for i := 0; i < len(desc)-1; i++ {
299 if desc[i] == '-' && desc[i+1] == '>' {
300 arrow = i
301 break
302 }
303 }
304 var paramStr, resultStr string
305 if arrow >= 0 {
306 paramStr = desc[:arrow]
307 resultStr = desc[arrow+2:]
308 } else {
309 paramStr = desc
310 }
311 var params []*TCVar
312 if paramStr != "" {
313 parts := splitComma(paramStr)
314 for _, p := range parts {
315 params = append(params, NewTCVar(nil, "", parseTypeDesc(p)))
316 }
317 }
318 var results []*TCVar
319 if resultStr != "" {
320 parts := splitComma(resultStr)
321 for _, r := range parts {
322 results = append(results, NewTCVar(nil, "", parseTypeDesc(r)))
323 }
324 }
325 var pTuple, rTuple *Tuple
326 if len(params) > 0 {
327 pTuple = NewTuple(params...)
328 }
329 if len(results) > 0 {
330 rTuple = NewTuple(results...)
331 }
332 return NewSignature(nil, pTuple, rTuple, false)
333 }
334
335 func splitComma(s string) []string {
336 var parts []string
337 start := 0
338 for i := 0; i < len(s); i++ {
339 if s[i] == ',' {
340 parts = append(parts, s[start:i])
341 start = i + 1
342 }
343 }
344 parts = append(parts, s[start:])
345 return parts
346 }
347
348