Files
2026-09-03 10:44:30 +02:00

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
}