90 lines
2.6 KiB
Odin
90 lines
2.6 KiB
Odin
package jnigen
|
|
|
|
import "core:fmt"
|
|
import "core:strings"
|
|
|
|
Prim :: struct {
|
|
odin: string,
|
|
sig: string,
|
|
call: string,
|
|
jval: string,
|
|
jcast: string,
|
|
}
|
|
|
|
// Odin's u16 stands in for Java's char: both are unsigned 16-bit.
|
|
prims := []Prim{
|
|
{"bool", "Z", "boolean", "z", "android.jboolean"},
|
|
{"i8", "B", "byte", "b", "android.jbyte"},
|
|
{"u16", "C", "char", "c", "android.jchar"},
|
|
{"i16", "S", "short", "s", "android.jshort"},
|
|
{"i32", "I", "int", "i", "android.jint"},
|
|
{"i64", "J", "long", "j", "android.jlong"},
|
|
{"f32", "F", "float", "f", "android.jfloat"},
|
|
{"f64", "D", "double", "d", "android.jdouble"},
|
|
}
|
|
|
|
resolve_type :: proc(g: ^Gen, odin: string, line: int) -> (Type_Ref, bool) {
|
|
src := strings.trim_space(odin)
|
|
if src == "" {
|
|
return Type_Ref{sig = "V", of = .Void, call = "void"}, true
|
|
}
|
|
|
|
for p in prims {
|
|
if src == p.odin {
|
|
return Type_Ref{
|
|
odin = src, sig = p.sig, of = .Prim,
|
|
call = p.call, jval = p.jval, jcast = p.jcast,
|
|
}, true
|
|
}
|
|
}
|
|
|
|
if src == "string" || src == "cstring" {
|
|
return Type_Ref{
|
|
odin = src, sig = "Ljava/lang/String;", of = .String,
|
|
call = "object", jval = "l",
|
|
}, true
|
|
}
|
|
|
|
if strings.has_prefix(src, "[]") {
|
|
elem := strings.trim_space(src[2:])
|
|
et, ok := resolve_type(g, elem, line)
|
|
if !ok {
|
|
return {}, false
|
|
}
|
|
if et.of == .Array {
|
|
errorf(g, line, "nested slice '%s' is not supported; declare it as a jobject instead", src)
|
|
return {}, false
|
|
}
|
|
return Type_Ref{
|
|
odin = src, sig = fmt.aprintf("[%s", et.sig), of = .Array,
|
|
call = "object", jval = "l", elem = elem,
|
|
}, true
|
|
}
|
|
|
|
// A raw jobject is untyped on the Java side, so it signs as Object.
|
|
if src == "android.jobject" || src == "jobject" {
|
|
return Type_Ref{
|
|
odin = src, sig = "Ljava/lang/Object;", of = .Object,
|
|
call = "object", jval = "l",
|
|
}, true
|
|
}
|
|
|
|
if cls, ok := g.classes[src]; ok {
|
|
return Type_Ref{
|
|
odin = src, sig = fmt.aprintf("L%s;", cls), of = .Object,
|
|
call = "object", jval = "l",
|
|
}, true
|
|
}
|
|
|
|
errorf(g, line, "unknown type '%s'; register it with @(java_class=\"...\") or use a primitive", src)
|
|
return {}, false
|
|
}
|
|
|
|
// Whether a returned value allocates and so needs an allocator parameter.
|
|
allocates :: proc(t: Type_Ref) -> bool {
|
|
if t.of == .String {
|
|
return true
|
|
}
|
|
return t.of == .Array
|
|
}
|