[pypy-svn] r14474 - in pypy/dist/pypy: annotation rpython rpython/test translator/c translator/c/test

arigo at codespeak.net arigo at codespeak.net
Sun Jul 10 15:27:45 CEST 2005


Author: arigo
Date: Sun Jul 10 15:27:40 2005
New Revision: 14474

Modified:
   pypy/dist/pypy/annotation/specialize.py
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rbuiltin.py
   pypy/dist/pypy/translator/c/extfunc_include.h
   pypy/dist/pypy/translator/c/fixedname.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/test/test_extfunc.py
Log:
GenC now passes a test for os.open/write/read/close().  This required the
following changes:

- some C code in extfunc_include.h, but not too much.  It looks quite nice.

- specialization now always attached an attribute _specializedversionof_ to
  the specialized functions, pointing back to the original one.  This allows
  the function pointer objects to have the original function as _callable
  in all cases, which is needed to be able to recognize them.

- all ll_os_* and ll_time_* functions are now annotated by default.  This
  required some more allowance in annlowlevel to not complain on high-level
  objects (e.g. SomeStrings) being passed around in low-level functions.

- fix some broken tests.

- GenC checks that it isn't trying to compile a suggested_primitive.



Modified: pypy/dist/pypy/annotation/specialize.py
==============================================================================
--- pypy/dist/pypy/annotation/specialize.py	(original)
+++ pypy/dist/pypy/annotation/specialize.py	Sun Jul 10 15:27:40 2005
@@ -27,7 +27,7 @@
         if isinstance(key, tuple): 
             # cache specialization
             try:
-                func = bookkeeper.cachespecializations[key]
+                newfunc = bookkeeper.cachespecializations[key]
             except KeyError:
                 if key[0] is func:
                     postfix = key[1:]
@@ -36,14 +36,16 @@
                 newfunc = clone(func, postfix)
                 if key[0] is func:
                     bookkeeper.cachespecializations[(newfunc,) + postfix] = newfunc
-                func = bookkeeper.cachespecializations[key] = newfunc
+                bookkeeper.cachespecializations[key] = newfunc
         elif isinstance(key, str): 
             # specialization explicit in operation annotation
             postfix = key
-            func = clone(func, postfix)
+            newfunc = clone(func, postfix)
         else: 
             # specialization already retrieved
-            func = key
+            newfunc = key
+        newfunc._specializedversionof_ = func
+        func = newfunc
     
     if unpacked:
         func = func, args

Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Sun Jul 10 15:27:40 2005
@@ -45,7 +45,12 @@
                 new_args_s.append(s_obj)
             else:
                 new_args_s.append(not_const(s_obj))
-                key.append(annmodel.annotation_to_lltype(s_obj))
+                try:
+                    key.append(annmodel.annotation_to_lltype(s_obj))
+                except ValueError:
+                    # passing non-low-level types to a ll_* function is allowed
+                    # for module/ll_*
+                    key.append(s_obj.__class__)
         return tuple(key), bookkeeper.build_args('simple_call', new_args_s)
         
 

Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Sun Jul 10 15:27:40 2005
@@ -35,7 +35,7 @@
 
 
 table = {}
-def declare(func, annotation, ll_function, ll_annotable=False, backend_functiontemplate=None):
+def declare(func, annotation, ll_function, ll_annotable=True, backend_functiontemplate=None):
     # annotation can be a function computing the annotation
     # or a simple python type from which an annotation will be constructed
     global table
@@ -51,7 +51,7 @@
 nonefactory = lambda *args: None
 
 # external function declarations
-declare(os.open   , int        , 'll_os/open', True)
+declare(os.open   , int        , 'll_os/open')
 declare(os.read   , str        , 'll_os/read')
 declare(os.write  , int        , 'll_os/write')
 declare(os.close  , nonefactory, 'll_os/close')

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Sun Jul 10 15:27:40 2005
@@ -226,13 +226,12 @@
 def getconcretetype(v):
     return getattr(v, 'concretetype', PyObjPtr)
 
