Source

opycaml / api.ml

include Type

module Py = struct
  module OCaml = struct
    module String = String
    module Callback = Callback
    module List = List
  end
    
  open Autoapi

  module String = String
  module ByteArray = ByteArray
  module Number = Number
  module Type = Type
  module Mapping = Mapping
  module DictProxy = DictProxy
  module Dict = struct
    include Dict
    let new_proxy = DictProxy.new_
  end

  module Index = Index
  module Import = Import
  module Iter = Iter

  module Sequence = Sequence
  module Eval = Eval
  module Run = Run
  
  module Tuple = struct
    include Tuple

    module X : sig
      val from_list : [> _Object] t list -> _Tuple t
      val to_list : _Tuple t -> _Object t list
    end = struct
      let from_list lst =
	let tpl = new_ (OCaml.List.length lst) in
	Utils.List.iteri (setItemPos tpl) lst;
	tpl
  
      let to_list a =
	let len = _GET_SIZE a in
	let rec f st = function
          | -1 -> st
          | n -> f (getItemPos a n :: st) (n-1)
	in
	f [](len-1)
    end
    include X
  end
  
  module Callback : sig
    val functions : (string, _Object t option -> _Object t list -> _Object t) Hashtbl.t
    val initialize : unit -> unit
  end = struct
    (** Python calls OCaml function *)
    (* open Type *)
    
    let functions = Hashtbl.create 107
    
    type result = 
      | Ok of _Object t
      | Error of string
      | Not_found of _Object t
    
    let callback : _Object t option -> _Tuple t -> result = fun self_option args_tuple ->
      prerr_endline "Opycaml.Api.Callback.callback is called!";
      let args = Tuple.to_list args_tuple in
      match args with
      | [] -> assert false
      | name_object::args ->
  	  let f = try Some (Hashtbl.find functions (String.asString (Object.str name_object))) with _ -> None in
  	  match f with
  	  | None -> Not_found name_object
  	  | Some f -> try Ok (f self_option args) with e -> Error (Printexc.to_string e)
    ;;
  
    let closure_callback : (_Tuple t -> _Object t) -> _Tuple t -> result = fun closure args_tuple ->
      try Ok (closure args_tuple) with e -> Error (Printexc.to_string e)
    ;;
  
    external python_init : unit -> unit = "opycaml_init_callback"

    let initialize () = 
      prerr_endline "Opycaml.Api.Callback.initialize()...";
      OCaml.Callback.register "( ゚∀゚)o彡°O'PyCaml callback" callback;
      OCaml.Callback.register "( ゚∀゚)o彡°O'PyCaml closure callback" closure_callback;
      python_init ()
  end
  
  module Base = struct
    include Base

    module X : sig
      external none : unit -> _None t = "opycaml_none"
        (** Get Py_None object. *)
    
      external phys_eq : [>_Object] t -> [>_Object] t -> bool = "opycaml_physical_equal"
        (** Checks physical equality of objects *)
    
      (* reference count functions: use with care *)
      external refcnt : [>_Object] t -> int = "opycaml_refcnt"
      external incref : [>_Object] t -> unit = "opycaml_incref"
      external decref : [>_Object] t -> unit = "opycaml_decref"
    
      (* get address of objects for debugging *)
      external address : [>_Object] t -> nativeint = "opycaml_address"
    
      val initialize : unit -> unit
        (** Python api initialization with OCaml exception registeration.
    	Any other function in OPyCaml must be called after [initialize ()].
        *)
    
      val debug : string -> [>_Object] t -> unit
        (** debug print of objects *) 
    
      val main : string list -> int
        (** Call to Py_Main
    
    	The main program for the standard interpreter. This is made available for programs which embed Python. The argc and argv parameters should be prepared exactly as those which are passed to a C program’s main() function. It is important to note that the argument list may be modified (but the contents of the strings pointed to by the argument list are not). The return value will be the integer passed to the sys.exit() function, 1 if the interpreter exits due to an exception, or 2 if the parameter list does not represent a valid Python command line.
    	Note that if an otherwise unhandled SystemError is raised,
    	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(_), while CTRL+D works fine.
        **)

      external unsafe_embed : 'a -> _CObject t = "opycaml_embed_ocaml_value"
      (** Unsafe: embed any OCaml value into Python's CObject. *)

      external unsafe_extract : _CObject t -> 'a = "opycaml_extract_embeded_ocaml_value"
      (** Unsafe: extract an OCaml value from Python's CObject. 
          It merely tests the given object is really a CObject or not.
          No other sanity check is performed.

          EXTREMELY UNSAFE OPERATION. UNTESTED. BAD IDEA.
          TRY AVOID USING THIS. THINK TWICE WHY YOU NEED THIS. 
      *)

      external embed_closure : ([> _Tuple] t -> _Object t) -> _Closure t = "opycaml_create_closure_wrap"
	(** Embed an OCaml function of type [[> _Tuple] t -> _Object t] to a Python object *)
    end = struct
  
      external none : unit -> _None t = "opycaml_none"
      external poly_none : unit -> 'a t = "opycaml_none" (* unsafe *)
      external phys_eq : [>_Object] t -> [>_Object] t -> bool = "opycaml_physical_equal"
      external refcnt : [>_Object] t -> int = "opycaml_refcnt"
      external incref : [>_Object] t -> unit = "opycaml_incref"
      external decref : [>_Object] t -> unit = "opycaml_decref"
      external address : [>_Object] t -> nativeint = "opycaml_address"
    
      external internal_init : unit -> unit = "opycaml_init"
      let initialized = ref false
      let initialize () =
        if not !initialized then begin
          initialized := true;
          OCaml.Callback.register_exception "( ゚∀゚)o彡°O'PyCaml exception" (Error (poly_none (), poly_none ()));
          internal_init ();
          if Sys.argv.(0) <> "from python" then _internal_initialize ();
          Callback.initialize ()
        end
      ;;

      let debug name o =
        let cnt = refcnt o in
        let repr = String.asString (Object.repr o) in
        let address = address o in
        Printf.eprintf "%s : %d : %nx : %s\n%!" name cnt address repr
    
      external _main : int -> string list -> int = "opycaml_Py_Main"
      let main argv = _main (OCaml.List.length argv) argv

      external unsafe_embed : 'a -> _CObject t = "opycaml_embed_ocaml_value"
      external unsafe_extract : _CObject t -> 'a = "opycaml_extract_embeded_ocaml_value"

      external embed_closure : ([> _Tuple] t -> _Object t) -> _Closure t = "opycaml_create_closure_wrap"
    end

    include X
  end
  
  module Module = struct
    include Module
      
    module X : sig
      val setToSys : [>_Module] t -> string -> unit
	(** [setToSys name m] registers a module [m] as [name] into
	    the Python system modules dictionary. 

            Note: the argument order is fliped for OO interface
        *)

      val setItemString : [>_Module] t -> string -> [>_Object] t -> unit
	(** [setItemString m name t] adds object [t] to the module [m]'s
	    dictionary as [name]. *)

      val setClosureString : [>_Module] t -> string -> ([>_Tuple] t -> _Object t) -> unit
	(** [setItemString m name t] adds object [t] to the module [m]'s
	    dictionary as [name]. *)
    end = struct
      let setToSys m name =
	let sys = Import.importModule "sys" in
	let sysdict = Module.getDict sys in
	let modules = Dict.coerce (Dict.getItemString sysdict "modules") in
	Dict.setItemString modules name m

      let setItemString m name t =
	let dict = Module.getDict m in
	Dict.setItemString dict name t

      let setClosureString m name clos =
	let oclos = Base.embed_closure clos in
	setItemString m name oclos
    end
    include X
  end 

  module Object = struct
    include Object

    module X : sig
      val call : [> _Callable ] t -> ?kwd:[> _Dict ] t -> [> _Object ] t list -> _Object t
	(** Function call *)
      val callObject : [> _Callable ] t -> [> _Object ] t list -> _Object t
	(** Object method call *)
      val obj : [> _Object ] t -> _Object t
	(** Forget the type of the object *)
      val repr_string : [> _Object ] t -> string
      (** obtain OCaml string of repr *)
      val str_string : [> _Object ] t -> string
	(** obtain OCaml string of str *)
    end = struct
      let call callable ?kwd list =
	_internal_call callable (Tuple.from_list list) kwd
  
      let callObject callable = function
	| [] -> _internal_callObject callable None
	| list -> _internal_callObject callable (Some (Tuple.from_list list))

      let obj t : _Object t = unsafe_coerce t

      let repr_string t = String.asString (repr t)
      let str_string t = String.asString (str t)
    end

    include X

    (* copied from Base *)       
    let debug o s = Base.debug s o
    let address = Base.address
    let decref = Base.decref
    let incref = Base.incref
    let refcnt = Base.refcnt
    let phys_eq = Base.phys_eq

    (* copied from ByteArray *)
    let toByteArray = ByteArray.fromObject

    (* from Err *) (* CR jfuruse: not sure they are ok or not *)
    let errWriteUnraisable = Err.writeUnraisable
    let errNewException str o1 o2 = Err.newException o1 str o2
    let errSetNone = Err.setNone
    let errSetObject = Err.setObject
    let errSetString = Err.setString
    let errGivenExceptionMatches = Err.givenExceptionMatches
    let errExceptionMatches = Err.exceptionMatches
  
  end
  
  module Callable = struct
    include Callable

    let _internal_call = Object._internal_call
    let _internal_callObject = Object._internal_callObject
    let call = Object.call
    let callObject = Object.callObject
  end

  module Err = struct
    include Err

    module X : sig
      external reraise : unit -> 'a = "opycaml_error"
        (** reraise the current exception. 
    	Err.Occured() must be return Some. Otherwise Failwith is
        raised instead. *)
    
      val normalizeException : unit -> (_Object t * _Object t * _Object t) option
    end = struct
      external reraise : unit -> 'a = "opycaml_error"
  
      let normalizeException () =
	match occurred () with
	| None -> None
	| Some _ -> Some (_internal_normalizeException ())
    end

    include X
  end
  
  module Int = struct
    include Int

    module X : sig  
      val asLong : [>_Int] t -> int
          (** raises Error at overflow *)
    end = struct
      let asLong t =
	let res = _internal_asLong t in
	if res <> -1 then res
	else match Err.occurred () with
	| None -> -1
	| Some _ -> Err.reraise ()
    end
      
    include X
  end

  module Class = struct
    let isSubclass = Object.isSubclass
  end
  
end

(* Name space hack: Modules whose names do not collide with the OCaml
   standard library are exported here too. *)
open Py
(* module String = String -- collides with OCaml standard library *)
(* module Callback = -- collides with OCaml standard library *)
module ByteArray = ByteArray
module Number = Number
module Type = Type
module Mapping = Mapping
module Dict = Dict
module DictProxy = DictProxy
module Module = Module
module Index = Index
module Import = Import
module Iter = Iter
module Callable = Callable
module Sequence = Sequence
module Eval = Eval
module Run = Run
module Tuple = Tuple
module Base = Base
module Object = Object
module Err = Err
module Int = Int
module Class = Class

let _ = Base.initialize ()
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.