--- /dev/null
+#
+# Pyrex - Builtin Definitions
+#
+
+from Symtab import BuiltinScope
+from TypeSlots import Signature
+
+builtin_function_table = [
+ # name, args, return, C API func, py equiv = "*"
+ ('abs', "O", "O", "PyNumber_Absolute"),
+ #('chr', "", "", ""),
+ #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
+ #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start)
+ ('delattr', "OO", "r", "PyObject_DelAttr"),
+ ('dir', "O", "O", "PyObject_Dir"),
+ ('divmod', "OO", "O", "PyNumber_Divmod"),
+ #('eval', "", "", ""),
+ #('execfile', "", "", ""),
+ #('filter', "", "", ""),
+ ('getattr', "OO", "O", "PyObject_GetAttr"),
+ ('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr"),
+ ('hasattr', "OO", "i", "PyObject_HasAttr"),
+ ('hash', "O", "i", "PyObject_Hash"),
+ #('hex', "", "", ""),
+ #('id', "", "", ""),
+ #('input', "", "", ""),
+ ('intern', "s", "O", "PyString_InternFromString"),
+ ('isinstance', "OO", "i", "PyObject_IsInstance"),
+ ('issubclass', "OO", "i", "PyObject_IsSubclass"),
+ ('iter', "O", "O", "PyObject_GetIter"),
+ ('len', "O", "Z", "PyObject_Length"),
+ #('map', "", "", ""),
+ #('max', "", "", ""),
+ #('min', "", "", ""),
+ #('oct', "", "", ""),
+ # Not worth doing open, when second argument would become mandatory
+ #('open', "ss", "O", "PyFile_FromString"),
+ #('ord', "", "", ""),
+ ('pow', "OOO", "O", "PyNumber_Power"),
+ #('range', "", "", ""),
+ #('raw_input', "", "", ""),
+ #('reduce', "", "", ""),
+ ('reload', "O", "O", "PyImport_ReloadModule"),
+ ('repr', "O", "O", "PyObject_Repr"),
+ #('round', "", "", ""),
+ ('setattr', "OOO", "r", "PyObject_SetAttr"),
+ #('sum', "", "", ""),
+ #('unichr', "", "", ""),
+ #('unicode', "", "", ""),
+ #('vars', "", "", ""),
+ #('zip', "", "", ""),
+ # Can't do these easily until we have builtin type entries.
+ #('typecheck', "OO", "i", "PyObject_TypeCheck", False),
+ #('issubtype', "OO", "i", "PyType_IsSubtype", False),
+]
+
+# Builtin types
+# bool
+# buffer
+# classmethod
+# dict
+# enumerate
+# file
+# float
+# int
+# list
+# long
+# object
+# property
+# slice
+# staticmethod
+# super
+# str
+# tuple
+# type
+# xrange
+
+getattr3_utility_code = ["""
+static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
+""","""
+static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
+ PyObject *r = PyObject_GetAttr(o, n);
+ if (!r) {
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ goto bad;
+ PyErr_Clear();
+ r = d;
+ Py_INCREF(d);
+ }
+ return r;
+bad:
+ return 0;
+}
+"""]
+
+builtin_utility_code = {
+ 'getattr3': getattr3_utility_code,
+}
+
+builtin_scope = BuiltinScope()
+
+def declare_builtin_func(name, args, ret, cname, py_equiv = "*"):
+ sig = Signature(args, ret)
+ type = sig.function_type()
+ utility = builtin_utility_code.get(name)
+ builtin_scope.declare_builtin_cfunction(name, type, cname, py_equiv, utility)
+
+def init_builtin_funcs():
+ for desc in builtin_function_table:
+ declare_builtin_func(*desc)
+
+def init_builtins():
+ init_builtin_funcs()
+
+init_builtins()
# temps used during assignment.
#
# calculate_result_code
- # - Return a C code fragment evaluating to
- # the result. This is only called when the
- # result is not a temporary.
+ # - Called during the Allocate Temps phase. Should return a
+ # C code fragment evaluating to the result. This is only
+ # called when the result is not a temporary.
#
# target_code
# Called by the default implementation of allocate_target_temps.
if debug_temp_alloc:
print self, "Allocated result", self.result_code
else:
- self.result_code = self.calculate_result_code()
+ self.result_code = self.calculate_result_code_with_env(env)
+
+ def calculate_result_code_with_env(self, env):
+ return self.calculate_result_code()
def target_code(self):
# Return code fragment for use as LHS of a C assignment.
if entry.is_pyglobal or entry.is_builtin:
assert type.is_pyobject, "Python global or builtin not a Python object"
if Options.intern_names:
- self.interned_cname = env.intern(self.name)
+ self.interned_cname = env.intern(self.entry.name)
def check_identifier_kind(self):
#print "NameNode.check_identifier_kind:", self.entry.name ###
#print self.entry.__dict__ ###
entry = self.entry
- entry.used = 1
+ #entry.used = 1
if not (entry.is_const or entry.is_variable
or entry.is_builtin or entry.is_cfunction):
if self.entry.as_variable:
# result is in a temporary.
return 0
+ def calculate_result_code_with_env(self, env):
+ entry = self.entry
+ if entry:
+ entry.used = 1
+ if entry.utility_code:
+ env.use_utility_code(entry.utility_code)
+ return self.calculate_result_code()
+
def calculate_result_code(self):
- if self.entry is None:
+ entry = self.entry
+ if not entry:
return "<error>" # There was an error earlier
- return self.entry.cname
+ entry.used = 1
+ return entry.cname
def generate_result_code(self, code):
assert hasattr(self, 'entry')
- #if not hasattr(self, 'entry'):
- # error(self.pos, "INTERNAL ERROR: NameNode has no entry attribute during code generation")
entry = self.entry
if entry is None:
return # There was an error earlier
else: # entry.is_pyglobal
namespace = entry.namespace_cname
if Options.intern_names:
- #assert entry.interned_cname is not None
code.putln(
'%s = __Pyx_GetName(%s, %s); %s' % (
self.result_code,
namespace,
- #entry.interned_cname,
self.interned_cname,
code.error_goto_if_null(self.result_code, self.pos)))
else:
# of an extension type
# defined_in_pxd boolean Is defined in a .pxd file (not just declared)
# api boolean Generate C API for C class or function
+ # utility_code string Utility code needed when this entry is used
borrowed = 0
init = ""
is_special = 0
defined_in_pxd = 0
api = 0
+ utility_code = None
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
self.cached_entries.append(entry)
self.undeclared_cached_entries.append(entry)
else:
- entry.is_builtin = 1
+ entry.is_builtin = 1
return entry
-
- def declare_builtin_cfunction(self, name, type, cname, with_python_equiv = 0):
+
+ def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
+ utility_code = None):
+ # If python_equiv == "*", the Python equivalent has the same name
+ # as the entry, otherwise it has the name specified by python_equiv.
entry = self.declare_cfunction(name, type, None, cname)
- if with_python_equiv:
- var_entry = Entry(name, name, py_object_type)
+ entry.utility_code = utility_code
+ if python_equiv:
+ if python_equiv == "*":
+ python_equiv = name
+ var_entry = Entry(python_equiv, python_equiv, py_object_type)
var_entry.is_variable = 1
var_entry.is_builtin = 1
entry.as_variable = var_entry