-def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype, _callable=None):
+def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype):
     """Make a functionptr from the given Python function."""
     graph = translator.getflowgraph(graphfunc)
     llinputs = [getconcretetype(v) for v in graph.getargs()]
     lloutput = getconcretetype(graph.getreturnvar())
     FT = FuncType(llinputs, lloutput)
-    if _callable is None:
-        _callable = graphfunc
+    _callable = getattr(graphfunc, '_specializedversionof_', graphfunc)
     return functionptr(FT, graphfunc.func_name, graph = graph, _callable = _callable)
 

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Sun Jul 10 15:27:40 2005
@@ -382,10 +382,10 @@
 
     # __________ utilities __________
 
-    def getfunctionptr(self, graphfunc, _callable=None):
+    def getfunctionptr(self, graphfunc):
         def getconcretetype(v):
             return self.bindingrepr(v).lowleveltype
-        return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype, _callable=_callable)
+        return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype)
 
     def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None):
         self.call_all_setups()  # compute ForwardReferences now
@@ -543,7 +543,7 @@
         dontcare, spec_function = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s)
 
         # build the 'direct_call' operation
-        f = self.rtyper.getfunctionptr(spec_function, _callable=ll_function)
+        f = self.rtyper.getfunctionptr(spec_function)
         c = inputconst(typeOf(f), f)
         return self.genop('direct_call', [c]+list(args_v),
                           resulttype = typeOf(f).TO.RESULT)

Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rbuiltin.py	Sun Jul 10 15:27:40 2005
@@ -93,10 +93,10 @@
     except OSError:
         pass
     count = 0
-    from pypy.rpython import extfunctable
+    from pypy.rpython.module import ll_os
     for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn):
         cfptr = dir_call.args[0]
-        assert cfptr.value._obj._callable == extfunctable.ll_os_dup
+        assert cfptr.value._obj._callable == ll_os.ll_os_dup
         count += 1
     assert count == 1
 
@@ -110,10 +110,10 @@
     res = interpret(f, [])
     os.close(res)
     count = 0
-    from pypy.rpython import extfunctable
+    from pypy.rpython.module import ll_os
     for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, wr_open):
         cfptr = dir_call.args[0]
-        assert cfptr.value._obj._callable == extfunctable.ll_os_open
+        assert cfptr.value._obj._callable == ll_os.ll_os_open
         count += 1
     assert count == 1
         

Modified: pypy/dist/pypy/translator/c/extfunc_include.h
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc_include.h	(original)
+++ pypy/dist/pypy/translator/c/extfunc_include.h	Sun Jul 10 15:27:40 2005
@@ -6,6 +6,7 @@
 /******************************************************************/
 
 
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -15,32 +16,66 @@
   #define PATH_MAX 254
 #endif
 
-/* The functions below are mapped to functions from pypy.rpython.extfunctable
-   by the pypy.translator.c.fixedname.EXTERNALS dictionary. */
+/* The functions below are mapped to functions from pypy.rpython.module.*
+   by the pypy.translator.c.fixedname.EXTERNALS dictionary.
+   They should correspond to the functions with the suggested_primitive
+   flag set, and NOT necessarily directly to the ll_os_*() functions.
+   See for example ll_read_into(), which is called by ll_os_read().
+   The latter would be messy to write here, but LL_read_into() is quite easy.
+*/
 
 #define RPyString_Size(rps)		((rps)->rs_chars.length)
 #define RPyString_AsString(rps)		((rps)->rs_chars.items)
 
 
+/************************************************************/
+ /***   os module                                          ***/
+
+
 int LL_os_open(RPyString *filename, int flag, int mode)
 {
 	char buf[PATH_MAX];
 	int fd, error, namelen = RPyString_Size(filename);
 	if (namelen >= PATH_MAX) {
-		error = ENAMETOOLONG;
+		RAISE_OSERROR(ENAMETOOLONG);
+		return -1;
 	}
 	else {
 		memcpy(buf, RPyString_AsString(filename), namelen);
 		buf[namelen] = 0;
 		fd = open(buf, flag, mode);
-		if (fd != -1)
-			return fd;
-		error = errno;
+		if (fd == -1)
+			RAISE_OSERROR(errno);
+		return fd;
 	}
-	RAISE_OSERROR(error);
-	return -1;
 }
 
