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