camlspotter avatar camlspotter committed e15d9ba Merge

merge

Comments (0)

Files changed (13)

 .*\.cm[a-z]+$
 .*~$
-\.(sp[io]t|annot|o|cm[a-z]+|orig|omc|lock|so|a|exe|byt)$
+\.(sp[io]t|annot|o|cm[a-z]+|orig|omc|lock|so|a|exe|byt|opt|run)$
 \.omakedb$
 ^auto\.(idl|ml|mli)
 ^.*\.idl
+To add things:
+--------------
+
+- Edit <*.idl.in> files. <*.idl> are created from <*.idl.in>.
+- If you create new <*.idl.in> files, add include lines of <*.idl> in auto.idl.in, and add entries to IDLS in OMakefile.
+
+*.idl.in
+--------
+
+In addition to the CamlIDL attributes, there are some additional attributes:
+
+[option] : Pointer value may be NULL. The corresponding ML type becomes _ option.
+
+[new] : For return type only. It returns a new reference. Without this attribute, objects references are considered borrowed.
+
+[stolen] : For argument only. The function ``steals'' reference of the argument.
+
+[internal] : For function name only. ML function is prefixed with ``_internal_''
+
+Currently these new attributes are implemented by pretty dirty perl hack. They may not be used in conjunction.
+
+
 
 .DEFAULT: opycaml.cma opycaml.cmxa
 
-MLMODULES= test 
-CMOS=$(addsuffix .cmo, $(MLMODULES)) 
-CMXS=$(addsuffix .cmx, $(MLMODULES)) 
+OCAML_LIBS += opycaml
 
-test.byt: $(CMOS) opycaml.cma libopycaml.a dllopycaml.so
-    $(OCamlC) -verbose -o $@ opycaml.cma $(CMOS)
+.DEFAULT: $(OCamlProgram test, test)
+.DEFAULT: $(OCamlProgram test_bug1, test_bug1)
 
-test.exe: $(CMXS) opycaml.cmxa libopycaml.a dllopycaml.so
-    $(OCamlOpt) -verbose -o $@ opycaml.cmxa $(CMXS)
-
-.DEFAULT: test.exe
+# 
+# PROGRAM=test
+# FILOCAML_LIBS+=opycaml.cma
+# 
+# MLMODULES= test 
+# CMOS=$(addsuffix .cmo, $(MLMODULES)) 
+# CMXS=$(addsuffix .cmx, $(MLMODULES)) 
+# CMXOS=$(addsuffix .o, $(MLMODULES)) 
+# 
+# test.byt: $(CMOS) opycaml.cma libopycaml.a dllopycaml.so
+#     $(OCamlC) -verbose -o $@ opycaml.cma $(CMOS)
+# 
+# test.exe: $(CMXS) $(CMXOS) opycaml.cmxa libopycaml.a dllopycaml.so
+#     $(OCamlOpt) -verbose -o $@ opycaml.cmxa $(CMXS)
+# 
+# .DEFAULT: test.exe
 	this function will not return 1, but exit the process, as long
 	as Py_InspectFlag is not set.
 
-	Bug: Py_Main never returns to OCaml at exit(_). Strange...
+	Bug: Py_Main never returns to OCaml at exit(_), while CTRL+D works fine.
     **)
 end = struct
   include Base
 
   external internal_init : unit -> unit = "opycaml_init"
   let initialize () =
-    Callback.register_exception "OPyCaml exception" (Error (none ()));
+    Callback.register_exception "OPyCaml exception" (Error (none (), none ()));
     internal_init ();
-    initialize ()
+    _internal_initialize ()
 
   let debug name o =
     let cnt = refcnt o in
 
   external reraise : unit -> 'a = "opycaml_error"
     (** reraise the current exception. 
-	Err.Occured() must be return Some. Otherwise Failwith is raised instead. *)
+	Err.Occured() must be return Some. Otherwise Failwith is
+    raised instead. *)
+
+  val normalizeException : unit -> (t * t * t) option
 end = struct
   include Err
     
   external reraise : unit -> 'a = "opycaml_error"
+
+  let normalizeException () =
+    match occurred () with
+    | None -> None
+    | Some _ -> Some (_internal_normalizeException ())
 end
 
 module Int : sig
   include Int
 
   let asLong t =
-    let res = asLong t in
+    let res = _internal_asLong t in
     if res <> -1 then res
     else match Err.occurred () with
     | None -> -1
     opycaml_exc = caml_named_value("OPyCaml exception");
 }
 