+long LL_read_into(int fd, RPyString *buffer)
+{
+	long n = read(fd, RPyString_AsString(buffer), RPyString_Size(buffer));
+	if (n == -1)
+		RAISE_OSERROR(errno);
+	return n;
+}
+
+long LL_os_write(int fd, RPyString *buffer)
+{
+	long n = write(fd, RPyString_AsString(buffer), RPyString_Size(buffer));
+	if (n == -1)
+		RAISE_OSERROR(errno);
+	return n;
+}
+
+void LL_os_close(int fd)
+{
+	if (close(fd) == -1)
+		RAISE_OSERROR(errno);
+}
+
+
+/************************************************************/
+ /***   time module                                        ***/
+
 
 double LL_time_clock(void)
 {

Modified: pypy/dist/pypy/translator/c/fixedname.py
==============================================================================
--- pypy/dist/pypy/translator/c/fixedname.py	(original)
+++ pypy/dist/pypy/translator/c/fixedname.py	Sun Jul 10 15:27:40 2005
@@ -9,6 +9,9 @@
 # table of functions hand-written in extfunc_include.h
 EXTERNALS = {
     ll_os  .ll_os_open:    'LL_os_open',
+    ll_os  .ll_read_into:  'LL_read_into',
+    ll_os  .ll_os_write:   'LL_os_write',
+    ll_os  .ll_os_close:   'LL_os_close',
     ll_time.ll_time_clock: 'LL_time_clock',
     }
 

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Sun Jul 10 15:27:40 2005
@@ -480,6 +480,9 @@
         # fixedname.EXTERNALS.
         db.externalfuncs[fnobj._callable] = fnobj
         return None
+    elif getattr(fnobj._callable, 'suggested_primitive', False):
+        raise ValueError, "trying to compile suggested primitive %r" % (
+            fnobj._callable,)
     elif hasattr(fnobj, 'graph'):
         cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython"
         return FunctionCodeGenerator(fnobj.graph, db, cpython_exc)

Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_extfunc.py	Sun Jul 10 15:27:40 2005
@@ -1,11 +1,11 @@
 import autopath
 import py
+import os, time
 from pypy.tool.udir import udir
 from pypy.translator.c.test.test_genc import compile
 
 
 def test_time_clock():
-    import time
     def does_stuff():
         return time.clock()
     f1 = compile(does_stuff, [])
@@ -17,7 +17,6 @@
 
 
 def test_os_open():
-    import os
     tmpfile = str(udir.join('test_os_open.txt'))
     def does_stuff():
         fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777)
@@ -29,7 +28,6 @@
     assert os.path.exists(tmpfile)
 
 def test_failing_os_open():
-    import os
     tmpfile = str(udir.join('test_failing_os_open.DOESNTEXIST'))
     def does_stuff():
         fd = os.open(tmpfile, os.O_RDONLY, 0777)
@@ -38,3 +36,20 @@
     f1 = compile(does_stuff, [])
     py.test.raises(OSError, f1)
     assert not os.path.exists(tmpfile)
+
+def test_open_read_write_close():
+    filename = str(udir.join('test_open_read_write_close.txt'))
+    def does_stuff():
+        fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777)
+        count = os.write(fd, "hello world\n")
+        assert count == len("hello world\n")
+        os.close(fd)
+        fd = os.open(filename, os.O_RDONLY, 0777)
+        data = os.read(fd, 500)
+        assert data == "hello world\n"
+        os.close(fd)
+
+    f1 = compile(does_stuff, [])
+    f1()
+    assert open(filename, 'r').read() == "hello world\n"
+    os.unlink(filename)



More information about the Pypy-commit mailing list