[pypy-svn] r6270 - pypy/branch/pypy-genc/translator
arigo at codespeak.net
arigo at codespeak.net
Thu Sep 2 17:43:22 CEST 2004
Author: arigo
Date: Thu Sep 2 17:43:22 2004
New Revision: 6270
Modified:
pypy/branch/pypy-genc/translator/genc.h
pypy/branch/pypy-genc/translator/genc.py
pypy/branch/pypy-genc/translator/typer.py
Log:
- Support for constant string objects.
- Factored bits of constant_representation() to can_convert_to_pyobj().
It's still quite big, though.
- Support for built-in functions in genc.py.
- New macro syntax CALL_funcname_typecodes in genc.h for typed built-in calls.
- In typer.py, replaced an infinite recursion with an error message (always a
good idea).
Modified: pypy/branch/pypy-genc/translator/genc.h
==============================================================================
--- pypy/branch/pypy-genc/translator/genc.h (original)
+++ pypy/branch/pypy-genc/translator/genc.h Thu Sep 2 17:43:22 2004
@@ -91,5 +91,11 @@
}
+/* a few built-in functions */
+
+#define CALL_len_oi(o,r,err) if ((r=PyObject_Size(o))<0) goto err;
+#define CALL_pow_iii(x,y,r) { int i=y; r=1; while (--i>=0) r*=x; } /*slow*/
+
+
/************************************************************/
/*** The rest is produced by genc.py ***/
Modified: pypy/branch/pypy-genc/translator/genc.py
==============================================================================
--- pypy/branch/pypy-genc/translator/genc.py (original)
+++ pypy/branch/pypy-genc/translator/genc.py Thu Sep 2 17:43:22 2004
@@ -2,10 +2,10 @@
Generate a C source file from the flowmodel.
"""
-import autopath, os, re
+import autopath, os, re, types, __builtin__
from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant
from pypy.objspace.flow.model import Block, Link, traverse
-from pypy.translator.typer import LLFunction, LLOp, LLConst
+from pypy.translator.typer import LLFunction, LLOp, LLConst, TypingError
from pypy.annotation import model as annmodel
@@ -24,10 +24,6 @@
return '<C: %s>' % ' + '.join(self.impl)
-class TypingError(Exception):
- pass
-
-
class CTypeSet:
"A (small) set of C types that typer.LLFunction can manipulate."
@@ -72,10 +68,12 @@
return hltype.impl
def typingerror(self, opname, hltypes):
- # build operations with a variable number of argument on demand
+ # build operations with a variable number of arguments on demand
if opname == 'OP_NEWLIST':
opnewlist = self.lloperations.setdefault('OP_NEWLIST', {})
sig = (self.R_OBJECT,) * len(hltypes)
+ if sig in opnewlist:
+ return False
def writer(*stuff):
content = stuff[:-2]
result = stuff[-2]
@@ -87,8 +85,23 @@
result, i, content[i], content[i]))
return '\n'.join(ls)
opnewlist[sig] = writer, True
- return # retry
- raise TypingError((opname,) + hltypes)
+ return True # retry
+ if opname == 'OP_SIMPLE_CALL' and hltypes:
+ opsimplecall = self.lloperations.setdefault('OP_SIMPLE_CALL', {})
+ sig = (self.R_OBJECT,) * len(hltypes)
+ if sig in opsimplecall:
+ return False
+ def writer(func, *stuff):
+ args = stuff[:-2]
+ result = stuff[-2]
+ err = stuff[-1]
+ format = 'O' * len(args)
+ return ('if (!(%s = PyObject_CallFunction(%s, "%s", %s)))'
+ ' goto %s;' % (result, func, format,
+ ', '.join(args), err))
+ opsimplecall[sig] = writer, True
+ return True # retry
+ return False
def knownanswer(self, llname):
if hasattr(llname, 'known_answer'):
@@ -131,25 +144,17 @@
conv[r, self.R_INT] = writer, False
writer.known_answer = [LLConst(self.R_INT, '%d' % value)]
# can convert the constant to a PyObject*
- def writer(z, err):
- return 'convert_io(%d, %s, %s)' % (value, z, err)
- conv[r, self.R_OBJECT] = writer, True
- llconst = LLConst('PyObject*', 'g_IntObject_%d' % value)
- writer.known_answer = [llconst]
- writer.globaldefs_decl = [llconst]
- writer.globaldefs_impl = ['%s = PyInt_FromLong(%d);' %
- (llconst.name, value)]
+ self.can_convert_to_pyobj(r, 'PyInt_FromLong(%d)' % value,
+ 'g_IntObj_%d' % value)
elif isinstance(value, str):
# can convert the constant to a PyObject*
- def writer(z, err):
- return 'convert_so(%s, %d, %s, %s)' % (
- (c_str(value), len(value), z, err))
- conv[r, self.R_OBJECT] = writer, True
+ self.can_convert_to_pyobj(r,
+ 'PyString_FromStringAndSize(%s, %d)' % (c_str(value),
+ len(value)),
+ 'g_StrObj_%s' % manglestr(value))
elif value is None:
# can convert the constant to Py_None
- def writer(z):
- return 'convert_vo(%s)' % (z,)
- conv[r, self.R_OBJECT] = writer, False
+ self.can_convert_to_pyobj(r, 'Py_None')
elif callable(value) and value in self.genc.llfunctions:
# another Python function: can be called with OP_SIMPLE_CALL
llfunc = self.genc.llfunctions[value]
@@ -176,10 +181,42 @@
else:
XXX("to do")
ops[tuple(sig)] = writer, True
+ elif (isinstance(value, types.BuiltinFunctionType) and
+ value is getattr(__builtin__, value.__name__, None)):
+ # a function from __builtin__: can convert to PyObject*
+ self.can_convert_to_pyobj(r,
+ 'PyMapping_GetItemString(PyEval_GetBuiltins(), %s)' % (
+ c_str(value.__name__)),
+ 'g_Builtin_%s' % manglestr(value.__name__))
+ # if the function is defined in genc.h, import its definition
+ # by copying the operation CALL_xxx to OP_SIMPLE_CALL with
+ # a first argument which is the constant function xxx.
+ opname = 'CALL_' + value.__name__
+ if opname in self.lloperations:
+ ops = self.lloperations.setdefault('OP_SIMPLE_CALL', {})
+ for sig, ll in self.lloperations[opname].items():
+ sig = (r,) + sig
+ ops[sig] = ll
else:
print "// XXX not implemented: constant", key
return r
+ def can_convert_to_pyobj(self, r, initexpr, globalname=None):
+ conv = self.lloperations['convert']
+ if globalname is not None:
+ def writer(z, err):
+ return 'if (!(%s = %s)) goto %s;' % (z, initexpr, err)
+ conv[r, self.R_OBJECT] = writer, True
+ llconst = LLConst('PyObject*', globalname)
+ writer.globaldefs_decl = [llconst]
+ writer.globaldefs_impl = ['%s = %s;' % (llconst.name, initexpr)]
+ else:
+ def writer(z):
+ return '%s = %s; Py_INCREF(%s);' % (z, initexpr, z)
+ conv[r, self.R_OBJECT] = writer, False
+ llconst = LLConst('PyObject*', initexpr)
+ writer.known_answer = [llconst]
+
def parse_operation_templates(self):
# parse the genc.h header to figure out which macros are implemented
codes = ''.join(self.REPR_BY_CODE.keys())
@@ -209,6 +246,18 @@
s = '"' + s[1:-1].replace('"', r'\"') + '"'
return s
+def manglestr(s):
+ "Return an identifier name unique for the string 's'."
+ l = []
+ for c in s:
+ if not ('a' <= c <= 'z' or 'A' <= c <= 'Z' or '0' <= c <= '9'):
+ if c == '_':
+ c = '__'
+ else:
+ c = '_%02x' % ord(c)
+ l.append(c)
+ return ''.join(l)
+
# ____________________________________________________________
Modified: pypy/branch/pypy-genc/translator/typer.py
==============================================================================
--- pypy/branch/pypy-genc/translator/typer.py (original)
+++ pypy/branch/pypy-genc/translator/typer.py Thu Sep 2 17:43:22 2004
@@ -23,6 +23,9 @@
self.args = args # list of LLVars
self.errtarget = errtarget # label to jump to in case of error
+class TypingError(Exception):
+ pass
+
# ____________________________________________________________
#
@@ -54,8 +57,8 @@
#
# def typingerror(self, opname, hltypes):
# Called when no match is found in lloperations. This function must
-# either extend lloperations and return (to retry), or raise an
-# exception (to stop).
+# either extend lloperations and return True to retry, or return
+# False to fail.
#
# def knownanswer(self, llname):
# Optionally returns a list of LLVars that give the well-known, constant
@@ -235,12 +238,17 @@
llname, can_fail = llsigs[sig]
break
else:
- self.typingerror(opname, tuple(args_t))
+ retry = self.typingerror(opname, tuple(args_t))
# if 'typingerror' did not raise an exception, try again.
# infinite recursion here means that 'typingerror' did not
# correctly extend 'lloperations'.
- self.operation(opname, args, result, errlabel, resulttype)
- return
+ if retry:
+ try:
+ self.operation(opname, args, result, errlabel, resulttype)
+ return
+ except RuntimeError: # infinite recursion
+ pass
+ raise TypingError([opname] + args_t)
# check if the answer has an existing well-known answer
if resulttype is not None: # if we are allowed to patch self.llreprs
llrepr = self.knownanswer(llname)
More information about the Pypy-commit
mailing list