-inline void opycaml_raise_error(value v)
+inline void opycaml_raise_error(value v, value detail)
 { 
-    caml_raise_with_arg(*opycaml_exc, v); 
+    value vs[2] = { v, detail };
+    caml_raise_with_args(*opycaml_exc, 2, vs); 
 }
 
 // custom value
 {
     value err;
     PyObject *exn = PyErr_Occurred(); // It's borrowed. Increment its refcnt!
+    PyObject *ptype, *pvalue, *ptraceback;
     if( !exn ){ caml_failwith("PyErr_Occurred returned NULL!"); }
     err = Val_PyObject(exn, 1); // borrowed: need to incr
-    PyErr_Print();
+    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+    value caml_value = Val_PyObject(pvalue, 1); // incr
     PyErr_Clear();
-    opycaml_raise_error(err);
+    opycaml_raise_error(err, caml_value);
 }
 
 value Val_PyObject_opt( PyObject *obj, int incr ) {
 type py_ssize_t = int
 type size_t = int
 
-exception Error of t
+exception Error of t (* type *) * t (* detail value *)
 
+
 	    if( /^\s*\/\// ){ next; }
 	    if( /(Py[A-Za-z_0-9]+)\(/ ){
 		$func_name = $1;
+		if( /\[internal\]/ ){
+		    $internal{$func_name} = 1;
+		}
 		while(<IN>){
 		    if( /^\/\/\s*/ ){
 			$_ = $';
 	    $fname =~ s/py/Py/;
 	    $comment = $comment{$fname};
             $comment =~ s/\n/\n      /g;
+            $internal = $internal{$fname};
 
             # $f =~ s/GET_SIZE/get_size/;
             if( $f =~ /^[A-Z_]+$/ ){
       	        $f = lcfirst($f);
             }
     	    $f =~ s/^(type|and|or|new)$/$1_/;
+            if( $internal ){ $f = "_internal_$f"; }
     
             # rem includes type 
             $rem =~ s/pyObject_p_option/t option/g;
 // --------------------------------- base
  
-void Py_Initialize();
+void [internal] Py_Initialize();
 
 void Py_Finalize();
  
 boolean PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc);
 // Return true if the given exception matches the exception in exc. If exc is a class object, this also returns true when given is an instance of a subclass. If exc is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
 
-// void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb)
+void [internal] PyErr_NormalizeException([out] PyObject**exc, [out] PyObject**val, [out] PyObject**tb);
 // Under certain circumstances, the values returned by PyErr_Fetch() below can be “unnormalized”, meaning that *exc is a class object but *val is not an instance of the same class. This function can be used to instantiate the class in that case. If the values are already normalized, nothing happens. The delayed normalization is implemented to improve performance.
 
 void PyErr_Clear();
     s/\[option\]\s*([A-Za-z0-9_]+)/$1_option/g;
     s/\[new\]\s*([A-Za-z0-9_]+)/$1_noincr/g;
     s/\[stolen\]\s*([A-Za-z0-9_]+)/$1_incr/g;
+    s/\[internal\]//g;
     if( /^[^\/]/ ){
         s/value/value_/g;
     }
 [new] PyObject* PyInt_FromSize_t(size_t ival);
 //    Create a new integer object with a value of ival. If the value exceeds LONG_MAX, a long integer object is returned.
 
-long PyInt_AsLong(PyObject *io);
+long [internal] PyInt_AsLong(PyObject *io);
 //    Will first attempt to cast the object to a PyIntObject, if it is not already one, and then return its value. If there is an error, -1 is returned, and the caller should check PyErr_Occurred() to find out whether there was an error, or whether the value just happened to be -1.
 
 // long PyInt_AS_LONG(PyObject *io);
 open Opycaml.Api
 
+let _ = 
+  prerr_endline "start";
+  Base.initialize ()
+;;
+
 let _ =
-  prerr_endline "start";
-  Base.initialize ();
+  try
+    ignore (Import.importModule "hogehoge")
+  with
+  | Error (e, detail) ->
+      Printf.eprintf "Error: %s %s\n%!" (String.asString (Object.repr e)) (String.asString (Object.repr detail))
+;;
+
+let _ =
   let o = String.fromString "hello world" in
   Base.debug "o" o;
 
     let minus_1 = Int.fromLong (-1) in
     assert (Int.asLong minus_1 = -1); 
 
+    Run.simpleString "print 'Run.simpleString'";
+    (* Run.simpleString "print(string.lowercase)"; *) (* does not work *)
+    (* Run.simpleString "print(lowercase)"; *) (* does not work *)
+
     ignore (Base.main []);
     prerr_endline "exited from toploop";
 
-    Base.finalize ()
   with
-  | Error e -> Printf.eprintf "Error: %s\n%!" (String.asString (Object.repr e))
+  | Error (e, detail) -> 
+      Printf.eprintf "Error: %s %s\n%!" (String.asString (Object.repr e)) (String.asString (Object.repr detail))
 ;;
 
-  
+let _ = Base.finalize ()
+open Opycaml.Api
+
+let _ = 
+  Base.initialize ();
+  ignore (Base.main []);
+  (* We cannot import things after Base.main ??? *)
+  ignore (Import.importModule "hogehoge"); 
+  Base.finalize ();
+  prerr_endline "finished"
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.