Commits

Yosuke Onoue  committed 3d36217 Draft

fix caml_call

  • Participants
  • Parent commits b6ae7ca

Comments (0)

Files changed (3)

File otypes/template.py

 import sys
 import ctypes
 from functools import wraps
+from contextlib import contextmanager
 
 #define No_scan_tag 251
 NO_SCAN_TAG = 251
         roots.tables[i] = ctypes.pointer(arg)
     return roots
 
-def caml_xparam_n(args):
-    roots = caml__roots_block()
-    local_roots = caml_local_roots()
-    roots.next = local_roots
-    local_roots.contents = roots
-    roots.nitems = len(args)
-    roots.ntables = 1
-    roots.tables[0] = args
-
-def caml_local(n):
-    if n > 5:
-        values = (ml_value * n)()
-        caml_xparam_n(values)
-        return values
+@contextmanager
+def caml_local(*args):
+    values = [f() for f in args]
+    roots = caml_xparam(*values)
+    try:
+        if len(values) == 1:
+            yield values[0]
+        else:
+            yield values
+    except:
+        raise # TODO
     else:
-        values = [ml_value(0) for _ in range(n)]
-        roots = caml_xparam(*values)
-        if n == 1:
-            return roots, values[0]
-        else:
-            return roots, values
+        pass # TODO
 
 def caml_call(f):
     @wraps(f)
     def _caml_call(*args, **kw):
-        frame = force_cast_copy(caml_local_roots, caml__roots_block_p)
+        frame = force_cast_copy(caml_local_roots(), caml__roots_block_p)
         res = f(*args, **kw)
         if frame:
             caml_local_roots().contents = frame.contents

File otypes/util.py

 def alloc_array(seq, f=lambda x: x):
     @otypes.caml_call
     def inner(seq, f):
-        roots, ml_array = otypes.caml_local(1)
-        size = len(seq)
-        ml_array.value = otypes.caml_alloc(size, 0).value
-        for i,item in enumerate(seq):
-            ml_item = f(item)
-            otypes.store_field(ml_array, i, ml_item)
-        return ml_array
+        g = lambda : otypes.caml_alloc(len(seq), 0)
+        with otypes.caml_local(g) as ml_array:
+            for i, item in enumerate(seq):
+                otypes.store_field(ml_array, i, f(item))
+            return ml_array
     return inner(seq, f)
 
 def alloc_list(seq, f=lambda x: x):

File test/test.py

         res = lib.int_val(lib.caml_callback(f4, a, b, c, d))
         self.assertEqual(res, 10)
 
+    def test_caml_call(self):
+        @caml_call
+        def f():
+            g1 = lambda : lib.caml_copy_string('spam')
+            g2 = lambda : lib.caml_copy_string('ham')
+            g3 = lambda : lib.caml_copy_string('egg')
+            with lib.caml_local(g1, g2, g3) as (spam, ham, egg):
+                return spam, ham, egg
+        f()
+
 if __name__ == "__main__":
     unittest.main()