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 || int(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 || int(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 && int(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_iface
106 func moxie_register_iface(pkgPathPtr unsafe.Pointer, pkgPathLen int32, namePtr unsafe.Pointer, nameLen int32, methodsPtr unsafe.Pointer, methodsLen int32) {
107 runtime.InitCShared()
108 ensureImportRegistry()
109 pkgPath := string(unsafe.Slice((*byte)(pkgPathPtr), pkgPathLen))
110 name := string(unsafe.Slice((*byte)(namePtr), nameLen))
111 methodsDesc := string(unsafe.Slice((*byte)(methodsPtr), methodsLen))
112 pkg := importRegistry[pkgPath]
113 if pkg == nil {
114 return
115 }
116 var methods []*IfaceMethod
117 if methodsDesc != "" {
118 parts := splitSemicolon(methodsDesc)
119 for _, p := range parts {
120 eqIdx := -1
121 for i := 0; i < len(p); i++ {
122 if p[i] == '=' {
123 eqIdx = i
124 break
125 }
126 }
127 if eqIdx < 0 {
128 continue
129 }
130 mname := p[:eqIdx]
131 msig := parseSignatureDesc(p[eqIdx+1:])
132 methods = append(methods, NewTCIfaceMethod(mname, msig))
133 }
134 }
135 iface := NewTCInterface(methods, nil)
136 iface.Complete()
137 tn := NewTypeName(pkg, name, iface)
138 pkg.Scope().Insert(tn)
139 }
140
141 func splitSemicolon(s string) []string {
142 var parts []string
143 start := 0
144 for i := 0; i < len(s); i++ {
145 if s[i] == ';' {
146 parts = append(parts, s[start:i])
147 start = i + 1
148 }
149 }
150 parts = append(parts, s[start:])
151 return parts
152 }
153
154 //export moxie_clear_imports
155 func moxie_clear_imports() {
156 runtime.InitCShared()
157 ensureImportRegistry()
158 importRegistry = map[string]*TCPackage{}
159 }
160
161 func parseTypeDesc(desc string) Type {
162 switch desc {
163 case "bool":
164 return Typ[Bool]
165 case "int8":
166 return Typ[Int8]
167 case "int16":
168 return Typ[Int16]
169 case "int32", "int":
170 return Typ[Int32]
171 case "int64":
172 return Typ[Int64]
173 case "uint8", "byte":
174 return Typ[Uint8]
175 case "uint16":
176 return Typ[Uint16]
177 case "uint32", "uint":
178 return Typ[Uint32]
179 case "uint64":
180 return Typ[Uint64]
181 case "float32":
182 return Typ[Float32]
183 case "float64":
184 return Typ[Float64]
185 case "string":
186 return Typ[TCString]
187 case "ptr":
188 return Typ[UnsafePointer]
189 case "error":
190 errorSig := NewSignature(nil, nil, NewTuple(NewTCVar(nil, "", Typ[TCString])), false)
191 errorIface := NewTCInterface([]*IfaceMethod{NewTCIfaceMethod("Error", errorSig)}, nil)
192 errorIface.Complete()
193 return errorIface
194 case "interface{}":
195 emptyIface := NewTCInterface(nil, nil)
196 emptyIface.Complete()
197 return emptyIface
198 }
199 if len(desc) > 2 && desc[0] == '[' && desc[1] == ']' {
200 elem := parseTypeDesc(desc[2:])
201 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
202 return Typ[TCString]
203 }
204 return NewSlice(elem)
205 }
206 if len(desc) > 1 && desc[0] == '*' {
207 return NewPointer(parseTypeDesc(desc[1:]))
208 }
209 return Typ[Int32]
210 }
211
212 func parseSignatureDesc(desc string) *Signature {
213 // format: "param1,param2->result1,result2" or "param1,param2" (void) or "->result" (no params)
214 arrow := -1
215 for i := 0; i < len(desc)-1; i++ {
216 if desc[i] == '-' && desc[i+1] == '>' {
217 arrow = i
218 break
219 }
220 }
221 var paramStr, resultStr string
222 if arrow >= 0 {
223 paramStr = desc[:arrow]
224 resultStr = desc[arrow+2:]
225 } else {
226 paramStr = desc
227 }
228 var params []*TCVar
229 if paramStr != "" {
230 parts := splitComma(paramStr)
231 for _, p := range parts {
232 params = append(params, NewTCVar(nil, "", parseTypeDesc(p)))
233 }
234 }
235 var results []*TCVar
236 if resultStr != "" {
237 parts := splitComma(resultStr)
238 for _, r := range parts {
239 results = append(results, NewTCVar(nil, "", parseTypeDesc(r)))
240 }
241 }
242 var pTuple, rTuple *Tuple
243 if len(params) > 0 {
244 pTuple = NewTuple(params...)
245 }
246 if len(results) > 0 {
247 rTuple = NewTuple(results...)
248 }
249 return NewSignature(nil, pTuple, rTuple, false)
250 }
251
252 func splitComma(s string) []string {
253 var parts []string
254 start := 0
255 for i := 0; i < len(s); i++ {
256 if s[i] == ',' {
257 parts = append(parts, s[start:i])
258 start = i + 1
259 }
260 }
261 parts = append(parts, s[start:])
262 return parts
263 }
264
265 func main() {}
266