Commits

Yosuke Onoue committed 844e1af

add utility functions

Comments (0)

Files changed (3)

+import imp
+import sys
+import ctypes
+
+otypes_src = '''\
+import ctypes
+
+DOUBLE_TAG = 253
+
+class ml_intnat(ctypes.c_long):
+    def __repr__(self):
+        return 'ml_intnat({})'.format(self.value)
+
+class ml_uintnat(ctypes.c_ulong):
+    def __repr__(self):
+        return 'ml_uintnat({})'.format(self.value)
+
+class ml_value(ml_intnat):
+    def __repr__(self):
+        return 'ml_value({})'.format(self.value)
+
+class ml_header_t(ml_uintnat):
+    def __repr__(self):
+        return 'ml_header_t({})'.format(self.value)
+
+class ml_mlsize_t(ml_uintnat):
+    def __repr__(self):
+        return 'ml_size_t({})'.format(self.value)
+
+def caml_named_value(name):
+    return context.caml_named_value(ctypes.c_char_p(name)).contents
+
+def caml_callback(*args):
+    l = len(args)
+    if l == 2:
+        return ctypes.c_long(context.caml_callback(*args))
+    elif l == 3:
+        return ctypes.c_long(context.caml_callback2(*args))
+    elif l == 4:
+        return ctypes.c_long(context.caml_callback3(*args))
+    else:
+        # TODO
+        raise NotImplementedError()
+
+def caml_alloc(size, tag):
+    return ctypes.c_long(context.caml_alloc(size, tag))
+
+def caml_alloc_tuple(size):
+    return ctypes.c_long(context.caml_alloc_tuple(size))
+
+def caml_modify(dest, src):
+    return context.caml_modify(dest, src)
+
+def field(x, i):
+    return ctypes.c_long(ctypes.pointer(ctypes.c_long.from_address(x.value))[i])
+
+def store_field(block, offset, val):
+    block = ctypes.c_long(block.value + ctypes.alignment(ctypes.c_long) * offset)
+    return context.caml_modify(block, val)
+
+def is_long(x):
+    return (x.value & 1) != 0
+
+def is_block(x):
+    return (x.value & 1) == 0
+
+def val_long(x):
+    return (x << 1) + 1
+
+def long_val(x):
+    return x.value >> 1
+
+def val_int(x):
+    return val_long(x)
+
+def int_val(x):
+    return ctypes.c_int(long_val(x))
+
+def store_double_val(v, d):
+    ctypes.c_double.from_address(v.value).value = d
+
+def double_val(v):
+    return ctypes.c_double.from_address(v.value).value
+
+def val_emptylist():
+    return ctypes.c_long(val_int(0))
+
+def wosize_hd(hd):
+    return ml_mlsize_t(hd.value >> 10)
+
+def hd_val(val):
+    return ml_header_t.from_address(val.value - ctypes.alignment(ml_header_t))
+
+def wosize_val(val):
+    return wosize_hd(hd_val(val))
+'''
+
+util_src = '''\
+def alloc_tuple(*args):
+    size = len(args)
+    ml_tuple = otypes.caml_alloc(size, 0)
+    for i,arg in enumerate(args):
+        otypes.store_field(ml_tuple, i, arg)
+    return ml_tuple
+
+def alloc_array(seq, f=lambda x: x):
+    size = len(seq)
+    ml_array = otypes.caml_alloc(size, 0)
+    for i,item in enumerate(seq):
+        ml_item = f(item)
+        otypes.store_field(ml_array, i, ml_item)
+    return ml_array
+
+def alloc_list(seq, f=lambda x: x):
+    ml_next = otypes.val_emptylist()
+    for item in reversed(seq):
+        ml_item = f(item)
+        ml_next = alloc_tuple(ml_item, ml_next)
+    return ml_next
+
+def py_list_of_ml_list(ml_list, f=lambda x: x):
+    l = []
+    empty = otypes.val_emptylist().value
+    while ml_list.value != empty:
+        l.append(f(otypes.field(ml_list, 0)))
+        ml_list = otypes.field(ml_list, 1)
+    return l
+
+def py_list_of_ml_array(ml_array, f=lambda x: x):
+    size = ml_array_length(ml_array)
+    return [f(otypes.field(ml_array, i)) for i in range(size)]
+
+def ml_array_length(ml_array):
+    return otypes.wosize_val(ml_array).value
+'''
+
+def load_lib(name):
+    lib = ctypes.CDLL(name)
+    ArgArray = ctypes.c_char_p * (len(sys.argv) + 1)
+    args = ArgArray()
+    for i,arg in enumerate(sys.argv):
+        args[i] = ctypes.c_char_p(arg)
+    args[len(sys.argv)] = None
+    lib.caml_startup(args)
+    lib.caml_named_value.restype = ctypes.POINTER(ctypes.c_long)
+    lib.caml_callback.restype = ctypes.c_long
+    lib.caml_callback2.restype = ctypes.c_long
+    lib.caml_callback3.restype = ctypes.c_long
+    lib.caml_alloc.restype = ctypes.c_long
+    return lib
+
+def create_module(name, src, context):
+    mod = imp.new_module(name)
+    mod.__dict__['__source__'] = src
+    exec src in mod.__dict__
+    mod.__dict__['context'] = context
+    sys.modules[name] = mod
+    return mod
+
+def make(name, module_name):
+    lib = load_lib(name)
+    mod = create_module(module_name, otypes_src, lib)
+    util = create_module(module_name + '.util', util_src, lib)
+    util.__dict__['otypes'] = mod
+    mod.__dict__['util'] = util
   List.sort (fun a  b -> b - a) list
 
 let sort_array array =
