README: document nit_env.sh
[nit.git] / lib / jvm.nit
index 4337d9e..62cebe1 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Manipulates the Java Virtual Machine
+# Java Virtual Machine services
 #
 # See: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html
 module jvm is
-       c_compiler_option("-I $(JAVA_HOME)/include/")
-       c_linker_option("-L $(JNI_LIB_PATH) -ljvm")
+       cflags "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
+       ldflags "-L $(JNI_LIB_PATH) -ljvm"
 end
 
 in "C Header" `{
@@ -30,7 +30,8 @@ in "C Header" `{
 # Utility to select options to create the VM using `create_jvm`
 #
 # Usage example:
-# ~~~~
+#
+# ~~~~nitish
 # var builder = new JavaVMBuilder
 # builder.options.add "-Djava.class.path=."
 # var jvm = builder.create_jvm
@@ -39,9 +40,15 @@ in "C Header" `{
 class JavaVMBuilder
        super JniEnvRef
 
-       var version: Int = "00010002".to_hex
+       # Version code of the JVM requested by `create_jvm`
+       #
+       # Default at 0x00010002
+       var version = 0x00010002 is writable
+
+       # Additional option strings
        var options = new Array[String]
 
+       # Create the JVM and return it on success
        fun create_jvm: nullable JavaVM
        do
                var args = new JavaVMInitArgs
@@ -68,7 +75,7 @@ class JavaVMBuilder
        end
 end
 
-extern class JavaVMInitArgs `{ JavaVMInitArgs* `}
+private extern class JavaVMInitArgs `{ JavaVMInitArgs* `}
        new `{ return (JavaVMInitArgs*)malloc(sizeof(JavaVMInitArgs)); `}
 
        # Set the defaut config for a VM
@@ -77,40 +84,40 @@ extern class JavaVMInitArgs `{ JavaVMInitArgs* `}
        # Unavailable on Android, where you cannot instanciate a new JVM.
        fun set_default `{
        #ifndef ANDROID
-               JNI_GetDefaultJavaVMInitArgs(recv);
+               JNI_GetDefaultJavaVMInitArgs(self);
        #endif
        `}
 
-       fun version: Int `{ return recv->version; `}
-       fun version=(v: Int) `{ recv->version = v; `}
+       fun version: Int `{ return self->version; `}
+       fun version=(v: Int) `{ self->version = v; `}
 
-       fun options: JavaVMOptionArray `{ return recv->options; `}
-       fun options=(v: JavaVMOptionArray) `{ recv->options = v; `}
+       fun options: JavaVMOptionArray `{ return self->options; `}
+       fun options=(v: JavaVMOptionArray) `{ self->options = v; `}
 
-       fun n_options: Int `{ return recv->nOptions; `}
-       fun n_options=(v: Int) `{ recv->nOptions = v; `}
+       fun n_options: Int `{ return self->nOptions; `}
+       fun n_options=(v: Int) `{ self->nOptions = v; `}
 end
 
-extern class JavaVMOption `{ JavaVMOption* `}
+private extern class JavaVMOption `{ JavaVMOption* `}
        fun string: String import NativeString.to_s `{
-               return NativeString_to_s((char*)recv->optionString);
+               return NativeString_to_s((char*)self->optionString);
        `}
        fun string=(v: String) import String.to_cstring `{
-               recv->optionString = String_to_cstring(v);
+               self->optionString = String_to_cstring(v);
        `}
 
        fun extra_info: String import NativeString.to_s `{
-               return NativeString_to_s((char*)recv->extraInfo);
+               return NativeString_to_s((char*)self->extraInfo);
        `}
        fun extra_info=(v: String) import String.to_cstring `{
-               recv->extraInfo = String_to_cstring(v);
+               self->extraInfo = String_to_cstring(v);
        `}
 end
 
-extern class JavaVMOptionArray `{ JavaVMOption* `}
+private extern class JavaVMOptionArray `{ JavaVMOption* `}
        new(size: Int) `{ return (JavaVMOption*)malloc(sizeof(JavaVMOption)*size); `}
 
-       fun [](i: Int): JavaVMOption `{ return recv+i; `}
+       fun [](i: Int): JavaVMOption `{ return self+i; `}
 end
 
 # Represents a jni JavaVM
@@ -118,7 +125,8 @@ extern class JavaVM `{JavaVM *`}
        # Create the JVM, returns its handle and store the a pointer to JniEnv in `env_ref`
        #
        # Unavailable on Android, where you cannot instanciate a new JVM.
-       new(args: JavaVMInitArgs, env_ref: JniEnvRef) import jni_error, JniEnvRef.jni_env=, JniEnv.as nullable `{
+       private new(args: JavaVMInitArgs, env_ref: JniEnvRef)
+       import jni_error, JniEnvRef.jni_env=, JniEnv.as nullable `{
 
        #ifdef ANDROID
                JavaVM_jni_error(NULL, "JVM creation not supported on Android", 0);
@@ -141,19 +149,19 @@ extern class JavaVM `{JavaVM *`}
                }
        `}
 
-       fun jni_error(msg: NativeString, v: Int)
+       private fun jni_error(msg: NativeString, v: Int)
        do
                print "JNI Error: {msg} ({v})"
                abort
        end
 
        fun destroy `{
-               (*recv)->DestroyJavaVM(recv);
+               (*self)->DestroyJavaVM(self);
        `}
 
        fun env: JniEnv import jni_error `{
                JNIEnv *env;
-               int res = (*recv)->GetEnv(recv, (void **)&env, JNI_VERSION_1_6);
+               int res = (*self)->GetEnv(self, (void **)&env, JNI_VERSION_1_6);
                if (res != JNI_OK) {
                        JavaVM_jni_error(NULL, "Could not get JNIEnv from Java VM", res);
                        return NULL;
@@ -161,99 +169,105 @@ extern class JavaVM `{JavaVM *`}
                return env;
        `}
 
-       fun attach_current_thread: JniEnv `{
+       fun attach_current_thread: JniEnv import jni_error `{
                JNIEnv *env;
        #ifdef ANDROID
                // the signature is different (better actually) on Android
-               int res = (*recv)->AttachCurrentThread(recv, &env, NULL);
+               int res = (*self)->AttachCurrentThread(self, &env, NULL);
        #else
-               int res = (*recv)->AttachCurrentThread(recv, (void**)&env, NULL);
+               int res = (*self)->AttachCurrentThread(self, (void**)&env, NULL);
        #endif
                if (res != JNI_OK) {
                        JavaVM_jni_error(NULL, "Could not attach current thread to Java VM", res);
                        return NULL;
                }
+               return env;
        `}
 end
 
 # Represents a jni JNIEnv, which is a thread in a JavaVM
 extern class JniEnv `{JNIEnv *`}
-       
+
        # Get a class object from its fully-qualified name or null if the class cannot be found
        fun find_class(class_name : String): JClass import String.to_cstring `{
-               return (*recv)->FindClass(recv,String_to_cstring(class_name));
+               return (*self)->FindClass(self,String_to_cstring(class_name));
        `}
-       
+
        # Return the method id for an instance of a class or interface
        # The method is determined by its name and signature
        # To obtain the method ID of a constructor, supply "<init>" as the method name and "void(V)" as the return type
        fun get_method_id(clazz : JClass, name : String, signature : String): JMethodID import String.to_cstring `{
-               return (*recv)->GetMethodID(recv, clazz, String_to_cstring(name), String_to_cstring(signature));
+               return (*self)->GetMethodID(self, clazz, String_to_cstring(name), String_to_cstring(signature));
        `}
-       
+
        # Construct a new Java object from the `clazz`, using the constructor ̀ method_id`
        fun new_object(clazz: JClass, method_id: JMethodID): JavaObject `{
-               return (*recv)->NewObject(recv, clazz, method_id);
+               return (*self)->NewObject(self, clazz, method_id);
        `}
-       
+
        # Return the JClass of `obj`
        fun get_object_class(obj: JavaObject): JClass `{
-               return (*recv)->GetObjectClass(recv, obj);
+               return (*self)->GetObjectClass(self, obj);
        `}
 
-       # Registers native methods with the class specified by the `clazz` argument     
+       # Registers native methods with the class specified by the `clazz` argument
        fun register_natives(clazz: JClass, method: JNINativeMethod, n_method : Int): Int `{
-               return (*recv)->RegisterNatives(recv, clazz, method, n_method);
+               return (*self)->RegisterNatives(self, clazz, method, n_method);
        `}
 
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments
        fun call_void_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]) import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               (*recv)->CallVoidMethodA(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               (*self)->CallVoidMethodA(self, obj, method_id, args_tab);
                free(args_tab);
        `}
-       
+
        # Call a method on `obj` designed by `method_id` with an array `args` of argument returning a JavaObject
        fun call_object_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): JavaObject import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               (*recv)->CallObjectMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jobject res = (*self)->CallObjectMethod(self, obj, method_id, args_tab);
                free(args_tab);
+               return res;
        `}
-       
+
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments returning a Bool
        fun call_boolean_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): Bool import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               return (*recv)->CallBooleanMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jboolean res = (*self)->CallBooleanMethod(self, obj, method_id, args_tab);
                free(args_tab);
+               return res;
        `}
 
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments returning a Char
        fun call_char_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): Char import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               return (*recv)->CallCharMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jchar res = (*self)->CallCharMethod(self, obj, method_id, args_tab);
                free(args_tab);
+               return res;
        `}
 
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments returning an Int
        fun call_int_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): Int import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               return (*recv)->CallIntMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jint res = (*self)->CallIntMethod(self, obj, method_id, args_tab);
                free(args_tab);
+               return res;
        `}
-       
+
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments returning a Float
        fun call_float_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): Float import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               return (*recv)->CallFloatMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jfloat res = (*self)->CallFloatMethod(self, obj, method_id, args_tab);
                free(args_tab);
+               return res;
        `}
 
        # Call a method on `obj` designed by `method_id` with an array `args` of arguments returning a NativeString
        fun call_string_method(obj: JavaObject, method_id: JMethodID, args: nullable Array[nullable Object]): NativeString import convert_args_to_jni `{
-               jvalue * args_tab = JniEnv_convert_args_to_jni(recv, args);
-               jobject jobj = (*recv)->CallObjectMethod(recv, obj, method_id, args_tab);
+               jvalue * args_tab = JniEnv_convert_args_to_jni(self, args);
+               jobject jobj = (*self)->CallObjectMethod(self, obj, method_id, args_tab);
                free(args_tab);
-               return (char*)(*recv)->GetStringUTFChars(recv, (jstring)jobj, NULL);
+               return (char*)(*self)->GetStringUTFChars(self, (jstring)jobj, NULL);
        `}
 
        private fun convert_args_to_jni(args: nullable Array[nullable Object]): Pointer import Array[nullable Object].as not nullable, Array[nullable Object].[], Array[nullable Object].length, nullable Object.as(Int), nullable Object.as(Char), nullable Object.as(Bool), nullable Object.as(Float), nullable Object.as(JavaObject), nullable Object.as(String), String.to_cstring, String.length `{
@@ -284,7 +298,7 @@ extern class JniEnv `{JNIEnv *`}
                        } else if(nullable_Object_is_a_String(nullable_obj)){
                                String val = nullable_Object_as_String(nullable_obj);
                                char* c = String_to_cstring(val);
-                               jstring js = (*recv)->NewStringUTF(recv, c);
+                               jstring js = (*self)->NewStringUTF(self, c);
                                c_array[i].l = js;
                        } else {
                                fprintf(stderr, "NOT YET SUPPORTED: nit objects are not supported\n");
@@ -296,99 +310,99 @@ extern class JniEnv `{JNIEnv *`}
 
        # Returns the field ID for an instance field of a class. The field is specified by its name and signature
        fun get_field_id(clazz: JClass, name: String, sign: String): JFieldID import String.to_cstring `{
-               return (*recv)->GetFieldID(recv, clazz, String_to_cstring(name), String_to_cstring(sign));
+               return (*self)->GetFieldID(self, clazz, String_to_cstring(name), String_to_cstring(sign));
        `}
-       
+
        # returns the value of an instance (nonstatic) field of an object. The field to access is specified by a field ID obtained by calling get_field_id()
        fun get_object_field(obj: JavaObject, fieldID: JFieldID): JavaObject `{
-               return (*recv)->GetObjectField(recv, obj, fieldID);
+               return (*self)->GetObjectField(self, obj, fieldID);
        `}
 
        fun get_boolean_field(obj: JavaObject, fieldID: JFieldID): Bool `{
-               return (*recv)->GetBooleanField(recv, obj, fieldID);
+               return (*self)->GetBooleanField(self, obj, fieldID);
        `}
-       
+
        fun get_char_field(obj: JavaObject, fieldID: JFieldID): Char `{
-               return (*recv)->GetCharField(recv, obj, fieldID);
+               return (*self)->GetCharField(self, obj, fieldID);
        `}
 
        fun get_int_field(obj: JavaObject, fieldID: JFieldID): Int `{
-               return (*recv)->GetIntField(recv, obj, fieldID);
+               return (*self)->GetIntField(self, obj, fieldID);
        `}
 
        fun get_float_field(obj: JavaObject, fieldID: JFieldID): Float `{
-               return (*recv)->GetFloatField(recv, obj, fieldID);
+               return (*self)->GetFloatField(self, obj, fieldID);
        `}
 
        fun set_object_field(obj: JavaObject, fieldID: JFieldID, value: JavaObject) `{
-               (*recv)->SetObjectField(recv, obj, fieldID, value);
+               (*self)->SetObjectField(self, obj, fieldID, value);
        `}
 
        fun set_boolean_field(obj: JavaObject, fieldID: JFieldID, value: Bool) `{
-               (*recv)->SetBooleanField(recv, obj, fieldID, value);
+               (*self)->SetBooleanField(self, obj, fieldID, value);
        `}
 
        fun set_char_field(obj: JavaObject, fieldID: JFieldID, value: Char) `{
-               (*recv)->SetCharField(recv, obj, fieldID, value);
+               (*self)->SetCharField(self, obj, fieldID, value);
        `}
 
        fun set_int_field(obj: JavaObject, fieldID: JFieldID, value: Int) `{
-               (*recv)->SetIntField(recv, obj, fieldID, value);
-       `}              
+               (*self)->SetIntField(self, obj, fieldID, value);
+       `}
 
        fun set_float_field(obj: JavaObject, fieldID: JFieldID, value: Float) `{
-               (*recv)->SetFloatField(recv, obj, fieldID, value);
+               (*self)->SetFloatField(self, obj, fieldID, value);
        `}
-       
+
        # Check for pending exception without creating a local reference to the exception object
        fun exception_check: Bool `{
-               return (*recv)->ExceptionCheck(recv);
+               return (*self)->ExceptionCheck(self);
        `}
 
        # Construct an exception object from the specified class with the message specified by `message` and causes that exception to be thrown
        fun throw_new(clazz: JClass, message: String): Int import String.to_cstring `{
-               return (*recv)->ThrowNew(recv, clazz, String_to_cstring(message));
+               return (*self)->ThrowNew(self, clazz, String_to_cstring(message));
        `}
 
        # return the exception if there is one in the process of being thrown, or NULL if no exception is currently being thrown
        fun exception_occurred: JavaObject `{
-               return (*recv)->ExceptionOccurred(recv);
+               return (*self)->ExceptionOccurred(self);
        `}
 
        # prints an exception and backtrace to error channel
        fun exception_describe `{
-               return (*recv)->ExceptionDescribe(recv);
+               return (*self)->ExceptionDescribe(self);
        `}
 
        # clears any exception currently being thrown, has no effect if there is no exception
        fun exception_clear `{
-               return (*recv)->ExceptionClear(recv);
+               return (*self)->ExceptionClear(self);
        `}
-       
+
        # Raise a fatal error
        fun fatal_error(msg: String) import String.to_cstring `{
-               (*recv)->FatalError(recv, String_to_cstring(msg));
+               (*self)->FatalError(self, String_to_cstring(msg));
        `}
 
        # Transform a NIT String into a JavaObject
        fun string_to_jobject(string: String): JavaObject `{
-               return (*recv)->NewStringUTF(recv, String_to_cstring(string));
+               return (*self)->NewStringUTF(self, String_to_cstring(string));
        `}
 
        # Pushes a local reference frame on the JNI stack
        fun push_local_frame(capacity: Int): Bool `{
-               return (*recv)->PushLocalFrame(recv, capacity);
+               return (*self)->PushLocalFrame(self, capacity);
        `}
 
        # Pops the current local reference frame on the JNI stack
        #
        # Similiar to `JavaObject::pop_from_local_frame` which returns a value.
        fun pop_local_frame `{
-               (*recv)->PopLocalFrame(recv, NULL);
+               (*self)->PopLocalFrame(self, NULL);
        `}
 end
 
-# used to initialize a JavaVM 
+# used to initialize a JavaVM
 class JniEnvRef
        var jni_env: nullable JniEnv = null
 end
@@ -408,19 +422,19 @@ end
 # Represents a jni JNINNativeMethod
 extern class JNINativeMethod `{ JNINativeMethod* `}
        fun name: String import NativeString.to_s `{
-               return NativeString_to_s((void*)recv->name);
+               return NativeString_to_s((void*)self->name);
        `}
 
        fun name=(name: String) import String.to_cstring `{
-               recv->name = String_to_cstring(name);
+               self->name = String_to_cstring(name);
        `}
 
        fun signature: String import NativeString.to_s `{
-               return NativeString_to_s((void*)recv->signature);
+               return NativeString_to_s((void*)self->signature);
        `}
 
        fun signature=(signature: String) import String.to_cstring `{
-               recv->signature = String_to_cstring(signature);
+               self->signature = String_to_cstring(signature);
        `}
 end
 
@@ -432,50 +446,50 @@ end
 extern class JValue `{jvalue`}
 
        fun set_boolean(b: Bool) `{
-               recv.z = b;
+               self.z = b;
        `}
 
        fun get_boolean:Bool `{
-               return recv.z;
+               return self.z;
        `}
-       
+
        fun set_char(c: Char)`{
-               recv.c = c;
+               self.c = c;
        `}
-       
+
        fun get_char: Char `{
-               return recv.c;
+               return self.c;
        `}
 
        fun set_int(i: Int) `{
-               recv.i = i;
+               self.i = i;
        `}
 
        fun get_int: Int `{
-               return recv.i;
+               return self.i;
        `}
 
        fun set_float(f: Float) `{
-               recv.f = f;
+               self.f = f;
        `}
 
        fun get_float: Float `{
-               return recv.f;
+               return self.f;
        `}
 
        fun set_jobject(obj: JavaObject) `{
-               recv.l = obj;
+               self.l = obj;
        `}
 
        fun get_jobject: JavaObject `{
-               return recv.l;
+               return self.l;
        `}
 end
 
 redef class Int
        redef fun to_jvalue(env): JValue `{
                jvalue value;
-               value.i = recv;
+               value.i = self;
                return value;
        `}
 end
@@ -483,7 +497,7 @@ end
 redef class Float
        redef fun to_jvalue(env): JValue `{
                jvalue value;
-               value.f = recv;
+               value.f = self;
                return value;
        `}
 end
@@ -491,7 +505,7 @@ end
 redef class Bool
        redef fun to_jvalue(env): JValue `{
                jvalue value;
-               value.z = recv;
+               value.z = self;
                return value;
        `}
 end
@@ -499,7 +513,7 @@ end
 redef class NativeString
        redef fun to_jvalue(env)`{
                jvalue value;
-               value.l = (*env)->NewStringUTF(env, recv);
+               value.l = (*env)->NewStringUTF(env, self);
                return value;
        `}
 end