-  Array.iter (fun x -> Printf.printf "%d " x) array;print_newline ();
   Array.sort (fun a b -> b - a) array
 
 let _ =
 otypes.make('sample.so', 'sample')
 import sample
 import sample as lib
+from sample import util
 
 print 'test1'
 x = lib.caml_named_value('x')
 
 print 'test6 passing tuple'
 max3 = lib.caml_named_value('max3')
-arg = lib.caml_alloc(3, 0)
-lib.store_field(arg, 0, lib.val_int(3))
-lib.store_field(arg, 1, lib.val_int(8))
-lib.store_field(arg, 2, lib.val_int(5))
+arg = util.alloc_tuple(lib.val_int(3), lib.val_int(8), lib.val_int(5))
 ret = lib.caml_callback(max3, arg)
 print lib.int_val(ret).value
 print
 
+
 print 'test7 sorting array'
 l = [1,4,2,35,64,3,12,14,46,57]
 sort_array = lib.caml_named_value('sort_array')
-ml_array = lib.caml_alloc(len(l), 0)
-for i,item in enumerate(l):
-    lib.store_field(ml_array, i, lib.val_int(item))
+ml_array = util.alloc_array(l, lib.val_int)
 lib.caml_callback(sort_array, ml_array)
-for i in range(len(l)):
-    print lib.int_val(lib.field(ml_array, i)).value
+res = util.py_list_of_ml_array(ml_array, lambda x: lib.int_val(x).value)
+print res
 print
 
 print 'test8 sorting list'
+l = [1,4,2,35,64,3,12,14,46,57]
 sort_list = lib.caml_named_value('sort_list')
-def cons(hd, tl):
-    l = lib.caml_alloc(2, 1)
-    lib.store_field(l, 0, hd)
-    lib.store_field(l, 1, tl)
-    return l
-tl = lib.val_emptylist()
-tl = cons(lib.val_int(57), tl)
-tl = cons(lib.val_int(46), tl)
-l = cons(lib.val_int(58), tl)
-l = lib.caml_callback(sort_list, l)
-print lib.int_val(lib.field(l, 0)).value
-l = lib.field(l, 1)
-print lib.int_val(lib.field(l, 0)).value
-l = lib.field(l, 1)
-print lib.int_val(lib.field(l, 0)).value
+ml_list = util.alloc_list(l, lib.val_int)
+ml_list = lib.caml_callback(sort_list, ml_list)
+res = util.py_list_of_ml_list(ml_list, lambda x: lib.int_val(x).value)
+print res
+print