ExprNodes.py 365 KB
Newer Older
William Stein's avatar
William Stein committed
1
#
2
#   Parse tree nodes for expressions
William Stein's avatar
William Stein committed
3 4
#

5 6 7 8 9 10 11 12 13
import cython
cython.declare(error=object, warning=object, warn_once=object, InternalError=object,
               CompileError=object, UtilityCode=object, StringEncoding=object, operator=object,
               Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object,
               list_type=object, tuple_type=object, set_type=object, dict_type=object, \
               unicode_type=object, str_type=object, bytes_type=object, type_type=object,
               Builtin=object, Symtab=object, Utils=object, find_coercion_error=object,
               debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object)

14
import operator
William Stein's avatar
William Stein committed
15

16
from Errors import error, warning, warn_once, InternalError, CompileError
17
from Errors import hold_errors, release_errors, held_errors, report_error
18
from Code import UtilityCode
19
import StringEncoding
William Stein's avatar
William Stein committed
20
import Naming
Robert Bradshaw's avatar
Robert Bradshaw committed
21
import Nodes
William Stein's avatar
William Stein committed
22 23
from Nodes import Node
import PyrexTypes
24
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
25
     unspecified_type, cython_memoryview_ptr_type
26
import TypeSlots
27 28
from Builtin import list_type, tuple_type, set_type, dict_type, \
     unicode_type, str_type, bytes_type, type_type
29
import Builtin
William Stein's avatar
William Stein committed
30 31
import Symtab
import Options
32
from Cython import Utils
33
from Annotate import AnnotationItem
William Stein's avatar
William Stein committed
34

William Stein's avatar
William Stein committed
35
from Cython.Debugging import print_call_chain
William Stein's avatar
William Stein committed
36 37 38
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
    debug_coercion

39 40 41 42 43
try:
    from __builtin__ import basestring
except ImportError:
    basestring = str # Python 3

Stefan Behnel's avatar
Stefan Behnel committed
44 45 46 47
class NotConstant(object):
    def __repr__(self):
        return "<NOT CONSTANT>"

48
not_a_constant = NotConstant()
49
constant_value_not_set = object()
50

51 52 53 54 55 56 57 58 59 60
# error messages when coercing from key[0] to key[1]
find_coercion_error = {
    # string related errors
    (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
    (Builtin.unicode_type, Builtin.str_type)   : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
    (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
    (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
    (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
    (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
    (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
61
    (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
62 63 64 65 66
    (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
    (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
    }.get


William Stein's avatar
William Stein committed
67 68 69 70 71 72
class ExprNode(Node):
    #  subexprs     [string]     Class var holding names of subexpr node attrs
    #  type         PyrexType    Type of the result
    #  result_code  string       Code fragment
    #  result_ctype string       C type of result_code if different from type
    #  is_temp      boolean      Result is in a temporary variable
73
    #  is_sequence_constructor
William Stein's avatar
William Stein committed
74
    #               boolean      Is a list or tuple constructor expression
75
    #  is_starred   boolean      Is a starred expression (e.g. '*a')
William Stein's avatar
William Stein committed
76 77 78
    #  saved_subexpr_nodes
    #               [ExprNode or [ExprNode or None] or None]
    #                            Cached result of subexpr_nodes()
79
    #  use_managed_ref boolean   use ref-counted temps/assignments/etc.
80 81 82
    #  result_is_used  boolean   indicates that the result will be dropped and the
    #                            result_code/temp_result can safely be set to None

William Stein's avatar
William Stein committed
83
    result_ctype = None
84
    type = None
85 86
    temp_code = None
    old_temp = None # error checker for multiple frees etc.
87
    use_managed_ref = True # can be set by optimisation transforms
88
    result_is_used = True
William Stein's avatar
William Stein committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

    #  The Analyse Expressions phase for expressions is split
    #  into two sub-phases:
    #
    #    Analyse Types
    #      Determines the result type of the expression based
    #      on the types of its sub-expressions, and inserts
    #      coercion nodes into the expression tree where needed.
    #      Marks nodes which will need to have temporary variables
    #      allocated.
    #
    #    Allocate Temps
    #      Allocates temporary variables where needed, and fills
    #      in the result_code field of each node.
    #
    #  ExprNode provides some convenience routines which
    #  perform both of the above phases. These should only
    #  be called from statement nodes, and only when no
    #  coercion nodes need to be added around the expression
    #  being analysed. In that case, the above two phases
    #  should be invoked separately.
    #
    #  Framework code in ExprNode provides much of the common
    #  processing for the various phases. It makes use of the
    #  'subexprs' class attribute of ExprNodes, which should
    #  contain a list of the names of attributes which can
    #  hold sub-nodes or sequences of sub-nodes.
116 117
    #
    #  The framework makes use of a number of abstract methods.
William Stein's avatar
William Stein committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    #  Their responsibilities are as follows.
    #
    #    Declaration Analysis phase
    #
    #      analyse_target_declaration
    #        Called during the Analyse Declarations phase to analyse
    #        the LHS of an assignment or argument of a del statement.
    #        Nodes which cannot be the LHS of an assignment need not
    #        implement it.
    #
    #    Expression Analysis phase
    #
    #      analyse_types
    #        - Call analyse_types on all sub-expressions.
    #        - Check operand types, and wrap coercion nodes around
    #          sub-expressions where needed.
    #        - Set the type of this node.
    #        - If a temporary variable will be required for the
    #          result, set the is_temp flag of this node.
    #
    #      analyse_target_types
    #        Called during the Analyse Types phase to analyse
140
    #        the LHS of an assignment or argument of a del
William Stein's avatar
William Stein committed
141 142
    #        statement. Similar responsibilities to analyse_types.
    #
143 144 145 146
    #      target_code
    #        Called by the default implementation of allocate_target_temps.
    #        Should return a C lvalue for assigning to the node. The default
    #        implementation calls calculate_result_code.
William Stein's avatar
William Stein committed
147 148 149 150
    #
    #      check_const
    #        - Check that this node and its subnodes form a
    #          legal constant expression. If so, do nothing,
151
    #          otherwise call not_const.
William Stein's avatar
William Stein committed
152
    #
153
    #        The default implementation of check_const
William Stein's avatar
William Stein committed
154 155 156 157 158 159 160 161
    #        assumes that the expression is not constant.
    #
    #      check_const_addr
    #        - Same as check_const, except check that the
    #          expression is a C lvalue whose address is
    #          constant. Otherwise, call addr_not_const.
    #
    #        The default implementation of calc_const_addr
162
    #        assumes that the expression is not a constant
William Stein's avatar
William Stein committed
163 164 165 166 167 168 169 170 171 172 173 174
    #        lvalue.
    #
    #   Code Generation phase
    #
    #      generate_evaluation_code
    #        - Call generate_evaluation_code for sub-expressions.
    #        - Perform the functions of generate_result_code
    #          (see below).
    #        - If result is temporary, call generate_disposal_code
    #          on all sub-expressions.
    #
    #        A default implementation of generate_evaluation_code
175
    #        is provided which uses the following abstract methods:
William Stein's avatar
William Stein committed
176 177 178 179 180 181
    #
    #          generate_result_code
    #            - Generate any C statements necessary to calculate
    #              the result of this node from the results of its
    #              sub-expressions.
    #
182
    #          calculate_result_code
183 184
    #            - Should return a C code fragment evaluating to the
    #              result. This is only called when the result is not
185 186
    #              a temporary.
    #
William Stein's avatar
William Stein committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    #      generate_assignment_code
    #        Called on the LHS of an assignment.
    #        - Call generate_evaluation_code for sub-expressions.
    #        - Generate code to perform the assignment.
    #        - If the assignment absorbed a reference, call
    #          generate_post_assignment_code on the RHS,
    #          otherwise call generate_disposal_code on it.
    #
    #      generate_deletion_code
    #        Called on an argument of a del statement.
    #        - Call generate_evaluation_code for sub-expressions.
    #        - Generate code to perform the deletion.
    #        - Call generate_disposal_code on all sub-expressions.
    #
    #
202

William Stein's avatar
William Stein committed
203
    is_sequence_constructor = 0
204
    is_string_literal = 0
William Stein's avatar
William Stein committed
205
    is_attribute = 0
206

William Stein's avatar
William Stein committed
207 208
    saved_subexpr_nodes = None
    is_temp = 0
209
    is_target = 0
210
    is_starred = 0
William Stein's avatar
William Stein committed
211

212 213
    constant_result = constant_value_not_set

214 215 216 217
    try:
        _get_child_attrs = operator.attrgetter('subexprs')
    except AttributeError:
        # Python 2.3
218
        def __get_child_attrs(self):
219
            return self.subexprs
220
        _get_child_attrs = __get_child_attrs
221
    child_attrs = property(fget=_get_child_attrs)
222

William Stein's avatar
William Stein committed
223 224 225 226
    def not_implemented(self, method_name):
        print_call_chain(method_name, "not implemented") ###
        raise InternalError(
            "%s.%s not implemented" %
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
227
                (self.__class__.__name__, method_name))
228

William Stein's avatar
William Stein committed
229 230
    def is_lvalue(self):
        return 0
231

William Stein's avatar
William Stein committed
232 233 234 235 236 237 238 239 240 241 242
    def is_ephemeral(self):
        #  An ephemeral node is one whose result is in
        #  a Python temporary and we suspect there are no
        #  other references to it. Certain operations are
        #  disallowed on such values, since they are
        #  likely to result in a dangling pointer.
        return self.type.is_pyobject and self.is_temp

    def subexpr_nodes(self):
        #  Extract a list of subexpression nodes based
        #  on the contents of the subexprs class attribute.
243 244 245
        nodes = []
        for name in self.subexprs:
            item = getattr(self, name)
Stefan Behnel's avatar
Stefan Behnel committed
246 247
            if item is not None:
                if type(item) is list:
248
                    nodes.extend(item)
Stefan Behnel's avatar
Stefan Behnel committed
249 250
                else:
                    nodes.append(item)
251
        return nodes
252

253
    def result(self):
254 255 256
        if self.is_temp:
            return self.temp_code
        else:
257
            return self.calculate_result_code()
258

William Stein's avatar
William Stein committed
259 260
    def result_as(self, type = None):
        #  Return the result code cast to the specified C type.
261
        return typecast(type, self.ctype(), self.result())
262

William Stein's avatar
William Stein committed
263 264 265
    def py_result(self):
        #  Return the result code cast to PyObject *.
        return self.result_as(py_object_type)
266

William Stein's avatar
William Stein committed
267 268 269 270
    def ctype(self):
        #  Return the native C type of the result (i.e. the
        #  C type of the result_code expression).
        return self.result_ctype or self.type
271

272
    def get_constant_c_result_code(self):
273
        # Return the constant value of this node as a result code
274 275 276 277 278 279 280
        # string, or None if the node is not constant.  This method
        # can be called when the constant result code is required
        # before the code generation phase.
        #
        # The return value is a string that can represent a simple C
        # value, a constant C name or a constant C expression.  If the
        # node type depends on Python code, this must return None.
281 282
        return None

283
    def calculate_constant_result(self):
284 285 286 287 288
        # Calculate the constant compile time result value of this
        # expression and store it in ``self.constant_result``.  Does
        # nothing by default, thus leaving ``self.constant_result``
        # unknown.  If valid, the result can be an arbitrary Python
        # value.
289 290 291 292 293 294
        #
        # This must only be called when it is assured that all
        # sub-expressions have a valid constant_result value.  The
        # ConstantFolding transform will do this.
        pass

295 296 297 298
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

299 300 301
    def compile_time_value(self, denv):
        #  Return value of compile-time expression, or report error.
        error(self.pos, "Invalid compile-time expression")
302

303 304 305
    def compile_time_value_error(self, e):
        error(self.pos, "Error in compile-time expression: %s: %s" % (
            e.__class__.__name__, e))
306

William Stein's avatar
William Stein committed
307
    # ------------- Declaration Analysis ----------------
308

William Stein's avatar
William Stein committed
309 310
    def analyse_target_declaration(self, env):
        error(self.pos, "Cannot assign to or delete this")
311

William Stein's avatar
William Stein committed
312
    # ------------- Expression Analysis ----------------
313

William Stein's avatar
William Stein committed
314 315 316 317 318 319
    def analyse_const_expression(self, env):
        #  Called during the analyse_declarations phase of a
        #  constant expression. Analyses the expression's type,
        #  checks whether it is a legal const expression,
        #  and determines its value.
        self.analyse_types(env)
320
        return self.check_const()
321

William Stein's avatar
William Stein committed
322 323
    def analyse_expressions(self, env):
        #  Convenience routine performing both the Type
324
        #  Analysis and Temp Allocation phases for a whole
William Stein's avatar
William Stein committed
325 326
        #  expression.
        self.analyse_types(env)
327

328
    def analyse_target_expression(self, env, rhs):
William Stein's avatar
William Stein committed
329 330 331 332
        #  Convenience routine performing both the Type
        #  Analysis and Temp Allocation phases for the LHS of
        #  an assignment.
        self.analyse_target_types(env)
333

William Stein's avatar
William Stein committed
334 335 336 337 338
    def analyse_boolean_expression(self, env):
        #  Analyse expression and coerce to a boolean.
        self.analyse_types(env)
        bool = self.coerce_to_boolean(env)
        return bool
339

William Stein's avatar
William Stein committed
340 341 342 343 344 345 346 347 348
    def analyse_temp_boolean_expression(self, env):
        #  Analyse boolean expression and coerce result into
        #  a temporary. This is used when a branch is to be
        #  performed on the result and we won't have an
        #  opportunity to ensure disposal code is executed
        #  afterwards. By forcing the result into a temporary,
        #  we ensure that all disposal has been done by the
        #  time we get the result.
        self.analyse_types(env)
Stefan Behnel's avatar
Stefan Behnel committed
349 350
        return self.coerce_to_boolean(env).coerce_to_simple(env)

351
    # --------------- Type Inference -----------------
352

Robert Bradshaw's avatar
Robert Bradshaw committed
353
    def type_dependencies(self, env):
354 355 356 357
        # Returns the list of entries whose types must be determined
        # before the type of self can be infered.
        if hasattr(self, 'type') and self.type is not None:
            return ()
Robert Bradshaw's avatar
Robert Bradshaw committed
358
        return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
359

360
    def infer_type(self, env):
361 362
        # Attempt to deduce the type of self.
        # Differs from analyse_types as it avoids unnecessary
363 364 365 366 367 368 369 370
        # analysis of subexpressions, but can assume everything
        # in self.type_dependencies() has been resolved.
        if hasattr(self, 'type') and self.type is not None:
            return self.type
        elif hasattr(self, 'entry') and self.entry is not None:
            return self.entry.type
        else:
            self.not_implemented("infer_type")
371

372 373 374
    def nonlocally_immutable(self):
        # Returns whether this variable is a safe reference, i.e.
        # can't be modified as part of globals or closures.
375
        return self.is_temp or self.type.is_array or self.type.is_cfunction
376

William Stein's avatar
William Stein committed
377
    # --------------- Type Analysis ------------------
378

William Stein's avatar
William Stein committed
379 380 381 382
    def analyse_as_module(self, env):
        # If this node can be interpreted as a reference to a
        # cimported module, return its scope, else None.
        return None
383

384 385 386 387
    def analyse_as_type(self, env):
        # If this node can be interpreted as a reference to a
        # type, return that type, else None.
        return None
388

William Stein's avatar
William Stein committed
389 390 391 392
    def analyse_as_extension_type(self, env):
        # If this node can be interpreted as a reference to an
        # extension type, return its type, else None.
        return None
393

William Stein's avatar
William Stein committed
394 395
    def analyse_types(self, env):
        self.not_implemented("analyse_types")
396

William Stein's avatar
William Stein committed
397 398
    def analyse_target_types(self, env):
        self.analyse_types(env)
399

400
    def nogil_check(self, env):
401 402 403
        # By default, any expression based on Python objects is
        # prevented in nogil environments.  Subtypes must override
        # this if they can work without the GIL.
404
        if self.type and self.type.is_pyobject:
405
            self.gil_error()
406

407 408 409 410
    def gil_assignment_check(self, env):
        if env.nogil and self.type.is_pyobject:
            error(self.pos, "Assignment of Python object not allowed without gil")

William Stein's avatar
William Stein committed
411 412
    def check_const(self):
        self.not_const()
413
        return False
414

William Stein's avatar
William Stein committed
415 416
    def not_const(self):
        error(self.pos, "Not allowed in a constant expression")
417

William Stein's avatar
William Stein committed
418 419
    def check_const_addr(self):
        self.addr_not_const()
420
        return False
421

William Stein's avatar
William Stein committed
422 423
    def addr_not_const(self):
        error(self.pos, "Address is not constant")
424

William Stein's avatar
William Stein committed
425
    # ----------------- Result Allocation -----------------
426

William Stein's avatar
William Stein committed
427 428 429 430 431 432
    def result_in_temp(self):
        #  Return true if result is in a temporary owned by
        #  this node or one of its subexpressions. Overridden
        #  by certain nodes which can share the result of
        #  a subnode.
        return self.is_temp
433

William Stein's avatar
William Stein committed
434 435 436
    def target_code(self):
        #  Return code fragment for use as LHS of a C assignment.
        return self.calculate_result_code()
437

William Stein's avatar
William Stein committed
438 439
    def calculate_result_code(self):
        self.not_implemented("calculate_result_code")
440

Robert Bradshaw's avatar
Robert Bradshaw committed
441 442 443
#    def release_target_temp(self, env):
#        #  Release temporaries used by LHS of an assignment.
#        self.release_subexpr_temps(env)
William Stein's avatar
William Stein committed
444

445 446
    def allocate_temp_result(self, code):
        if self.temp_code:
447
            raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
448 449 450 451 452
        type = self.type
        if not type.is_void:
            if type.is_pyobject:
                type = PyrexTypes.py_object_type
            self.temp_code = code.funcstate.allocate_temp(
453
                type, manage_ref=self.use_managed_ref)
454 455 456 457 458
        else:
            self.temp_code = None

    def release_temp_result(self, code):
        if not self.temp_code:
459 460 461
            if not self.result_is_used:
                # not used anyway, so ignore if not set up
                return
462 463 464 465 466 467 468 469 470 471
            if self.old_temp:
                raise RuntimeError("temp %s released multiple times in %s" % (
                        self.old_temp, self.__class__.__name__))
            else:
                raise RuntimeError("no temp, but release requested in %s" % (
                        self.__class__.__name__))
        code.funcstate.release_temp(self.temp_code)
        self.old_temp = self.temp_code
        self.temp_code = None

William Stein's avatar
William Stein committed
472
    # ---------------- Code Generation -----------------
473

William Stein's avatar
William Stein committed
474 475 476 477
    def make_owned_reference(self, code):
        #  If result is a pyobject, make sure we own
        #  a reference to it.
        if self.type.is_pyobject and not self.result_in_temp():
478
            code.put_incref(self.result(), self.ctype())
479

William Stein's avatar
William Stein committed
480
    def generate_evaluation_code(self, code):
481
        code.mark_pos(self.pos)
482

William Stein's avatar
William Stein committed
483 484 485 486
        #  Generate code to evaluate this node and
        #  its sub-expressions, and dispose of any
        #  temporary results of its sub-expressions.
        self.generate_subexpr_evaluation_code(code)
487 488 489 490

        if self.is_temp:
            self.allocate_temp_result(code)

William Stein's avatar
William Stein committed
491 492
        self.generate_result_code(code)
        if self.is_temp:
493 494
            # If we are temp we do not need to wait until this node is disposed
            # before disposing children.
William Stein's avatar
William Stein committed
495
            self.generate_subexpr_disposal_code(code)
496
            self.free_subexpr_temps(code)
497

William Stein's avatar
William Stein committed
498 499 500
    def generate_subexpr_evaluation_code(self, code):
        for node in self.subexpr_nodes():
            node.generate_evaluation_code(code)
501

William Stein's avatar
William Stein committed
502 503
    def generate_result_code(self, code):
        self.not_implemented("generate_result_code")
504

505 506
    def generate_disposal_code(self, code):
        if self.is_temp:
507 508 509 510 511 512
            if self.result():
                if self.type.is_pyobject:
                    code.put_decref_clear(self.result(), self.ctype())
                elif self.type.is_memoryviewslice:
                    code.put_xdecref_memoryviewslice(
                            self.result(), have_gil=not self.in_nogil_context)
William Stein's avatar
William Stein committed
513
        else:
514
            # Already done if self.is_temp
515
            self.generate_subexpr_disposal_code(code)
516

William Stein's avatar
William Stein committed
517 518 519 520 521
    def generate_subexpr_disposal_code(self, code):
        #  Generate code to dispose of temporary results
        #  of all sub-expressions.
        for node in self.subexpr_nodes():
            node.generate_disposal_code(code)
522

William Stein's avatar
William Stein committed
523 524 525
    def generate_post_assignment_code(self, code):
        if self.is_temp:
            if self.type.is_pyobject:
526
                code.putln("%s = 0;" % self.result())
527 528 529
            elif self.type.is_memoryviewslice:
                code.putln("%s.memview = NULL;" % self.result())
                code.putln("%s.data = NULL;" % self.result())
William Stein's avatar
William Stein committed
530 531
        else:
            self.generate_subexpr_disposal_code(code)
532

William Stein's avatar
William Stein committed
533 534
    def generate_assignment_code(self, rhs, code):
        #  Stub method for nodes which are not legal as
535
        #  the LHS of an assignment. An error will have
William Stein's avatar
William Stein committed
536 537
        #  been reported earlier.
        pass
538

William Stein's avatar
William Stein committed
539 540 541 542 543
    def generate_deletion_code(self, code):
        #  Stub method for nodes that are not legal as
        #  the argument of a del statement. An error
        #  will have been reported earlier.
        pass
544 545

    def free_temps(self, code):
546 547 548 549
        if self.is_temp:
            if not self.type.is_void:
                self.release_temp_result(code)
        else:
550
            self.free_subexpr_temps(code)
551

552 553 554 555
    def free_subexpr_temps(self, code):
        for sub in self.subexpr_nodes():
            sub.free_temps(code)

556 557 558
    def generate_function_definitions(self, env, code):
        pass

559
    # ---------------- Annotation ---------------------
560

561 562 563
    def annotate(self, code):
        for node in self.subexpr_nodes():
            node.annotate(code)
564

William Stein's avatar
William Stein committed
565
    # ----------------- Coercion ----------------------
566

William Stein's avatar
William Stein committed
567 568 569 570 571 572 573 574
    def coerce_to(self, dst_type, env):
        #   Coerce the result so that it can be assigned to
        #   something of type dst_type. If processing is necessary,
        #   wraps this node in a coercion node and returns that.
        #   Otherwise, returns this node unchanged.
        #
        #   This method is called during the analyse_expressions
        #   phase of the src_node's processing.
575 576 577 578 579 580 581 582
        #
        #   Note that subclasses that override this (especially
        #   ConstNodes) must not (re-)set their own .type attribute
        #   here.  Since expression nodes may turn up in different
        #   places in the tree (e.g. inside of CloneNodes in cascaded
        #   assignments), this method must return a new node instance
        #   if it changes the type.
        #
William Stein's avatar
William Stein committed
583 584 585 586
        src = self
        src_type = self.type
        src_is_py_type = src_type.is_pyobject
        dst_is_py_type = dst_type.is_pyobject
587

588 589 590
        if self.check_for_coercion_error(dst_type):
            return self

591 592
        if dst_type.is_reference:
            dst_type = dst_type.ref_base_type
593

594 595 596 597 598
        if self.coercion_type is not None:
            # This is purely for error checking purposes!
            node = NameNode(self.pos, name='', type=self.coercion_type)
            node.coerce_to(dst_type, env)

599
        if dst_type.is_memoryviewslice:
600
            import MemoryView
601
            if not src.type.is_memoryviewslice:
602 603 604 605 606 607
                if src.type.is_pyobject:
                    src = CoerceToMemViewSliceNode(src, dst_type, env)
                else:
                    error(self.pos,
                          "Cannot convert '%s' to memoryviewslice" %
                                                                (src_type,))
608
            elif not MemoryView.src_conforms_to_dst(src.type, dst_type):
609 610 611 612 613 614 615 616
                if src.type.dtype.same_as(dst_type.dtype):
                    msg = "Memoryview '%s' not conformable to memoryview '%s'."
                    tup = src.type, dst_type
                else:
                    msg = "Different base types for memoryviews (%s, %s)"
                    tup = src.type.dtype, dst_type.dtype

                error(self.pos, msg % tup)
617

618
        elif dst_type.is_pyobject:
William Stein's avatar
William Stein committed
619
            if not src.type.is_pyobject:
620 621 622 623
                if dst_type is bytes_type and src.type.is_int:
                    src = CoerceIntToBytesNode(src, env)
                else:
                    src = CoerceToPyTypeNode(src, env)
William Stein's avatar
William Stein committed
624
            if not src.type.subtype_of(dst_type):
625 626
                if not isinstance(src, NoneNode):
                    src = PyTypeTestNode(src, dst_type, env)
William Stein's avatar
William Stein committed
627 628
        elif src.type.is_pyobject:
            src = CoerceFromPyTypeNode(dst_type, src, env)
629
        elif (dst_type.is_complex
630 631
              and src_type != dst_type
              and dst_type.assignable_from(src_type)):
632
            src = CoerceToComplexNode(src, dst_type, env)
William Stein's avatar
William Stein committed
633
        else: # neither src nor dst are py types
634
            # Added the string comparison, since for c types that
635
            # is enough, but Cython gets confused when the types are
636
            # in different pxi files.
637
            if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
638
                self.fail_assignment(dst_type)
William Stein's avatar
William Stein committed
639 640
        return src

641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
    def fail_assignment(self, dst_type):
        error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))

    def check_for_coercion_error(self, dst_type, fail=False, default=None):
        if fail and not default:
            default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
        message = find_coercion_error((self.type, dst_type), default)
        if message is not None:
            error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
            return True
        if fail:
            self.fail_assignment(dst_type)
            return True
        return False

William Stein's avatar
William Stein committed
656 657 658 659 660 661
    def coerce_to_pyobject(self, env):
        return self.coerce_to(PyrexTypes.py_object_type, env)

    def coerce_to_boolean(self, env):
        #  Coerce result to something acceptable as
        #  a boolean value.
662 663 664 665 666 667 668

        # if it's constant, calculate the result now
        if self.has_constant_result():
            bool_value = bool(self.constant_result)
            return BoolNode(self.pos, value=bool_value,
                            constant_result=bool_value)

William Stein's avatar
William Stein committed
669 670 671 672
        type = self.type
        if type.is_pyobject or type.is_ptr or type.is_float:
            return CoerceToBooleanNode(self, env)
        else:
673
            if not (type.is_int or type.is_enum or type.is_error):
674
                error(self.pos,
William Stein's avatar
William Stein committed
675 676
                    "Type '%s' not acceptable as a boolean" % type)
            return self
677

William Stein's avatar
William Stein committed
678 679 680 681 682 683
    def coerce_to_integer(self, env):
        # If not already some C integer type, coerce to longint.
        if self.type.is_int:
            return self
        else:
            return self.coerce_to(PyrexTypes.c_long_type, env)
684

William Stein's avatar
William Stein committed
685 686 687 688 689 690
    def coerce_to_temp(self, env):
        #  Ensure that the result is in a temporary.
        if self.result_in_temp():
            return self
        else:
            return CoerceToTempNode(self, env)
691

William Stein's avatar
William Stein committed
692 693 694 695 696 697
    def coerce_to_simple(self, env):
        #  Ensure that the result is simple (see is_simple).
        if self.is_simple():
            return self
        else:
            return self.coerce_to_temp(env)
698

William Stein's avatar
William Stein committed
699 700 701 702 703 704
    def is_simple(self):
        #  A node is simple if its result is something that can
        #  be referred to without performing any operations, e.g.
        #  a constant, local var, C global var, struct member
        #  reference, or temporary.
        return self.result_in_temp()
705 706

    def may_be_none(self):
707
        if self.type and not self.type.is_pyobject:
708 709 710 711
            return False
        if self.constant_result not in (not_a_constant, constant_value_not_set):
            return self.constant_result is not None
        return True
712

713
    def as_cython_attribute(self):
714
        return None
William Stein's avatar
William Stein committed
715

716
    def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()):
717 718 719
        # Wraps the node in a NoneCheckNode if it is not known to be
        # not-None (e.g. because it is a Python literal).
        if self.may_be_none():
720
            return NoneCheckNode(self, error, message, format_args)
721 722 723 724
        else:
            return self


William Stein's avatar
William Stein committed
725
class AtomicExprNode(ExprNode):
726 727
    #  Abstract base class for expression nodes which have
    #  no sub-expressions.
728

729 730 731
    subexprs = []

    # Override to optimize -- we know we have no children
732 733 734 735
    def generate_subexpr_evaluation_code(self, code):
        pass
    def generate_subexpr_disposal_code(self, code):
        pass
736

737
class PyConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
738
    #  Abstract base class for constant Python values.
739

740
    is_literal = 1
741
    type = py_object_type
742

William Stein's avatar
William Stein committed
743 744
    def is_simple(self):
        return 1
745 746 747 748

    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
749
    def analyse_types(self, env):
750
        pass
751

William Stein's avatar
William Stein committed
752 753 754 755 756 757 758 759 760
    def calculate_result_code(self):
        return self.value

    def generate_result_code(self, code):
        pass


class NoneNode(PyConstNode):
    #  The constant value None
761

762
    is_none = 1
William Stein's avatar
William Stein committed
763
    value = "Py_None"
764 765

    constant_result = None
766

767
    nogil_check = None
768

769 770
    def compile_time_value(self, denv):
        return None
771 772 773 774 775

    def may_be_none(self):
        return True


William Stein's avatar
William Stein committed
776 777
class EllipsisNode(PyConstNode):
    #  '...' in a subscript list.
778

William Stein's avatar
William Stein committed
779 780
    value = "Py_Ellipsis"

781 782
    constant_result = Ellipsis

783 784 785
    def compile_time_value(self, denv):
        return Ellipsis

William Stein's avatar
William Stein committed
786

787
class ConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
788 789 790
    # Abstract base type for literal constant nodes.
    #
    # value     string      C code fragment
791

William Stein's avatar
William Stein committed
792
    is_literal = 1
793
    nogil_check = None
794

William Stein's avatar
William Stein committed
795 796
    def is_simple(self):
        return 1
797

798 799 800
    def nonlocally_immutable(self):
        return 1

801 802 803
    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
804 805
    def analyse_types(self, env):
        pass # Types are held in class variables
806

William Stein's avatar
William Stein committed
807
    def check_const(self):
808
        return True
809

810
    def get_constant_c_result_code(self):
811 812
        return self.calculate_result_code()

William Stein's avatar
William Stein committed
813 814 815 816 817 818 819
    def calculate_result_code(self):
        return str(self.value)

    def generate_result_code(self, code):
        pass


820 821 822
class BoolNode(ConstNode):
    type = PyrexTypes.c_bint_type
    #  The constant value True or False
823 824 825 826

    def calculate_constant_result(self):
        self.constant_result = self.value

827 828
    def compile_time_value(self, denv):
        return self.value
829

830
    def calculate_result_code(self):
831
        return str(int(self.value))
832

833

William Stein's avatar
William Stein committed
834 835
class NullNode(ConstNode):
    type = PyrexTypes.c_null_ptr_type
836
    value = "NULL"
837
    constant_result = 0
William Stein's avatar
William Stein committed
838

839
    def get_constant_c_result_code(self):
840 841
        return self.value

William Stein's avatar
William Stein committed
842 843 844

class CharNode(ConstNode):
    type = PyrexTypes.c_char_type
845 846 847

    def calculate_constant_result(self):
        self.constant_result = ord(self.value)
848

849
    def compile_time_value(self, denv):
850
        return ord(self.value)
851

William Stein's avatar
William Stein committed
852
    def calculate_result_code(self):
853
        return "'%s'" % StringEncoding.escape_char(self.value)
William Stein's avatar
William Stein committed
854 855 856


class IntNode(ConstNode):
857 858 859

    # unsigned     "" or "U"
    # longness     "" or "L" or "LL"
860
    # is_c_literal   True/False/None   creator considers this a C integer literal
861 862 863

    unsigned = ""
    longness = ""
864
    is_c_literal = None # unknown
865 866 867

    def __init__(self, pos, **kwds):
        ExprNode.__init__(self, pos, **kwds)
Robert Bradshaw's avatar
Robert Bradshaw committed
868
        if 'type' not in kwds:
869 870 871 872 873 874 875 876
            self.type = self.find_suitable_type_for_value()

    def find_suitable_type_for_value(self):
        if self.constant_result is constant_value_not_set:
            try:
                self.calculate_constant_result()
            except ValueError:
                pass
877 878 879 880
        # we ignore 'is_c_literal = True' and instead map signed 32bit
        # integers as C long values
        if self.is_c_literal or \
               self.constant_result in (constant_value_not_set, not_a_constant) or \
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
               self.unsigned or self.longness == 'LL':
            # clearly a C literal
            rank = (self.longness == 'LL') and 2 or 1
            suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"]
            if self.type:
                suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type)
        else:
            # C literal or Python literal - split at 32bit boundary
            if self.constant_result >= -2**31 and self.constant_result < 2**31:
                if self.type and self.type.is_int:
                    suitable_type = self.type
                else:
                    suitable_type = PyrexTypes.c_long_type
            else:
                suitable_type = PyrexTypes.py_object_type
        return suitable_type
William Stein's avatar
William Stein committed
897

898
    def coerce_to(self, dst_type, env):
899
        if self.type is dst_type:
900
            return self
901
        elif dst_type.is_float:
902
            if self.constant_result is not not_a_constant:
903 904
                return FloatNode(self.pos, value='%d.0' % int(self.constant_result), type=dst_type,
                                 constant_result=float(self.constant_result))
905 906 907
            else:
                return FloatNode(self.pos, value=self.value, type=dst_type,
                                 constant_result=not_a_constant)
908
        if dst_type.is_numeric and not dst_type.is_complex:
909
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
910 911
                           type = dst_type, is_c_literal = True,
                           unsigned=self.unsigned, longness=self.longness)
912
            return node
913 914
        elif dst_type.is_pyobject:
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
915 916
                           type = PyrexTypes.py_object_type, is_c_literal = False,
                           unsigned=self.unsigned, longness=self.longness)
917
        else:
918 919
            # FIXME: not setting the type here to keep it working with
            # complex numbers. Should they be special cased?
920 921
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
                           unsigned=self.unsigned, longness=self.longness)
922 923 924
        # We still need to perform normal coerce_to processing on the
        # result, because we might be coercing to an extension type,
        # in which case a type test node will be needed.
925 926
        return ConstNode.coerce_to(node, dst_type, env)

927
    def coerce_to_boolean(self, env):
928 929 930 931
        return IntNode(
            self.pos, value=self.value,
            type = PyrexTypes.c_bint_type,
            unsigned=self.unsigned, longness=self.longness)
932

933
    def generate_evaluation_code(self, code):
934
        if self.type.is_pyobject:
935
            # pre-allocate a Python version of the number
936 937
            plain_integer_string = self.value_as_c_integer_string(plain_digits=True)
            self.result_code = code.get_py_num(plain_integer_string, self.longness)
938
        else:
939
            self.result_code = self.get_constant_c_result_code()
940

941
    def get_constant_c_result_code(self):
942 943 944
        return self.value_as_c_integer_string() + self.unsigned + self.longness

    def value_as_c_integer_string(self, plain_digits=False):
945 946 947 948
        value = self.value
        if isinstance(value, basestring) and len(value) > 2:
            # must convert C-incompatible Py3 oct/bin notations
            if value[1] in 'oO':
949 950 951 952
                if plain_digits:
                    value = int(value[2:], 8)
                else:
                    value = value[0] + value[2:] # '0o123' => '0123'
953 954
            elif value[1] in 'bB':
                value = int(value[2:], 2)
955 956 957
            elif plain_digits and value[1] in 'xX':
                value = int(value[2:], 16)
        return str(value)
958 959 960

    def calculate_result_code(self):
        return self.result_code
William Stein's avatar
William Stein committed
961

962
    def calculate_constant_result(self):
963
        self.constant_result = Utils.str_to_number(self.value)
964

965
    def compile_time_value(self, denv):
966
        return Utils.str_to_number(self.value)
967 968


William Stein's avatar
William Stein committed
969 970 971
class FloatNode(ConstNode):
    type = PyrexTypes.c_double_type

972
    def calculate_constant_result(self):
973
        self.constant_result = float(self.value)
974

975 976
    def compile_time_value(self, denv):
        return float(self.value)
977

Stefan Behnel's avatar
Stefan Behnel committed
978
    def calculate_result_code(self):
979 980 981 982
        strval = self.value
        assert isinstance(strval, (str, unicode))
        cmpval = repr(float(strval))
        if cmpval == 'nan':
983
            return "(Py_HUGE_VAL * 0)"
984
        elif cmpval == 'inf':
985
            return "Py_HUGE_VAL"
986
        elif cmpval == '-inf':
987
            return "(-Py_HUGE_VAL)"
Stefan Behnel's avatar
Stefan Behnel committed
988 989
        else:
            return strval
990

William Stein's avatar
William Stein committed
991

992
class BytesNode(ConstNode):
993 994 995 996
    # A char* or bytes literal
    #
    # value      BytesLiteral

997
    is_string_literal = True
998 999
    # start off as Python 'bytes' to support len() in O(1)
    type = bytes_type
1000 1001

    def compile_time_value(self, denv):
1002
        return self.value
1003

1004
    def analyse_as_type(self, env):
1005
        type = PyrexTypes.parse_basic_type(self.value)
1006
        if type is not None:
1007
            return type
1008 1009 1010 1011 1012 1013 1014
        from TreeFragment import TreeFragment
        pos = (self.pos[0], self.pos[1], self.pos[2]-7)
        declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
        sizeof_node = declaration.root.stats[0].expr
        sizeof_node.analyse_types(env)
        if isinstance(sizeof_node, SizeofTypeNode):
            return sizeof_node.arg_type
1015

1016 1017 1018
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

1019
    def coerce_to_boolean(self, env):
1020 1021
        # This is special because testing a C char* for truth directly
        # would yield the wrong result.
1022 1023
        bool_value = bool(self.value)
        return BoolNode(self.pos, value=bool_value, constant_result=bool_value)
1024

William Stein's avatar
William Stein committed
1025
    def coerce_to(self, dst_type, env):
1026 1027
        if self.type == dst_type:
            return self
1028
        if dst_type.is_int:
1029
            if not self.can_coerce_to_char_literal():
1030 1031
                error(self.pos, "Only single-character string literals can be coerced into ints.")
                return self
Stefan Behnel's avatar
Stefan Behnel committed
1032 1033
            if dst_type.is_unicode_char:
                error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.")
1034
                return self
1035 1036
            return CharNode(self.pos, value=self.value)

1037
        node = BytesNode(self.pos, value=self.value)
1038 1039 1040 1041 1042 1043 1044 1045
        if dst_type.is_pyobject:
            if dst_type in (py_object_type, Builtin.bytes_type):
                node.type = Builtin.bytes_type
            else:
                self.check_for_coercion_error(dst_type, fail=True)
                return node
        elif dst_type == PyrexTypes.c_char_ptr_type:
            node.type = dst_type
1046 1047 1048 1049
            return node
        elif dst_type == PyrexTypes.c_uchar_ptr_type:
            node.type = PyrexTypes.c_char_ptr_type
            return CastNode(node, PyrexTypes.c_uchar_ptr_type)
1050 1051
        elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
            node.type = dst_type
1052
            return node
1053

William Stein's avatar
William Stein committed
1054 1055 1056 1057 1058
        # We still need to perform normal coerce_to processing on the
        # result, because we might be coercing to an extension type,
        # in which case a type test node will be needed.
        return ConstNode.coerce_to(node, dst_type, env)

1059
    def generate_evaluation_code(self, code):
William Stein's avatar
William Stein committed
1060
        if self.type.is_pyobject:
1061
            self.result_code = code.get_py_string_const(self.value)
William Stein's avatar
William Stein committed
1062
        else:
1063
            self.result_code = code.get_string_const(self.value)
1064

1065
    def get_constant_c_result_code(self):
1066
        return None # FIXME
1067

1068 1069
    def calculate_result_code(self):
        return self.result_code
William Stein's avatar
William Stein committed
1070 1071


1072
class UnicodeNode(PyConstNode):
1073 1074
    # A Python unicode object
    #
1075 1076
    # value        EncodedString
    # bytes_value  BytesLiteral    the literal parsed as bytes string ('-3' unicode literals only)
Robert Bradshaw's avatar
Robert Bradshaw committed
1077

1078
    is_string_literal = True
1079
    bytes_value = None
1080
    type = unicode_type
1081

1082
    def coerce_to(self, dst_type, env):
1083 1084
        if dst_type is self.type:
            pass
Stefan Behnel's avatar
Stefan Behnel committed
1085
        elif dst_type.is_unicode_char:
1086
            if not self.can_coerce_to_char_literal():
Stefan Behnel's avatar
Stefan Behnel committed
1087
                error(self.pos, "Only single-character Unicode string literals or surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.")
1088 1089
                return self
            int_value = ord(self.value)
Stefan Behnel's avatar
Stefan Behnel committed
1090
            return IntNode(self.pos, type=dst_type, value=str(int_value), constant_result=int_value)
1091
        elif not dst_type.is_pyobject:
1092 1093 1094
            if dst_type.is_string and self.bytes_value is not None:
                # special case: '-3' enforced unicode literal used in a C char* context
                return BytesNode(self.pos, value=self.bytes_value).coerce_to(dst_type, env)
Stefan Behnel's avatar
Stefan Behnel committed
1095
            error(self.pos, "Unicode literals do not support coercion to C types other than Py_UNICODE or Py_UCS4.")
1096 1097 1098 1099
        elif dst_type is not py_object_type:
            if not self.check_for_coercion_error(dst_type):
                self.fail_assignment(dst_type)
        return self
1100

1101 1102
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1
Stefan Behnel's avatar
Stefan Behnel committed
1103 1104 1105
            ## or (len(self.value) == 2
            ##     and (0xD800 <= self.value[0] <= 0xDBFF)
            ##     and (0xDC00 <= self.value[1] <= 0xDFFF))
1106

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
    def contains_surrogates(self):
        # Check if the unicode string contains surrogate code points
        # on a CPython platform with wide (UCS-4) or narrow (UTF-16)
        # Unicode, i.e. characters that would be spelled as two
        # separate code units on a narrow platform.
        for c in map(ord, self.value):
            if c > 65535: # can only happen on wide platforms
                return True
            # We only look for the first code unit (D800-DBFF) of a
            # surrogate pair - if we find one, the other one
            # (DC00-DFFF) is likely there, too.  If we don't find it,
            # any second code unit cannot make for a surrogate pair by
            # itself.
            if c >= 0xD800 and c <= 0xDBFF:
                return True
        return False

1124
    def generate_evaluation_code(self, code):
1125
        self.result_code = code.get_py_string_const(self.value)
1126 1127 1128

    def calculate_result_code(self):
        return self.result_code
1129

1130 1131
    def compile_time_value(self, env):
        return self.value
1132 1133


1134 1135 1136 1137
class StringNode(PyConstNode):
    # A Python str object, i.e. a byte string in Python 2.x and a
    # unicode string in Python 3.x
    #
1138 1139
    # value          BytesLiteral (or EncodedString with ASCII content)
    # unicode_value  EncodedString or None
1140
    # is_identifier  boolean
1141

1142
    type = str_type
1143
    is_string_literal = True
1144
    is_identifier = None
1145
    unicode_value = None
1146

1147
    def coerce_to(self, dst_type, env):
1148
        if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
1149 1150 1151 1152 1153
#            if dst_type is Builtin.bytes_type:
#                # special case: bytes = 'str literal'
#                return BytesNode(self.pos, value=self.value)
            if not dst_type.is_pyobject:
                return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
1154
            self.check_for_coercion_error(dst_type, fail=True)
1155
        return self
1156

1157 1158
    def can_coerce_to_char_literal(self):
        return not self.is_identifier and len(self.value) == 1
1159

1160
    def generate_evaluation_code(self, code):
1161
        self.result_code = code.get_py_string_const(
1162 1163
            self.value, identifier=self.is_identifier, is_str=True,
            unicode_value=self.unicode_value)
1164

1165
    def get_constant_c_result_code(self):
1166 1167
        return None

1168
    def calculate_result_code(self):
1169
        return self.result_code
1170

1171 1172
    def compile_time_value(self, env):
        return self.value
1173 1174


1175 1176 1177 1178
class IdentifierStringNode(StringNode):
    # A special str value that represents an identifier (bytes in Py2,
    # unicode in Py3).
    is_identifier = True
1179 1180


1181
class LongNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1182 1183 1184
    #  Python long integer literal
    #
    #  value   string
1185

1186 1187
    type = py_object_type

1188
    def calculate_constant_result(self):
1189
        self.constant_result = Utils.str_to_number(self.value)
1190

1191
    def compile_time_value(self, denv):
1192
        return Utils.str_to_number(self.value)
1193

William Stein's avatar
William Stein committed
1194 1195
    def analyse_types(self, env):
        self.is_temp = 1
1196

1197 1198 1199
    def may_be_none(self):
        return False

1200 1201
    gil_message = "Constructing Python long int"

1202
    def generate_result_code(self, code):
William Stein's avatar
William Stein committed
1203
        code.putln(
1204
            '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1205
                self.result(),
William Stein's avatar
William Stein committed
1206
                self.value,
1207
                code.error_goto_if_null(self.result(), self.pos)))
1208
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1209 1210


1211
class ImagNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1212 1213 1214
    #  Imaginary number literal
    #
    #  value   float    imaginary part
1215

1216
    type = PyrexTypes.c_double_complex_type
1217 1218 1219

    def calculate_constant_result(self):
        self.constant_result = complex(0.0, self.value)
1220

1221 1222
    def compile_time_value(self, denv):
        return complex(0.0, self.value)
1223

William Stein's avatar
William Stein committed
1224
    def analyse_types(self, env):
1225 1226
        self.type.create_declaration_utility_code(env)

1227 1228 1229
    def may_be_none(self):
        return False

1230
    def coerce_to(self, dst_type, env):
1231 1232 1233
        if self.type is dst_type:
            return self
        node = ImagNode(self.pos, value=self.value)
1234
        if dst_type.is_pyobject:
1235 1236
            node.is_temp = 1
            node.type = PyrexTypes.py_object_type
1237 1238 1239
        # We still need to perform normal coerce_to processing on the
        # result, because we might be coercing to an extension type,
        # in which case a type test node will be needed.
1240
        return AtomicExprNode.coerce_to(node, dst_type, env)
1241 1242 1243

    gil_message = "Constructing complex number"

1244 1245 1246 1247 1248 1249
    def calculate_result_code(self):
        if self.type.is_pyobject:
            return self.result()
        else:
            return "%s(0, %r)" % (self.type.from_parts, float(self.value))

1250
    def generate_result_code(self, code):
1251 1252 1253 1254 1255 1256 1257
        if self.type.is_pyobject:
            code.putln(
                "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
                    self.result(),
                    float(self.value),
                    code.error_goto_if_null(self.result(), self.pos)))
            code.put_gotref(self.py_result())
1258

William Stein's avatar
William Stein committed
1259

Danilo Freitas's avatar
Danilo Freitas committed
1260
class NewExprNode(AtomicExprNode):
1261 1262 1263

    # C++ new statement
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1264
    # cppclass              node                 c++ class to create
1265

Robert Bradshaw's avatar
Robert Bradshaw committed
1266
    type = None
1267

1268
    def infer_type(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1269 1270
        type = self.cppclass.analyse_as_type(env)
        if type is None or not type.is_cpp_class:
Danilo Freitas's avatar
Danilo Freitas committed
1271
            error(self.pos, "new operator can only be applied to a C++ class")
Robert Bradshaw's avatar
Robert Bradshaw committed
1272
            self.type = error_type
Danilo Freitas's avatar
Danilo Freitas committed
1273
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
1274
        self.cpp_check(env)
1275
        constructor = type.scope.lookup(u'<init>')
Danilo Freitas's avatar
Danilo Freitas committed
1276
        if constructor is None:
1277 1278
            return_type = PyrexTypes.CFuncType(type, [])
            return_type = PyrexTypes.CPtrType(return_type)
1279 1280
            type.scope.declare_cfunction(u'<init>', return_type, self.pos)
            constructor = type.scope.lookup(u'<init>')
1281
        self.class_type = type
DaniloFreitas's avatar
DaniloFreitas committed
1282
        self.entry = constructor
Robert Bradshaw's avatar
Robert Bradshaw committed
1283
        self.type = constructor.type
1284
        return self.type
1285

1286
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1287 1288
        if self.type is None:
            self.infer_type(env)
1289 1290 1291 1292

    def may_be_none(self):
        return False

Danilo Freitas's avatar
Danilo Freitas committed
1293 1294
    def generate_result_code(self, code):
        pass
1295

Danilo Freitas's avatar
Danilo Freitas committed
1296
    def calculate_result_code(self):
1297
        return "new " + self.class_type.declaration_code("")
Danilo Freitas's avatar
Danilo Freitas committed
1298

William Stein's avatar
William Stein committed
1299

1300
class NameNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1301 1302 1303 1304
    #  Reference to a local or global variable name.
    #
    #  name            string    Python name of the variable
    #  entry           Entry     Symbol table entry
1305
    #  type_entry      Entry     For extension type names, the original type entry
1306 1307
    #  cf_is_null      boolean   Is uninitialized before this node
    #  cf_maybe_null   boolean   Maybe uninitialized before this node
Vitja Makarov's avatar
Vitja Makarov committed
1308
    #  allow_null      boolean   Don't raise UnboundLocalError
1309
    #  nogil           boolean   Whether it is used in a nogil context
1310

1311 1312
    is_name = True
    is_cython_module = False
Robert Bradshaw's avatar
Robert Bradshaw committed
1313
    cython_attribute = None
1314
    lhs_of_first_assignment = False # TODO: remove me
1315
    is_used_as_rvalue = 0
1316
    entry = None
1317
    type_entry = None
1318 1319
    cf_maybe_null = True
    cf_is_null = False
Vitja Makarov's avatar
Vitja Makarov committed
1320
    allow_null = False
1321
    nogil = False
1322 1323 1324 1325 1326

    def create_analysed_rvalue(pos, env, entry):
        node = NameNode(pos)
        node.analyse_types(env, entry=entry)
        return node
1327

1328
    def as_cython_attribute(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
1329
        return self.cython_attribute
1330

1331
    create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1332

Robert Bradshaw's avatar
Robert Bradshaw committed
1333 1334 1335 1336 1337 1338 1339
    def type_dependencies(self, env):
        if self.entry is None:
            self.entry = env.lookup(self.name)
        if self.entry is not None and self.entry.type.is_unspecified:
            return (self.entry,)
        else:
            return ()
1340

Robert Bradshaw's avatar
Robert Bradshaw committed
1341 1342 1343 1344 1345
    def infer_type(self, env):
        if self.entry is None:
            self.entry = env.lookup(self.name)
        if self.entry is None:
            return py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
1346 1347 1348
        elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
                self.name == self.entry.type.name:
            # Unfortunately the type attribute of type objects
1349
            # is used for the pointer to the type they represent.
Robert Bradshaw's avatar
Robert Bradshaw committed
1350
            return type_type
1351
        elif self.entry.type.is_cfunction:
Stefan Behnel's avatar
typo  
Stefan Behnel committed
1352
            # special case: referring to a C function must return its pointer
1353
            return PyrexTypes.CPtrType(self.entry.type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1354 1355
        else:
            return self.entry.type
1356

1357 1358 1359 1360
    def compile_time_value(self, denv):
        try:
            return denv.lookup(self.name)
        except KeyError:
Stefan Behnel's avatar
Stefan Behnel committed
1361
            error(self.pos, "Compile-time name '%s' not defined" % self.name)
1362 1363 1364 1365 1366

    def get_constant_c_result_code(self):
        if not self.entry or self.entry.type.is_pyobject:
            return None
        return self.entry.cname
1367

1368 1369 1370 1371 1372 1373 1374
    def coerce_to(self, dst_type, env):
        #  If coercing to a generic pyobject and this is a builtin
        #  C function with a Python equivalent, manufacture a NameNode
        #  referring to the Python builtin.
        #print "NameNode.coerce_to:", self.name, dst_type ###
        if dst_type is py_object_type:
            entry = self.entry
1375
            if entry and entry.is_cfunction:
1376 1377
                var_entry = entry.as_variable
                if var_entry:
1378
                    if var_entry.is_builtin and var_entry.is_const:
1379
                        var_entry = env.declare_builtin(var_entry.name, self.pos)
1380 1381 1382 1383
                    node = NameNode(self.pos, name = self.name)
                    node.entry = var_entry
                    node.analyse_rvalue_entry(env)
                    return node
1384

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1385
        return super(NameNode, self).coerce_to(dst_type, env)
1386

William Stein's avatar
William Stein committed
1387 1388 1389
    def analyse_as_module(self, env):
        # Try to interpret this as a reference to a cimported module.
        # Returns the module scope, or None.
1390 1391 1392
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1393 1394 1395
        if entry and entry.as_module:
            return entry.as_module
        return None
1396

1397
    def analyse_as_type(self, env):
1398 1399 1400 1401
        if self.cython_attribute:
            type = PyrexTypes.parse_basic_type(self.cython_attribute)
        else:
            type = PyrexTypes.parse_basic_type(self.name)
1402 1403
        if type:
            return type
1404 1405 1406 1407 1408 1409 1410
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
        if entry and entry.is_type:
            return entry.type
        else:
            return None
1411

William Stein's avatar
William Stein committed
1412 1413 1414
    def analyse_as_extension_type(self, env):
        # Try to interpret this as a reference to an extension type.
        # Returns the extension type, or None.
1415 1416 1417
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1418
        if entry and entry.is_type and entry.type.is_extension_type:
1419 1420 1421
            return entry.type
        else:
            return None
1422

William Stein's avatar
William Stein committed
1423
    def analyse_target_declaration(self, env):
1424 1425
        if not self.entry:
            self.entry = env.lookup_here(self.name)
William Stein's avatar
William Stein committed
1426
        if not self.entry:
1427 1428
            if env.directives['warn.undeclared']:
                warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1429
            if env.directives['infer_types'] != False:
1430 1431 1432 1433
                type = unspecified_type
            else:
                type = py_object_type
            self.entry = env.declare_var(self.name, type, self.pos)
1434 1435
        if self.entry.is_declared_generic:
            self.result_ctype = py_object_type
1436

1437
    def analyse_types(self, env):
1438
        self.initialized_check = env.directives['initializedcheck']
1439 1440
        if self.entry is None:
            self.entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1441 1442
        if not self.entry:
            self.entry = env.declare_builtin(self.name, self.pos)
1443 1444 1445
        if not self.entry:
            self.type = PyrexTypes.error_type
            return
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1446 1447 1448 1449 1450 1451 1452 1453
        entry = self.entry
        if entry:
            entry.used = 1
            if entry.type.is_buffer:
                import Buffer
                Buffer.used_buffer_aux_vars(entry)
            if entry.utility_code:
                env.use_utility_code(entry.utility_code)
1454
        self.analyse_rvalue_entry(env)
1455

1456
    def analyse_target_types(self, env):
William Stein's avatar
William Stein committed
1457
        self.analyse_entry(env)
1458 1459 1460 1461
        if not self.is_lvalue():
            error(self.pos, "Assignment to non-lvalue '%s'"
                % self.name)
            self.type = PyrexTypes.error_type
Stefan Behnel's avatar
Stefan Behnel committed
1462
        self.entry.used = 1
1463
        if self.entry.type.is_buffer:
1464 1465
            import Buffer
            Buffer.used_buffer_aux_vars(self.entry)
1466

1467 1468 1469 1470
    def analyse_rvalue_entry(self, env):
        #print "NameNode.analyse_rvalue_entry:", self.name ###
        #print "Entry:", self.entry.__dict__ ###
        self.analyse_entry(env)
1471
        entry = self.entry
1472

1473
        if entry.is_declared_generic:
William Stein's avatar
William Stein committed
1474
            self.result_ctype = py_object_type
1475

1476
        if entry.is_pyglobal or entry.is_builtin:
1477
            if entry.is_builtin and entry.is_const:
1478 1479 1480
                self.is_temp = 0
            else:
                self.is_temp = 1
1481
                env.use_utility_code(get_name_interned_utility_code)
1482

1483
            self.is_used_as_rvalue = 1
1484 1485 1486
        elif entry.type.is_memoryviewslice:
            self.is_temp = False
            self.is_used_as_rvalue = True
1487
            self.use_managed_ref = True
1488

1489
    def nogil_check(self, env):
1490
        self.nogil = True
1491 1492 1493
        if self.is_used_as_rvalue:
            entry = self.entry
            if entry.is_builtin:
1494
                if not entry.is_const: # cached builtins are ok
1495
                    self.gil_error()
1496
            elif entry.is_pyglobal:
1497
                self.gil_error()
1498 1499 1500 1501
            elif self.entry.type.is_memoryviewslice:
                if self.cf_is_null or self.cf_maybe_null:
                    import MemoryView
                    MemoryView.err_if_nogil_initialized_check(self.pos, env)
1502 1503 1504

    gil_message = "Accessing Python global or builtin"

1505 1506
    def analyse_entry(self, env):
        #print "NameNode.analyse_entry:", self.name ###
William Stein's avatar
William Stein committed
1507
        self.check_identifier_kind()
1508 1509 1510 1511
        entry = self.entry
        type = entry.type
        self.type = type

William Stein's avatar
William Stein committed
1512
    def check_identifier_kind(self):
1513 1514 1515
        # Check that this is an appropriate kind of name for use in an
        # expression.  Also finds the variable entry associated with
        # an extension type.
William Stein's avatar
William Stein committed
1516
        entry = self.entry
1517 1518
        if entry.is_type and entry.type.is_extension_type:
            self.type_entry = entry
1519
        if not (entry.is_const or entry.is_variable
Danilo Freitas's avatar
Danilo Freitas committed
1520 1521
            or entry.is_builtin or entry.is_cfunction
            or entry.is_cpp_class):
William Stein's avatar
William Stein committed
1522 1523 1524
                if self.entry.as_variable:
                    self.entry = self.entry.as_variable
                else:
1525
                    error(self.pos,
1526 1527
                          "'%s' is not a constant, variable or function identifier" % self.name)

William Stein's avatar
William Stein committed
1528 1529 1530
    def is_simple(self):
        #  If it's not a C variable, it'll be in a temp.
        return 1
1531

1532
    def may_be_none(self):
1533
        if self.cf_state and self.type and self.type.is_pyobject:
1534 1535 1536 1537 1538 1539 1540
            # gard against infinite recursion on self-dependencies
            if getattr(self, '_none_checking', False):
                # self-dependency - either this node receives a None
                # value from *another* node, or it can not reference
                # None at this point => safe to assume "not None"
                return False
            self._none_checking = True
1541 1542
            # evaluate control flow state to see if there were any
            # potential None values assigned to the node so far
1543
            may_be_none = False
1544 1545
            for assignment in self.cf_state:
                if assignment.rhs.may_be_none():
1546 1547 1548 1549
                    may_be_none = True
                    break
            del self._none_checking
            return may_be_none
1550 1551
        return super(NameNode, self).may_be_none()

1552
    def nonlocally_immutable(self):
1553 1554
        if ExprNode.nonlocally_immutable(self):
            return True
1555 1556 1557
        entry = self.entry
        return entry and (entry.is_local or entry.is_arg) and not entry.in_closure

William Stein's avatar
William Stein committed
1558 1559
    def calculate_target_results(self, env):
        pass
1560

William Stein's avatar
William Stein committed
1561 1562
    def check_const(self):
        entry = self.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
1563
        if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
William Stein's avatar
William Stein committed
1564
            self.not_const()
1565 1566
            return False
        return True
1567

William Stein's avatar
William Stein committed
1568 1569
    def check_const_addr(self):
        entry = self.entry
1570
        if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
William Stein's avatar
William Stein committed
1571
            self.addr_not_const()
1572 1573
            return False
        return True
William Stein's avatar
William Stein committed
1574 1575 1576 1577 1578

    def is_lvalue(self):
        return self.entry.is_variable and \
            not self.entry.type.is_array and \
            not self.entry.is_readonly
1579

William Stein's avatar
William Stein committed
1580 1581 1582 1583
    def is_ephemeral(self):
        #  Name nodes are never ephemeral, even if the
        #  result is in a temporary.
        return 0
1584

William Stein's avatar
William Stein committed
1585
    def calculate_result_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
1586 1587
        entry = self.entry
        if not entry:
William Stein's avatar
William Stein committed
1588
            return "<error>" # There was an error earlier
Stefan Behnel's avatar
Stefan Behnel committed
1589
        return entry.cname
1590

William Stein's avatar
William Stein committed
1591
    def generate_result_code(self, code):
1592
        assert hasattr(self, 'entry')
William Stein's avatar
William Stein committed
1593 1594 1595
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1596
        if entry.is_builtin and entry.is_const:
1597
            return # Lookup already cached
Stefan Behnel's avatar
Stefan Behnel committed
1598
        elif entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1599 1600 1601 1602 1603 1604
            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
            interned_cname = code.intern_identifier(self.entry.name)
            if entry.is_builtin:
                namespace = Naming.builtins_cname
            else: # entry.is_pyglobal
                namespace = entry.scope.namespace_cname
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
            if not self.cf_is_null:
                code.putln(
                    '%s = PyObject_GetItem(%s, %s);' % (
                        self.result(),
                        namespace,
                        interned_cname))
            if self.cf_maybe_null:
                if not self.cf_is_null:
                    code.putln('if (unlikely(!%s)) {' % self.result())
                    code.putln('PyErr_Clear();')
                code.putln(
                    '%s = __Pyx_GetName(%s, %s);' % (
                    self.result(),
                    Naming.module_cname,
                    interned_cname))
                if not self.cf_is_null:
                    code.putln("}");
            code.putln(code.error_goto_if_null(self.result(), self.pos))
Vitja Makarov's avatar
Vitja Makarov committed
1623
            code.put_gotref(self.py_result())
1624

1625
        elif entry.is_pyglobal or entry.is_builtin:
1626 1627
            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
            interned_cname = code.intern_identifier(self.entry.name)
William Stein's avatar
William Stein committed
1628 1629 1630
            if entry.is_builtin:
                namespace = Naming.builtins_cname
            else: # entry.is_pyglobal
1631
                namespace = entry.scope.namespace_cname
1632
            code.globalstate.use_utility_code(get_name_interned_utility_code)
1633 1634
            code.putln(
                '%s = __Pyx_GetName(%s, %s); %s' % (
1635
                self.result(),
1636
                namespace,
1637
                interned_cname,
1638
                code.error_goto_if_null(self.result(), self.pos)))
1639
            code.put_gotref(self.py_result())
1640

1641
        elif entry.is_local or entry.in_closure or entry.from_closure:
1642 1643 1644 1645
            # Raise UnboundLocalError for objects and memoryviewslices
            raise_unbound = (
                (self.cf_maybe_null or self.cf_is_null) and not self.allow_null)
            null_code = entry.type.check_for_null_code(entry.cname)
1646

1647 1648 1649 1650
            memslice_check = entry.type.is_memoryviewslice and self.initialized_check

            if null_code and raise_unbound and (entry.type.is_pyobject or memslice_check):
                code.put_error_if_unbound(self.pos, entry)
William Stein's avatar
William Stein committed
1651 1652

    def generate_assignment_code(self, rhs, code):
1653
        #print "NameNode.generate_assignment_code:", self.name ###
William Stein's avatar
William Stein committed
1654 1655 1656
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1657 1658 1659 1660

        if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
            and not self.lhs_of_first_assignment):
            error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1661

1662 1663
        # is_pyglobal seems to be True for module level-globals only.
        # We use this to access class->tp_dict if necessary.
William Stein's avatar
William Stein committed
1664
        if entry.is_pyglobal:
1665 1666
            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
            interned_cname = code.intern_identifier(self.entry.name)
1667
            namespace = self.entry.scope.namespace_cname
1668
            if entry.is_member:
Stefan Behnel's avatar
Stefan Behnel committed
1669
                # if the entry is a member we have to cheat: SetAttr does not work
1670
                # on types, so we create a descriptor which is then added to tp_dict
1671 1672 1673
                code.put_error_if_neg(self.pos,
                    'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
                        namespace,
1674
                        interned_cname,
1675
                        rhs.py_result()))
1676 1677
                rhs.generate_disposal_code(code)
                rhs.free_temps(code)
1678
                # in Py2.6+, we need to invalidate the method cache
1679
                code.putln("PyType_Modified(%s);" %
Vitja Makarov's avatar
Vitja Makarov committed
1680
                            entry.scope.parent_type.typeptr_cname)
Stefan Behnel's avatar
Stefan Behnel committed
1681
            elif entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1682
                code.put_error_if_neg(self.pos,
Stefan Behnel's avatar
Stefan Behnel committed
1683
                    'PyObject_SetItem(%s, %s, %s)' % (
Vitja Makarov's avatar
Vitja Makarov committed
1684 1685 1686 1687 1688 1689
                        namespace,
                        interned_cname,
                        rhs.py_result()))
                rhs.generate_disposal_code(code)
                rhs.free_temps(code)
            else:
1690 1691 1692
                code.put_error_if_neg(self.pos,
                    'PyObject_SetAttr(%s, %s, %s)' % (
                        namespace,
1693
                        interned_cname,
1694
                        rhs.py_result()))
1695
                if debug_disposal_code:
Stefan Behnel's avatar
Stefan Behnel committed
1696 1697
                    print("NameNode.generate_assignment_code:")
                    print("...generating disposal code for %s" % rhs)
1698
                rhs.generate_disposal_code(code)
1699
                rhs.free_temps(code)
William Stein's avatar
William Stein committed
1700
        else:
1701
            if self.type.is_memoryviewslice:
1702
                self.generate_acquire_memoryviewslice(rhs, code)
1703

1704
            elif self.type.is_buffer:
1705 1706 1707 1708 1709 1710 1711 1712 1713
                # Generate code for doing the buffer release/acquisition.
                # This might raise an exception in which case the assignment (done
                # below) will not happen.
                #
                # The reason this is not in a typetest-like node is because the
                # variables that the acquired buffer info is stored to is allocated
                # per entry and coupled with it.
                self.generate_acquire_buffer(rhs, code)

1714
            if self.type.is_pyobject:
William Stein's avatar
William Stein committed
1715 1716 1717 1718
                #print "NameNode.generate_assignment_code: to", self.name ###
                #print "...from", rhs ###
                #print "...LHS type", self.type, "ctype", self.ctype() ###
                #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1719 1720
                if self.use_managed_ref:
                    rhs.make_owned_reference(code)
1721
                    is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure
1722 1723 1724 1725 1726 1727
                    if is_external_ref:
                        if not self.cf_is_null:
                            if self.cf_maybe_null:
                                code.put_xgotref(self.py_result())
                            else:
                                code.put_gotref(self.py_result())
1728 1729 1730
                    if entry.is_cglobal:
                        code.put_decref(self.result(), self.ctype())
                    else:
1731 1732
                        if not self.cf_is_null:
                            if self.cf_maybe_null:
1733
                                code.put_xdecref(self.result(), self.ctype())
1734 1735
                            else:
                                code.put_decref(self.result(), self.ctype())
1736
                    if is_external_ref:
1737
                        code.put_giveref(rhs.py_result())
1738
            if not self.type.is_memoryviewslice:
1739
                code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1740 1741 1742 1743
                if debug_disposal_code:
                    print("NameNode.generate_assignment_code:")
                    print("...generating post-assignment code for %s" % rhs)
                rhs.generate_post_assignment_code(code)
1744 1745 1746
            elif rhs.result_in_temp():
                rhs.generate_post_assignment_code(code)

1747
            rhs.free_temps(code)
1748

1749 1750
    def generate_acquire_memoryviewslice(self, rhs, code):
        """
1751 1752
        Slices, coercions from objects, return values etc are new references.
        We have a borrowed reference in case of dst = src
1753 1754 1755 1756 1757 1758 1759 1760 1761
        """
        import MemoryView

        MemoryView.put_acquire_memoryviewslice(
            lhs_cname=self.result(),
            lhs_type=self.type,
            lhs_pos=self.pos,
            rhs=rhs,
            code=code,
1762
            incref_rhs=rhs.is_name,
Mark Florisson's avatar
Mark Florisson committed
1763
            have_gil=not self.in_nogil_context)
1764

1765
    def generate_acquire_buffer(self, rhs, code):
1766 1767 1768
        # rhstmp is only used in case the rhs is a complicated expression leading to
        # the object, to avoid repeating the same C expression for every reference
        # to the rhs. It does NOT hold a reference.
1769 1770 1771 1772 1773 1774 1775
        pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
        if pretty_rhs:
            rhstmp = rhs.result_as(self.ctype())
        else:
            rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
            code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))

1776
        import Buffer
1777
        Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry,
1778
                                    is_initialized=not self.lhs_of_first_assignment,
1779
                                    pos=self.pos, code=code)
1780

1781 1782 1783
        if not pretty_rhs:
            code.putln("%s = 0;" % rhstmp)
            code.funcstate.release_temp(rhstmp)
1784

William Stein's avatar
William Stein committed
1785 1786 1787
    def generate_deletion_code(self, code):
        if self.entry is None:
            return # There was an error earlier
1788
        elif self.entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1789
            namespace = self.entry.scope.namespace_cname
1790
            interned_cname = code.intern_identifier(self.entry.name)
Vitja Makarov's avatar
Vitja Makarov committed
1791
            code.put_error_if_neg(self.pos,
1792
                'PyMapping_DelItem(%s, %s)' % (
Vitja Makarov's avatar
Vitja Makarov committed
1793
                    namespace,
1794
                    interned_cname))
1795 1796 1797 1798 1799
        elif self.entry.is_pyglobal:
            code.put_error_if_neg(self.pos,
                '__Pyx_DelAttrString(%s, "%s")' % (
                    Naming.module_cname,
                    self.entry.name))
1800
        elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice:
1801 1802
            if not self.cf_is_null:
                if self.cf_maybe_null:
1803
                    code.put_error_if_unbound(self.pos, self.entry)
1804 1805 1806 1807 1808 1809 1810

                if self.entry.type.is_pyobject:
                    code.put_decref(self.result(), self.ctype())
                    code.putln('%s = NULL;' % self.result())
                else:
                    code.put_xdecref_memoryviewslice(self.entry.cname,
                                                     have_gil=not self.nogil)
Vitja Makarov's avatar
Vitja Makarov committed
1811
        else:
1812
            error(self.pos, "Deletion of C names not supported")
1813

1814 1815 1816 1817 1818 1819 1820
    def annotate(self, code):
        if hasattr(self, 'is_called') and self.is_called:
            pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
            if self.type.is_pyobject:
                code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
            else:
                code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1821

1822
class BackquoteNode(ExprNode):
William Stein's avatar
William Stein committed
1823 1824 1825
    #  `expr`
    #
    #  arg    ExprNode
1826

1827
    type = py_object_type
1828

William Stein's avatar
William Stein committed
1829
    subexprs = ['arg']
1830

William Stein's avatar
William Stein committed
1831 1832 1833 1834
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
        self.is_temp = 1
1835 1836 1837

    gil_message = "Backquote expression"

1838 1839 1840
    def calculate_constant_result(self):
        self.constant_result = repr(self.arg.constant_result)

William Stein's avatar
William Stein committed
1841 1842
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1843
            "%s = PyObject_Repr(%s); %s" % (
1844
                self.result(),
William Stein's avatar
William Stein committed
1845
                self.arg.py_result(),
1846
                code.error_goto_if_null(self.result(), self.pos)))
1847
        code.put_gotref(self.py_result())
1848

William Stein's avatar
William Stein committed
1849

1850
class ImportNode(ExprNode):
William Stein's avatar
William Stein committed
1851
    #  Used as part of import statement implementation.
1852
    #  Implements result =
Haoyu Bai's avatar
Haoyu Bai committed
1853
    #    __import__(module_name, globals(), None, name_list, level)
William Stein's avatar
William Stein committed
1854
    #
Haoyu Bai's avatar
Haoyu Bai committed
1855 1856 1857
    #  module_name   StringNode            dotted name of module. Empty module
    #                       name means importing the parent package accourding
    #                       to level
1858
    #  name_list     ListNode or None      list of names to be imported
Haoyu Bai's avatar
Haoyu Bai committed
1859 1860 1861 1862 1863
    #  level         int                   relative import level:
    #                       -1: attempt both relative import and absolute import;
    #                        0: absolute import;
    #                       >0: the number of parent directories to search
    #                           relative to the current module.
1864 1865
    #                     None: decide the level according to language level and
    #                           directives
1866

1867
    type = py_object_type
1868

William Stein's avatar
William Stein committed
1869
    subexprs = ['module_name', 'name_list']
1870

William Stein's avatar
William Stein committed
1871
    def analyse_types(self, env):
1872 1873 1874 1875 1876
        if self.level is None:
            if env.directives['language_level'] < 3 or env.directives['py2_import']:
                self.level = -1
            else:
                self.level = 0
William Stein's avatar
William Stein committed
1877 1878 1879 1880
        self.module_name.analyse_types(env)
        self.module_name = self.module_name.coerce_to_pyobject(env)
        if self.name_list:
            self.name_list.analyse_types(env)
1881
            self.name_list.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
1882 1883
        self.is_temp = 1
        env.use_utility_code(import_utility_code)
1884 1885 1886

    gil_message = "Python import"

William Stein's avatar
William Stein committed
1887 1888 1889 1890 1891 1892
    def generate_result_code(self, code):
        if self.name_list:
            name_list_code = self.name_list.py_result()
        else:
            name_list_code = "0"
        code.putln(
Haoyu Bai's avatar
Haoyu Bai committed
1893
            "%s = __Pyx_Import(%s, %s, %d); %s" % (
1894
                self.result(),
William Stein's avatar
William Stein committed
1895 1896
                self.module_name.py_result(),
                name_list_code,
Haoyu Bai's avatar
Haoyu Bai committed
1897
                self.level,
1898
                code.error_goto_if_null(self.result(), self.pos)))
1899
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1900 1901


1902
class IteratorNode(ExprNode):
William Stein's avatar
William Stein committed
1903
    #  Used as part of for statement implementation.
1904
    #
William Stein's avatar
William Stein committed
1905 1906 1907
    #  Implements result = iter(sequence)
    #
    #  sequence   ExprNode
1908

1909
    type = py_object_type
1910
    iter_func_ptr = None
1911
    counter_cname = None
1912
    reversed = False      # currently only used for list/tuple types (see Optimize.py)
1913

William Stein's avatar
William Stein committed
1914
    subexprs = ['sequence']
1915

William Stein's avatar
William Stein committed
1916 1917
    def analyse_types(self, env):
        self.sequence.analyse_types(env)
1918 1919
        if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \
                not self.sequence.type.is_string:
1920
            # C array iteration will be transformed later on
1921
            self.type = self.sequence.type
1922 1923
        else:
            self.sequence = self.sequence.coerce_to_pyobject(env)
1924 1925 1926
            if self.sequence.type is list_type or \
                   self.sequence.type is tuple_type:
                self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable")
William Stein's avatar
William Stein committed
1927
        self.is_temp = 1
1928 1929 1930

    gil_message = "Iterating over Python object"

1931 1932 1933 1934 1935
    _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
        PyrexTypes.py_object_type, [
            PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None),
            ]))

William Stein's avatar
William Stein committed
1936
    def generate_result_code(self, code):
Stefan Behnel's avatar
Stefan Behnel committed
1937 1938
        sequence_type = self.sequence.type
        if sequence_type.is_array or sequence_type.is_ptr:
1939
            raise InternalError("for in carray slice not transformed")
Stefan Behnel's avatar
Stefan Behnel committed
1940 1941
        is_builtin_sequence = sequence_type is list_type or \
                              sequence_type is tuple_type
1942 1943 1944
        if not is_builtin_sequence:
            # reversed() not currently optimised (see Optimize.py)
            assert not self.reversed, "internal error: reversed() only implemented for list/tuple objects"
Stefan Behnel's avatar
Stefan Behnel committed
1945 1946
        self.may_be_a_sequence = not sequence_type.is_builtin_type
        if self.may_be_a_sequence:
1947 1948 1949 1950
            code.putln(
                "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
                    self.sequence.py_result(),
                    self.sequence.py_result()))
Stefan Behnel's avatar
Stefan Behnel committed
1951
        if is_builtin_sequence or self.may_be_a_sequence:
1952 1953
            self.counter_cname = code.funcstate.allocate_temp(
                PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1954 1955 1956 1957 1958 1959 1960
            if self.reversed:
                if sequence_type is list_type:
                    init_value = 'PyList_GET_SIZE(%s) - 1' % self.result()
                else:
                    init_value = 'PyTuple_GET_SIZE(%s) - 1' % self.result()
            else:
                init_value = '0'
1961
            code.putln(
1962
                "%s = %s; __Pyx_INCREF(%s); %s = %s;" % (
1963 1964
                    self.result(),
                    self.sequence.py_result(),
1965 1966 1967 1968
                    self.result(),
                    self.counter_cname,
                    init_value
                    ))
1969
        if not is_builtin_sequence:
Stefan Behnel's avatar
Stefan Behnel committed
1970
            self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False)
Stefan Behnel's avatar
Stefan Behnel committed
1971
            if self.may_be_a_sequence:
Stefan Behnel's avatar
Stefan Behnel committed
1972
                code.putln("%s = NULL;" % self.iter_func_ptr)
1973
                code.putln("} else {")
1974 1975
                code.put("%s = -1; " % self.counter_cname)
            code.putln("%s = PyObject_GetIter(%s); %s" % (
1976 1977 1978
                    self.result(),
                    self.sequence.py_result(),
                    code.error_goto_if_null(self.result(), self.pos)))
1979
            code.put_gotref(self.py_result())
1980
            code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (self.iter_func_ptr, self.py_result()))
Stefan Behnel's avatar
Stefan Behnel committed
1981 1982 1983 1984
        if self.may_be_a_sequence:
            code.putln("}")

    def generate_next_sequence_item(self, test_name, result_name, code):
1985
        assert self.counter_cname, "internal error: counter_cname temp not prepared"
Stefan Behnel's avatar
Stefan Behnel committed
1986 1987 1988 1989 1990
        code.putln(
            "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
                self.counter_cname,
                test_name,
                self.py_result()))
1991 1992 1993 1994
        if self.reversed:
            inc_dec = '--'
        else:
            inc_dec = '++'
Stefan Behnel's avatar
Stefan Behnel committed
1995
        code.putln(
1996
            "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s;" % (
Stefan Behnel's avatar
Stefan Behnel committed
1997 1998 1999 2000 2001
                result_name,
                test_name,
                self.py_result(),
                self.counter_cname,
                result_name,
2002 2003
                self.counter_cname,
                inc_dec))
Stefan Behnel's avatar
Stefan Behnel committed
2004 2005 2006

    def generate_iter_next_result_code(self, result_name, code):
        sequence_type = self.sequence.type
2007 2008
        if self.reversed:
            code.putln("if (%s < 0) break;" % self.counter_cname)
Stefan Behnel's avatar
Stefan Behnel committed
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
        if sequence_type is list_type:
            self.generate_next_sequence_item('List', result_name, code)
            return
        elif sequence_type is tuple_type:
            self.generate_next_sequence_item('Tuple', result_name, code)
            return

        if self.may_be_a_sequence:
            for test_name in ('List', 'Tuple'):
                code.putln("if (Py%s_CheckExact(%s)) {" % (test_name, self.py_result()))
                self.generate_next_sequence_item(test_name, result_name, code)
                code.put("} else ")

        code.putln("{")
        code.putln(
            "%s = %s(%s);" % (
                result_name,
                self.iter_func_ptr,
                self.py_result()))
        code.putln("if (unlikely(!%s)) {" % result_name)
        code.putln("if (PyErr_Occurred()) {")
        code.putln("if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();")
        code.putln("else %s" % code.error_goto(self.pos))
        code.putln("}")
        code.putln("break;")
        code.putln("}")
        code.put_gotref(result_name)
        code.putln("}")
William Stein's avatar
William Stein committed
2037

2038
    def free_temps(self, code):
2039 2040
        if self.counter_cname:
            code.funcstate.release_temp(self.counter_cname)
2041 2042 2043 2044 2045
        if self.iter_func_ptr:
            code.funcstate.release_temp(self.iter_func_ptr)
            self.iter_func_ptr = None
        ExprNode.free_temps(self, code)

William Stein's avatar
William Stein committed
2046

2047
class NextNode(AtomicExprNode):
William Stein's avatar
William Stein committed
2048 2049 2050 2051 2052
    #  Used as part of for statement implementation.
    #  Implements result = iterator.next()
    #  Created during analyse_types phase.
    #  The iterator is not owned by this node.
    #
2053
    #  iterator   IteratorNode
2054

2055
    type = py_object_type
2056

2057
    def __init__(self, iterator):
William Stein's avatar
William Stein committed
2058 2059
        self.pos = iterator.pos
        self.iterator = iterator
2060 2061
        if iterator.type.is_ptr or iterator.type.is_array:
            self.type = iterator.type.base_type
William Stein's avatar
William Stein committed
2062
        self.is_temp = 1
2063

William Stein's avatar
William Stein committed
2064
    def generate_result_code(self, code):
Stefan Behnel's avatar
Stefan Behnel committed
2065
        self.iterator.generate_iter_next_result_code(self.result(), code)
2066

William Stein's avatar
William Stein committed
2067

2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101
class WithExitCallNode(ExprNode):
    # The __exit__() call of a 'with' statement.  Used in both the
    # except and finally clauses.

    # with_stat  WithStatNode                the surrounding 'with' statement
    # args       TupleNode or ResultStatNode the exception info tuple

    subexprs = ['args']

    def analyse_types(self, env):
        self.args.analyse_types(env)
        self.type = PyrexTypes.c_bint_type
        self.is_temp = True

    def generate_result_code(self, code):
        if isinstance(self.args, TupleNode):
            # call only if it was not already called (and decref-cleared)
            code.putln("if (%s) {" % self.with_stat.exit_var)
        result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
        code.putln("%s = PyObject_Call(%s, %s, NULL);" % (
            result_var,
            self.with_stat.exit_var,
            self.args.result()))
        code.put_decref_clear(self.with_stat.exit_var, type=py_object_type)
        code.putln(code.error_goto_if_null(result_var, self.pos))
        code.put_gotref(result_var)
        code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var))
        code.put_decref_clear(result_var, type=py_object_type)
        code.putln(code.error_goto_if_neg(self.result(), self.pos))
        code.funcstate.release_temp(result_var)
        if isinstance(self.args, TupleNode):
            code.putln("}")


2102
class ExcValueNode(AtomicExprNode):
William Stein's avatar
William Stein committed
2103 2104 2105
    #  Node created during analyse_types phase
    #  of an ExceptClauseNode to fetch the current
    #  exception value.
2106

2107
    type = py_object_type
2108

2109
    def __init__(self, pos, env):
William Stein's avatar
William Stein committed
2110
        ExprNode.__init__(self, pos)
2111 2112

    def set_var(self, var):
2113
        self.var = var
2114

2115 2116 2117
    def calculate_result_code(self):
        return self.var

William Stein's avatar
William Stein committed
2118
    def generate_result_code(self, code):
2119
        pass
William Stein's avatar
William Stein committed
2120

2121 2122 2123
    def analyse_types(self, env):
        pass

William Stein's avatar
William Stein committed
2124

2125
class TempNode(ExprNode):
2126 2127 2128 2129 2130 2131 2132
    # Node created during analyse_types phase
    # of some nodes to hold a temporary value.
    #
    # Note: One must call "allocate" and "release" on
    # the node during code generation to get/release the temp.
    # This is because the temp result is often used outside of
    # the regular cycle.
2133 2134

    subexprs = []
2135

2136
    def __init__(self, pos, type, env=None):
William Stein's avatar
William Stein committed
2137 2138 2139 2140 2141
        ExprNode.__init__(self, pos)
        self.type = type
        if type.is_pyobject:
            self.result_ctype = py_object_type
        self.is_temp = 1
2142

2143 2144
    def analyse_types(self, env):
        return self.type
2145

2146 2147 2148
    def analyse_target_declaration(self, env):
        pass

William Stein's avatar
William Stein committed
2149 2150 2151
    def generate_result_code(self, code):
        pass

2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
    def allocate(self, code):
        self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)

    def release(self, code):
        code.funcstate.release_temp(self.temp_cname)
        self.temp_cname = None

    def result(self):
        try:
            return self.temp_cname
        except:
            assert False, "Remember to call allocate/release on TempNode"
            raise

    # Do not participate in normal temp alloc/dealloc:
    def allocate_temp_result(self, code):
        pass
2169

2170 2171
    def release_temp_result(self, code):
        pass
William Stein's avatar
William Stein committed
2172 2173 2174

class PyTempNode(TempNode):
    #  TempNode holding a Python value.
2175

William Stein's avatar
William Stein committed
2176 2177 2178
    def __init__(self, pos, env):
        TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)

2179 2180
class RawCNameExprNode(ExprNode):
    subexprs = []
2181

2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
    def __init__(self, pos, type=None):
        self.pos = pos
        self.type = type

    def analyse_types(self, env):
        return self.type

    def set_cname(self, cname):
        self.cname = cname

    def result(self):
        return self.cname

    def generate_result_code(self, code):
        pass

William Stein's avatar
William Stein committed
2198

Mark Florisson's avatar
Mark Florisson committed
2199 2200 2201 2202 2203 2204 2205 2206
#-------------------------------------------------------------------
#
#  Parallel nodes (cython.parallel.thread(savailable|id))
#
#-------------------------------------------------------------------

class ParallelThreadsAvailableNode(AtomicExprNode):
    """
Mark Florisson's avatar
Mark Florisson committed
2207 2208
    Note: this is disabled and not a valid directive at this moment

Mark Florisson's avatar
Mark Florisson committed
2209 2210 2211 2212 2213 2214 2215 2216 2217
    Implements cython.parallel.threadsavailable(). If we are called from the
    sequential part of the application, we need to call omp_get_max_threads(),
    and in the parallel part we can just call omp_get_num_threads()
    """

    type = PyrexTypes.c_int_type

    def analyse_types(self, env):
        self.is_temp = True
2218
        # env.add_include_file("omp.h")
Mark Florisson's avatar
Mark Florisson committed
2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242
        return self.type

    def generate_result_code(self, code):
        code.putln("#ifdef _OPENMP")
        code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" %
                                                            self.temp_code)
        code.putln("else %s = omp_get_num_threads();" % self.temp_code)
        code.putln("#else")
        code.putln("%s = 1;" % self.temp_code)
        code.putln("#endif")

    def result(self):
        return self.temp_code


class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode):
    """
    Implements cython.parallel.threadid()
    """

    type = PyrexTypes.c_int_type

    def analyse_types(self, env):
        self.is_temp = True
2243
        # env.add_include_file("omp.h")
Mark Florisson's avatar
Mark Florisson committed
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256
        return self.type

    def generate_result_code(self, code):
        code.putln("#ifdef _OPENMP")
        code.putln("%s = omp_get_thread_num();" % self.temp_code)
        code.putln("#else")
        code.putln("%s = 0;" % self.temp_code)
        code.putln("#endif")

    def result(self):
        return self.temp_code


William Stein's avatar
William Stein committed
2257 2258 2259 2260 2261 2262
#-------------------------------------------------------------------
#
#  Trailer nodes
#
#-------------------------------------------------------------------

2263
class IndexNode(ExprNode):
William Stein's avatar
William Stein committed
2264 2265 2266 2267
    #  Sequence indexing.
    #
    #  base     ExprNode
    #  index    ExprNode
2268 2269 2270 2271 2272 2273
    #  indices  [ExprNode]
    #  is_buffer_access boolean Whether this is a buffer access.
    #
    #  indices is used on buffer access, index on non-buffer access.
    #  The former contains a clean list of index parameters, the
    #  latter whatever Python object is needed for index access.
2274

2275 2276 2277
    subexprs = ['base', 'index', 'indices']
    indices = None

2278 2279 2280 2281
    # Whether we're assigning to a buffer (in that case it needs to be
    # writable)
    writable_needed = False

2282 2283 2284 2285
    # Whether we are indexing or slicing a memoryviewslice
    memslice_index = False
    memslice_slice = False

2286 2287 2288
    def __init__(self, pos, index, *args, **kw):
        ExprNode.__init__(self, pos, index=index, *args, **kw)
        self._index = index
2289 2290 2291 2292 2293

    def calculate_constant_result(self):
        self.constant_result = \
            self.base.constant_result[self.index.constant_result]

2294 2295 2296 2297 2298 2299 2300
    def compile_time_value(self, denv):
        base = self.base.compile_time_value(denv)
        index = self.index.compile_time_value(denv)
        try:
            return base[index]
        except Exception, e:
            self.compile_time_value_error(e)
2301

William Stein's avatar
William Stein committed
2302 2303
    def is_ephemeral(self):
        return self.base.is_ephemeral()
2304

2305
    def is_simple(self):
2306
        if self.is_buffer_access or self.memslice_index:
2307
            return False
2308 2309 2310
        elif self.memslice_slice:
            return True

2311 2312 2313 2314
        base = self.base
        return (base.is_simple() and self.index.is_simple()
                and base.type and (base.type.is_ptr or base.type.is_array))

William Stein's avatar
William Stein committed
2315 2316
    def analyse_target_declaration(self, env):
        pass
2317

2318 2319 2320
    def analyse_as_type(self, env):
        base_type = self.base.analyse_as_type(env)
        if base_type and not base_type.is_pyobject:
2321
            if base_type.is_cpp_class:
2322
                if isinstance(self.index, TupleNode):
2323 2324 2325 2326 2327
                    template_values = self.index.args
                else:
                    template_values = [self.index]
                import Nodes
                type_node = Nodes.TemplatedTypeNode(
2328 2329
                    pos = self.pos,
                    positional_args = template_values,
2330 2331 2332 2333
                    keyword_args = None)
                return type_node.analyse(env, base_type = base_type)
            else:
                return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
2334
        return None
2335

Robert Bradshaw's avatar
Robert Bradshaw committed
2336
    def type_dependencies(self, env):
2337
        return self.base.type_dependencies(env) + self.index.type_dependencies(env)
2338

2339
    def infer_type(self, env):
2340 2341 2342 2343
        base_type = self.base.infer_type(env)
        if isinstance(self.index, SliceNode):
            # slicing!
            if base_type.is_string:
2344
                # sliced C strings must coerce to Python
2345
                return bytes_type
2346 2347 2348
            elif base_type in (unicode_type, bytes_type, str_type, list_type, tuple_type):
                # slicing these returns the same type
                return base_type
2349
            else:
2350 2351 2352
                # TODO: Handle buffers (hopefully without too much redundancy).
                return py_object_type

2353 2354
        index_type = self.index.infer_type(env)
        if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)):
2355 2356
            # indexing!
            if base_type is unicode_type:
2357 2358 2359
                # Py_UCS4 will automatically coerce to a unicode string
                # if required, so this is safe.  We only infer Py_UCS4
                # when the index is a C integer type.  Otherwise, we may
2360 2361 2362 2363
                # need to use normal Python item access, in which case
                # it's faster to return the one-char unicode string than
                # to receive it, throw it away, and potentially rebuild it
                # on a subsequent PyObject coercion.
2364
                return PyrexTypes.c_py_ucs4_type
2365 2366 2367
            elif base_type is str_type:
                # always returns str - Py2: bytes, Py3: unicode
                return base_type
2368 2369 2370 2371 2372 2373
            elif isinstance(self.base, BytesNode):
                #if env.global_scope().context.language_level >= 3:
                #    # infering 'char' can be made to work in Python 3 mode
                #    return PyrexTypes.c_char_type
                # Py2/3 return different types on indexing bytes objects
                return py_object_type
2374 2375
            elif base_type.is_ptr or base_type.is_array:
                return base_type.base_type
2376

2377
        # may be slicing or indexing, we don't know
2378 2379
        if base_type in (unicode_type, str_type):
            # these types always returns their own type on Python indexing/slicing
2380
            return base_type
2381 2382 2383
        else:
            # TODO: Handle buffers (hopefully without too much redundancy).
            return py_object_type
2384

William Stein's avatar
William Stein committed
2385
    def analyse_types(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2386
        self.analyse_base_and_index_types(env, getting = 1)
2387

Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2388 2389
    def analyse_target_types(self, env):
        self.analyse_base_and_index_types(env, setting = 1)
2390

2391
    def analyse_base_and_index_types(self, env, getting = 0, setting = 0, analyse_base = True):
2392 2393 2394
        # Note: This might be cleaned up by having IndexNode
        # parsed in a saner way and only construct the tuple if
        # needed.
2395 2396 2397 2398

        # Note that this function must leave IndexNode in a cloneable state.
        # For buffers, self.index is packed out on the initial analysis, and
        # when cloning self.indices is copied.
2399
        self.is_buffer_access = False
2400 2401

        # a[...] = b
2402
        self.is_memoryviewslice_access = False
2403 2404 2405 2406
        # incomplete indexing, Ellipsis indexing or slicing
        self.memslice_slice = False
        # integer indexing
        self.memslice_index = False
2407

2408 2409 2410
        if analyse_base:
            self.base.analyse_types(env)

2411 2412 2413 2414 2415
        if self.base.type.is_error:
            # Do not visit child tree if base is undeclared to avoid confusing
            # error messages
            self.type = PyrexTypes.error_type
            return
2416

2417
        is_slice = isinstance(self.index, SliceNode)
2418

2419
        # Potentially overflowing index value.
2420
        if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
2421
            self.index = self.index.coerce_to_pyobject(env)
2422

2423 2424
        is_memslice = self.base.type.is_memoryviewslice

2425
        # Handle the case where base is a literal char* (and we expect a string, not an int)
2426
        if not is_memslice and (isinstance(self.base, BytesNode) or is_slice):
Robert Bradshaw's avatar
Robert Bradshaw committed
2427
            if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array):
2428
                self.base = self.base.coerce_to_pyobject(env)
2429 2430 2431

        skip_child_analysis = False
        buffer_access = False
Mark Florisson's avatar
Mark Florisson committed
2432 2433
        memoryviewslice_access = False

2434 2435 2436 2437 2438 2439 2440
        if self.indices:
            indices = self.indices
        elif isinstance(self.index, TupleNode):
            indices = self.index.args
        else:
            indices = [self.index]

2441
        if (is_memslice and not self.indices and
Mark Florisson's avatar
Mark Florisson committed
2442
                isinstance(self.index, EllipsisNode)):
2443
            # Memoryviewslice copying
Mark Florisson's avatar
Mark Florisson committed
2444
            memoryviewslice_access = True
2445 2446 2447 2448 2449 2450

        elif is_memslice:
            # memoryviewslice indexing or slicing
            import MemoryView

            skip_child_analysis = True
2451 2452
            have_slices, indices = MemoryView.unellipsify(indices,
                                                          self.base.type.ndim)
2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471
            self.memslice_index = len(indices) == self.base.type.ndim
            axes = []

            index_type = PyrexTypes.c_py_ssize_t_type
            new_indices = []

            if len(indices) > self.base.type.ndim:
                self.type = error_type
                return error(indices[self.base.type.ndim].pos,
                             "Too many indices specified for type %s" %
                                                        self.base.type)

            suboffsets_dim = -1
            for i, index in enumerate(indices[:]):
                index.analyse_types(env)
                access, packing = self.base.type.axes[i]
                if isinstance(index, SliceNode):
                    suboffsets_dim = i
                    self.memslice_slice = True
2472 2473
                    if index.step.is_none:
                        axes.append((access, packing))
2474 2475
                    else:
                        axes.append((access, 'strided'))
2476 2477 2478 2479 2480 2481

                    # Coerce start, stop and step to temps of the right type
                    for attr in ('start', 'stop', 'step'):
                        value = getattr(index, attr)
                        if not value.is_none:
                            value = value.coerce_to(index_type, env)
2482
                            #value = value.coerce_to_temp(env)
2483 2484 2485 2486 2487
                            setattr(index, attr, value)
                            new_indices.append(value)

                elif index.type.is_int:
                    self.memslice_index = True
2488
                    index = index.coerce_to(index_type, env)
2489 2490 2491
                    indices[i] = index
                    new_indices.append(index)

2492
                    if access in ('ptr', 'generic') and i != 0 and have_slices:
2493 2494 2495 2496 2497 2498
                        self.type = error_type
                        return error(index.pos,
                                     "Indexing of non-leading indirect or generic "
                                     "dimensions not supported yet, "
                                     "try slicing with i:i+1")

2499
                else:
2500 2501
                    self.type = error_type
                    return error(index.pos, "Invalid index for memoryview specified")
2502

2503 2504
            self.memslice_index = self.memslice_index and not self.memslice_slice
            self.original_indices = indices
2505 2506
            # All indices with all start/stop/step for slices.
            # We need to keep this around
2507 2508
            self.indices = new_indices

2509 2510
            self.env = env

2511 2512
        elif self.base.type.is_buffer:
            # Buffer indexing
2513
            if len(indices) == self.base.type.ndim:
2514 2515 2516 2517 2518 2519
                buffer_access = True
                skip_child_analysis = True
                for x in indices:
                    x.analyse_types(env)
                    if not x.type.is_int:
                        buffer_access = False
2520

2521
            if buffer_access and not self.base.type.is_memoryviewslice:
Robert Bradshaw's avatar
Robert Bradshaw committed
2522
                assert hasattr(self.base, "entry") # Must be a NameNode-like node
2523

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2524 2525 2526
        # On cloning, indices is cloned. Otherwise, unpack index into indices
        assert not (buffer_access and isinstance(self.index, CloneNode))

2527 2528
        self.nogil = env.nogil

2529
        if buffer_access or self.memslice_index:
2530 2531 2532
            if self.base.type.is_memoryviewslice and not self.base.is_name:
                self.base = self.base.coerce_to_temp(env)

2533
            self.indices = indices
2534
            self.index = None
2535 2536
            self.type = self.base.type.dtype
            self.is_buffer_access = True
2537
            self.buffer_type = self.base.type #self.base.entry.type
2538 2539

            if getting and self.type.is_pyobject:
2540
                self.is_temp = True
2541 2542

            if setting and self.base.type.is_memoryviewslice:
2543
                self.base.type.writable_needed = True
2544
            elif setting:
2545 2546 2547
                if not self.base.entry.type.writable:
                    error(self.pos, "Writing to readonly buffer")
                else:
2548
                    self.writable_needed = True
2549
                    if self.base.type.is_buffer:
2550
                        self.base.entry.buffer_aux.writable_needed = True
2551

Mark Florisson's avatar
Mark Florisson committed
2552 2553 2554 2555 2556
        elif memoryviewslice_access:
            self.type = self.base.type
            self.is_memoryviewslice_access = True
            if getting:
                error(self.pos, "memoryviews currently support setting only.")
2557

2558
        elif self.memslice_slice:
2559
            self.index = None
2560
            self.is_temp = True
2561
            self.use_managed_ref = True
2562 2563 2564
            self.type = PyrexTypes.MemoryViewSliceType(
                            self.base.type.dtype, axes)

2565
        else:
2566
            base_type = self.base.type
2567 2568 2569 2570
            if isinstance(self.index, TupleNode):
                self.index.analyse_types(env, skip_children=skip_child_analysis)
            elif not skip_child_analysis:
                self.index.analyse_types(env)
2571
            self.original_index_type = self.index.type
Stefan Behnel's avatar
Stefan Behnel committed
2572 2573
            if base_type.is_unicode_char:
                # we infer Py_UNICODE/Py_UCS4 for unicode strings in some
2574 2575 2576 2577 2578 2579 2580
                # cases, but indexing must still work for them
                if self.index.constant_result in (0, -1):
                    # FIXME: we know that this node is redundant -
                    # currently, this needs to get handled in Optimize.py
                    pass
                self.base = self.base.coerce_to_pyobject(env)
                base_type = self.base.type
2581
            if base_type.is_pyobject:
2582
                if self.index.type.is_int:
2583
                    if (not setting
2584
                        and (base_type in (list_type, tuple_type, unicode_type))
2585 2586 2587
                        and (not self.index.type.signed
                             or not env.directives['wraparound']
                             or isinstance(self.index, IntNode) and int(self.index.value) >= 0)
2588 2589 2590 2591
                        and not env.directives['boundscheck']):
                        self.is_temp = 0
                    else:
                        self.is_temp = 1
2592 2593 2594
                    self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
                else:
                    self.index = self.index.coerce_to_pyobject(env)
2595
                    self.is_temp = 1
2596
                if self.index.type.is_int and base_type is unicode_type:
Stefan Behnel's avatar
Stefan Behnel committed
2597
                    # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string
2598
                    # if required, so this is fast and safe
2599
                    self.type = PyrexTypes.c_py_ucs4_type
2600 2601
                elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type):
                    self.type = base_type
2602 2603
                else:
                    self.type = py_object_type
William Stein's avatar
William Stein committed
2604
            else:
2605 2606
                if base_type.is_ptr or base_type.is_array:
                    self.type = base_type.base_type
2607 2608 2609
                    if is_slice:
                        self.type = base_type
                    elif self.index.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
2610 2611
                        self.index = self.index.coerce_to(
                            PyrexTypes.c_py_ssize_t_type, env)
2612
                    elif not self.index.type.is_int:
Robert Bradshaw's avatar
Robert Bradshaw committed
2613 2614 2615
                        error(self.pos,
                            "Invalid index type '%s'" %
                                self.index.type)
2616
                elif base_type.is_cpp_class:
2617
                    function = env.lookup_operator("[]", [self.base, self.index])
Robert Bradshaw's avatar
Robert Bradshaw committed
2618
                    if function is None:
2619
                        error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
2620 2621 2622 2623 2624 2625 2626 2627 2628
                        self.type = PyrexTypes.error_type
                        self.result_code = "<error>"
                        return
                    func_type = function.type
                    if func_type.is_ptr:
                        func_type = func_type.base_type
                    self.index = self.index.coerce_to(func_type.args[0].type, env)
                    self.type = func_type.return_type
                    if setting and not func_type.return_type.is_reference:
Robert Bradshaw's avatar
Robert Bradshaw committed
2629
                        error(self.pos, "Can't set non-reference result '%s'" % self.type)
2630 2631 2632
                else:
                    error(self.pos,
                        "Attempting to index non-array type '%s'" %
2633
                            base_type)
2634
                    self.type = PyrexTypes.error_type
Stefan Behnel's avatar
Stefan Behnel committed
2635

2636 2637
    gil_message = "Indexing Python object"

2638
    def nogil_check(self, env):
2639 2640
        if self.is_buffer_access or self.memslice_index or self.memslice_slice:
            if not self.memslice_slice and env.directives['boundscheck']:
2641 2642 2643 2644 2645
                error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
                return
            elif self.type.is_pyobject:
                error(self.pos, "Cannot access buffer with object dtype without gil")
                return
2646
        super(IndexNode, self).nogil_check(env)
2647 2648


William Stein's avatar
William Stein committed
2649
    def check_const_addr(self):
2650
        return self.base.check_const_addr() and self.index.check_const()
2651

William Stein's avatar
William Stein committed
2652 2653
    def is_lvalue(self):
        return 1
Dag Sverre Seljebotn's avatar
merge  
Dag Sverre Seljebotn committed
2654

William Stein's avatar
William Stein committed
2655
    def calculate_result_code(self):
2656
        if self.is_buffer_access:
2657
            return "(*%s)" % self.buffer_ptr_code
2658 2659 2660 2661
        elif self.base.type is list_type:
            return "PyList_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
        elif self.base.type is tuple_type:
            return "PyTuple_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
Stefan Behnel's avatar
Stefan Behnel committed
2662
        elif self.base.type is unicode_type and self.type.is_unicode_char:
2663
            return "__Pyx_PyUnicode_READ_CHAR(%s, %s)" % (self.base.result(), self.index.result())
2664 2665
        elif (self.type.is_ptr or self.type.is_array) and self.type == self.base.type:
            error(self.pos, "Invalid use of pointer slice")
2666 2667
        else:
            return "(%s[%s])" % (
2668
                self.base.result(), self.index.result())
2669

2670
    def extra_index_params(self):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2671 2672
        if self.index.type.is_int:
            if self.original_index_type.signed:
2673
                size_adjustment = ""
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2674
            else:
2675 2676
                size_adjustment = "+1"
            return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2677 2678
        else:
            return ""
2679 2680 2681

    def generate_subexpr_evaluation_code(self, code):
        self.base.generate_evaluation_code(code)
2682
        if not self.indices:
2683 2684
            self.index.generate_evaluation_code(code)
        else:
2685 2686
            for i in self.indices:
                i.generate_evaluation_code(code)
2687

2688 2689
    def generate_subexpr_disposal_code(self, code):
        self.base.generate_disposal_code(code)
2690
        if not self.indices:
2691 2692
            self.index.generate_disposal_code(code)
        else:
2693 2694
            for i in self.indices:
                i.generate_disposal_code(code)
2695

2696 2697 2698 2699 2700 2701 2702 2703
    def free_subexpr_temps(self, code):
        self.base.free_temps(code)
        if not self.indices:
            self.index.free_temps(code)
        else:
            for i in self.indices:
                i.free_temps(code)

William Stein's avatar
William Stein committed
2704
    def generate_result_code(self, code):
2705
        if self.is_buffer_access or self.memslice_index:
2706 2707
            if code.globalstate.directives['nonecheck']:
                self.put_nonecheck(code)
2708
            buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code)
2709 2710 2711
            if self.type.is_pyobject:
                # is_temp is True, so must pull out value and incref it.
                code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2712
                code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2713 2714 2715 2716

        elif self.memslice_slice:
            self.put_memoryviewslice_slice_code(code)

2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727
        elif self.is_temp:
            if self.type.is_pyobject:
                if self.index.type.is_int:
                    index_code = self.index.result()
                    if self.base.type is list_type:
                        function = "__Pyx_GetItemInt_List"
                    elif self.base.type is tuple_type:
                        function = "__Pyx_GetItemInt_Tuple"
                    else:
                        function = "__Pyx_GetItemInt"
                    code.globalstate.use_utility_code(getitem_int_utility_code)
2728
                else:
2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744
                    index_code = self.index.py_result()
                    if self.base.type is dict_type:
                        function = "__Pyx_PyDict_GetItem"
                        code.globalstate.use_utility_code(getitem_dict_utility_code)
                    else:
                        function = "PyObject_GetItem"
                code.putln(
                    "%s = %s(%s, %s%s); if (!%s) %s" % (
                        self.result(),
                        function,
                        self.base.py_result(),
                        index_code,
                        self.extra_index_params(),
                        self.result(),
                        code.error_goto(self.pos)))
                code.put_gotref(self.py_result())
Stefan Behnel's avatar
Stefan Behnel committed
2745
            elif self.type.is_unicode_char and self.base.type is unicode_type:
2746 2747 2748
                assert self.index.type.is_int
                index_code = self.index.result()
                function = "__Pyx_GetItemInt_Unicode"
2749 2750
                code.globalstate.use_utility_code(getitem_int_pyunicode_utility_code)
                code.putln(
2751
                    "%s = %s(%s, %s%s); if (unlikely(%s == (Py_UCS4)-1)) %s;" % (
2752 2753 2754 2755 2756 2757 2758
                        self.result(),
                        function,
                        self.base.py_result(),
                        index_code,
                        self.extra_index_params(),
                        self.result(),
                        code.error_goto(self.pos)))
2759

Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2760 2761 2762
    def generate_setitem_code(self, value_code, code):
        if self.index.type.is_int:
            function = "__Pyx_SetItemInt"
2763
            index_code = self.index.result()
2764
            code.globalstate.use_utility_code(setitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2765 2766
        else:
            index_code = self.index.py_result()
2767 2768
            if self.base.type is dict_type:
                function = "PyDict_SetItem"
Craig Citro's avatar
Craig Citro committed
2769
            # It would seem that we could specialized lists/tuples, but that
2770 2771 2772 2773 2774 2775
            # shouldn't happen here.
            # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
            # not a PyObject*, and bad conversion here would give the wrong
            # exception. Also, tuples are supposed to be immutable, and raise
            # TypeErrors when trying to set their entries (PyTuple_SetItem
            # is for creating new tuples from).
2776 2777
            else:
                function = "PyObject_SetItem"
2778
        code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2779 2780
            "if (%s(%s, %s, %s%s) < 0) %s" % (
                function,
2781
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2782 2783
                index_code,
                value_code,
2784
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2785
                code.error_goto(self.pos)))
2786

2787
    def generate_memoryviewslice_copy_code(self, rhs, code, op=""):
2788 2789 2790 2791 2792 2793 2794
        assert isinstance(self.index, EllipsisNode)
        import MemoryView
        util_code = MemoryView.CopyContentsFuncUtilCode(rhs.type, self.type)
        func_name = util_code.copy_contents_name
        code.putln(code.error_goto_if_neg("%s(&%s, &%s)" % (func_name, rhs.result(), self.base.result()), self.pos))
        code.globalstate.use_utility_code(util_code)

2795 2796
    def generate_buffer_setitem_code(self, rhs, code, op=""):
        # Used from generate_assignment_code and InPlaceAssignmentNode
2797
        if code.globalstate.directives['nonecheck'] and not self.memslice_index:
2798
            self.put_nonecheck(code)
2799 2800 2801

        buffer_entry, ptrexpr = self.buffer_lookup_code(code)

2802 2803 2804
        if self.buffer_type.dtype.is_pyobject:
            # Must manage refcounts. Decref what is already there
            # and incref what we put in.
2805 2806
            ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type,
                                               manage_ref=False)
2807
            rhs_code = rhs.result()
2808
            code.putln("%s = %s;" % (ptr, ptrexpr))
2809
            code.put_gotref("*%s" % ptr)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2810
            code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2811 2812 2813
                ptr, rhs_code
                ))
            code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2814
            code.put_giveref("*%s" % ptr)
2815
            code.funcstate.release_temp(ptr)
2816
        else:
2817
            # Simple case
2818
            code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2819

William Stein's avatar
William Stein committed
2820 2821
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2822
        if self.is_buffer_access or self.memslice_index:
2823
            self.generate_buffer_setitem_code(rhs, code)
2824 2825 2826
        elif self.memslice_slice:
            error(rhs.pos, "Slice assignment not supported yet")
            #self.generate_memoryviewslice_setslice_code(rhs, code)
2827
        elif self.is_memoryviewslice_access:
2828
            self.generate_memoryviewslice_copy_code(rhs, code)
2829
        elif self.type.is_pyobject:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2830
            self.generate_setitem_code(rhs.py_result(), code)
William Stein's avatar
William Stein committed
2831 2832 2833
        else:
            code.putln(
                "%s = %s;" % (
2834
                    self.result(), rhs.result()))
2835
        self.generate_subexpr_disposal_code(code)
2836
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2837
        rhs.generate_disposal_code(code)
2838
        rhs.free_temps(code)
2839

William Stein's avatar
William Stein committed
2840 2841
    def generate_deletion_code(self, code):
        self.generate_subexpr_evaluation_code(code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2842 2843
        #if self.type.is_pyobject:
        if self.index.type.is_int:
2844
            function = "__Pyx_DelItemInt"
2845
            index_code = self.index.result()
2846
            code.globalstate.use_utility_code(delitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2847 2848
        else:
            index_code = self.index.py_result()
2849 2850 2851 2852
            if self.base.type is dict_type:
                function = "PyDict_DelItem"
            else:
                function = "PyObject_DelItem"
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2853
        code.putln(
2854
            "if (%s(%s, %s%s) < 0) %s" % (
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2855
                function,
William Stein's avatar
William Stein committed
2856
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2857
                index_code,
2858
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2859
                code.error_goto(self.pos)))
William Stein's avatar
William Stein committed
2860
        self.generate_subexpr_disposal_code(code)
2861
        self.free_subexpr_temps(code)
2862

2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879
    def buffer_entry(self):
        import Buffer, MemoryView

        if self.base.is_name:
            entry = self.base.entry
        else:
            assert self.base.is_temp
            cname = self.base.result()
            entry = Symtab.Entry(cname, cname, self.base.type, self.base.pos)

        if entry.type.is_buffer:
            buffer_entry = Buffer.BufferEntry(entry)
        else:
            buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry)

        return buffer_entry

2880
    def buffer_lookup_code(self, code):
2881
        # Assign indices to temps
2882 2883 2884
        index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False)
                           for i in self.indices]

2885
        for temp, index in zip(index_temps, self.indices):
2886
            code.putln("%s = %s;" % (temp, index.result()))
2887

2888
        # Generate buffer access code using these temps
2889
        import Buffer, MemoryView
2890

2891
        buffer_entry = self.buffer_entry()
2892

2893
        if buffer_entry.type.is_buffer:
2894
            negative_indices = buffer_entry.type.negative_indices
2895 2896 2897
        else:
            negative_indices = Buffer.buffer_defaults['negative_indices']

2898 2899 2900 2901 2902 2903 2904
        return buffer_entry, Buffer.put_buffer_lookup_code(
               entry=buffer_entry,
               index_signeds=[i.type.signed for i in self.indices],
               index_cnames=index_temps,
               directives=code.globalstate.directives,
               pos=self.pos, code=code,
               negative_indices=negative_indices)
William Stein's avatar
William Stein committed
2905

2906 2907
    def put_memoryviewslice_slice_code(self, code):
        buffer_entry = self.buffer_entry()
2908
        have_gil = not self.in_nogil_context
2909 2910
        buffer_entry.generate_buffer_slice_code(code,
                                                self.original_indices,
2911
                                                self.result(),
2912
                                                have_gil=have_gil)
2913

2914 2915 2916 2917 2918 2919 2920
    def put_nonecheck(self, code):
        code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
        code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
        code.putln("__Pyx_RaiseNoneIndexingError();")
        code.putln(code.error_goto(self.pos))
        code.putln("}")

2921

2922
class SliceIndexNode(ExprNode):
William Stein's avatar
William Stein committed
2923 2924 2925 2926 2927
    #  2-element slice indexing
    #
    #  base      ExprNode
    #  start     ExprNode or None
    #  stop      ExprNode or None
2928

William Stein's avatar
William Stein committed
2929
    subexprs = ['base', 'start', 'stop']
2930

2931 2932 2933 2934 2935 2936 2937
    def infer_type(self, env):
        base_type = self.base.infer_type(env)
        if base_type.is_string:
            return bytes_type
        elif base_type in (bytes_type, str_type, unicode_type,
                           list_type, tuple_type):
            return base_type
2938 2939
        elif base_type.is_ptr or base_type.is_array:
            return PyrexTypes.c_array_type(base_type.base_type, None)
2940 2941
        return py_object_type

2942 2943 2944 2945
    def calculate_constant_result(self):
        self.constant_result = self.base.constant_result[
            self.start.constant_result : self.stop.constant_result]

2946 2947
    def compile_time_value(self, denv):
        base = self.base.compile_time_value(denv)
2948 2949 2950 2951 2952 2953 2954 2955
        if self.start is None:
            start = 0
        else:
            start = self.start.compile_time_value(denv)
        if self.stop is None:
            stop = None
        else:
            stop = self.stop.compile_time_value(denv)
2956 2957 2958 2959
        try:
            return base[start:stop]
        except Exception, e:
            self.compile_time_value_error(e)
2960

William Stein's avatar
William Stein committed
2961 2962
    def analyse_target_declaration(self, env):
        pass
2963

2964
    def analyse_target_types(self, env):
2965
        self.analyse_types(env, getting=False)
2966
        # when assigning, we must accept any Python type
2967 2968
        if self.type.is_pyobject:
            self.type = py_object_type
William Stein's avatar
William Stein committed
2969

2970
    def analyse_types(self, env, getting=True):
William Stein's avatar
William Stein committed
2971
        self.base.analyse_types(env)
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991

        if self.base.type.is_memoryviewslice:
            # Gross hack here! But we do not know the type until this point,
            # and we cannot create and return a new node. So we change the
            # type...
            none_node = NoneNode(self.pos)
            index = SliceNode(self.pos,
                              start=self.start or none_node,
                              stop=self.stop or none_node,
                              step=none_node)
            del self.start
            del self.stop
            self.index = index
            self.__class__ = IndexNode
            self.analyse_base_and_index_types(env,
                                              getting=getting,
                                              setting=not getting,
                                              analyse_base=False)
            return

William Stein's avatar
William Stein committed
2992 2993 2994 2995
        if self.start:
            self.start.analyse_types(env)
        if self.stop:
            self.stop.analyse_types(env)
2996 2997 2998
        base_type = self.base.type
        if base_type.is_string:
            self.type = bytes_type
2999 3000 3001
        elif base_type.is_ptr:
            self.type = base_type
        elif base_type.is_array:
3002 3003 3004
            # we need a ptr type here instead of an array type, as
            # array types can result in invalid type casts in the C
            # code
3005
            self.type = PyrexTypes.CPtrType(base_type.base_type)
3006 3007 3008
        else:
            self.base = self.base.coerce_to_pyobject(env)
            self.type = py_object_type
3009 3010 3011
        if base_type.is_builtin_type:
            # slicing builtin types returns something of the same type
            self.type = base_type
3012
        c_int = PyrexTypes.c_py_ssize_t_type
William Stein's avatar
William Stein committed
3013 3014 3015 3016 3017
        if self.start:
            self.start = self.start.coerce_to(c_int, env)
        if self.stop:
            self.stop = self.stop.coerce_to(c_int, env)
        self.is_temp = 1
3018

3019
    nogil_check = Node.gil_error
3020 3021
    gil_message = "Slicing Python object"

William Stein's avatar
William Stein committed
3022
    def generate_result_code(self, code):
3023 3024 3025 3026
        if not self.type.is_pyobject:
            error(self.pos,
                  "Slicing is not currently supported for '%s'." % self.type)
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
3027 3028 3029
        if self.base.type.is_string:
            if self.stop is None:
                code.putln(
3030
                    "%s = PyBytes_FromString(%s + %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
3031 3032 3033 3034 3035 3036
                        self.result(),
                        self.base.result(),
                        self.start_code(),
                        code.error_goto_if_null(self.result(), self.pos)))
            else:
                code.putln(
3037
                    "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
3038 3039 3040 3041 3042 3043 3044 3045
                        self.result(),
                        self.base.result(),
                        self.start_code(),
                        self.stop_code(),
                        self.start_code(),
                        code.error_goto_if_null(self.result(), self.pos)))
        else:
            code.putln(
3046
                "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
3047 3048 3049 3050 3051
                    self.result(),
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
                    code.error_goto_if_null(self.result(), self.pos)))
3052
        code.put_gotref(self.py_result())
3053

William Stein's avatar
William Stein committed
3054 3055
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
3056
        if self.type.is_pyobject:
3057
            code.put_error_if_neg(self.pos,
3058
                "__Pyx_PySequence_SetSlice(%s, %s, %s, %s)" % (
3059 3060 3061
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
Lisandro Dalcin's avatar
Lisandro Dalcin committed
3062
                    rhs.py_result()))
3063 3064 3065 3066 3067 3068 3069 3070
        else:
            start_offset = ''
            if self.start:
                start_offset = self.start_code()
                if start_offset == '0':
                    start_offset = ''
                else:
                    start_offset += '+'
Stefan Behnel's avatar
Stefan Behnel committed
3071 3072
            if rhs.type.is_array:
                array_length = rhs.type.size
3073
                self.generate_slice_guard_code(code, array_length)
Stefan Behnel's avatar
Stefan Behnel committed
3074
            else:
Stefan Behnel's avatar
Stefan Behnel committed
3075 3076
                error(self.pos,
                      "Slice assignments from pointers are not yet supported.")
Stefan Behnel's avatar
Stefan Behnel committed
3077 3078
                # FIXME: fix the array size according to start/stop
                array_length = self.base.type.size
3079 3080 3081 3082
            for i in range(array_length):
                code.putln("%s[%s%s] = %s[%d];" % (
                        self.base.result(), start_offset, i,
                        rhs.result(), i))
William Stein's avatar
William Stein committed
3083
        self.generate_subexpr_disposal_code(code)
3084
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
3085
        rhs.generate_disposal_code(code)
3086
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
3087 3088

    def generate_deletion_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3089
        if not self.base.type.is_pyobject:
3090 3091 3092
            error(self.pos,
                  "Deleting slices is only supported for Python types, not '%s'." % self.type)
            return
William Stein's avatar
William Stein committed
3093
        self.generate_subexpr_evaluation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3094
        code.put_error_if_neg(self.pos,
3095
            "__Pyx_PySequence_DelSlice(%s, %s, %s)" % (
William Stein's avatar
William Stein committed
3096 3097
                self.base.py_result(),
                self.start_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3098
                self.stop_code()))
William Stein's avatar
William Stein committed
3099
        self.generate_subexpr_disposal_code(code)
3100
        self.free_subexpr_temps(code)
3101 3102 3103 3104 3105 3106 3107 3108 3109 3110

    def generate_slice_guard_code(self, code, target_size):
        if not self.base.type.is_array:
            return
        slice_size = self.base.type.size
        start = stop = None
        if self.stop:
            stop = self.stop.result()
            try:
                stop = int(stop)
Stefan Behnel's avatar
Stefan Behnel committed
3111
                if stop < 0:
3112
                    slice_size = self.base.type.size + stop
Stefan Behnel's avatar
Stefan Behnel committed
3113 3114
                else:
                    slice_size = stop
3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144
                stop = None
            except ValueError:
                pass
        if self.start:
            start = self.start.result()
            try:
                start = int(start)
                if start < 0:
                    start = self.base.type.size + start
                slice_size -= start
                start = None
            except ValueError:
                pass
        check = None
        if slice_size < 0:
            if target_size > 0:
                error(self.pos, "Assignment to empty slice.")
        elif start is None and stop is None:
            # we know the exact slice length
            if target_size != slice_size:
                error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
                        slice_size, target_size))
        elif start is not None:
            if stop is None:
                stop = slice_size
            check = "(%s)-(%s)" % (stop, start)
        else: # stop is not None:
            check = stop
        if check:
            code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
3145
            code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
3146 3147 3148
                        target_size, check))
            code.putln(code.error_goto(self.pos))
            code.putln("}")
3149

William Stein's avatar
William Stein committed
3150 3151
    def start_code(self):
        if self.start:
3152
            return self.start.result()
William Stein's avatar
William Stein committed
3153 3154
        else:
            return "0"
3155

William Stein's avatar
William Stein committed
3156 3157
    def stop_code(self):
        if self.stop:
3158
            return self.stop.result()
3159 3160
        elif self.base.type.is_array:
            return self.base.type.size
William Stein's avatar
William Stein committed
3161
        else:
3162
            return "PY_SSIZE_T_MAX"
3163

William Stein's avatar
William Stein committed
3164
    def calculate_result_code(self):
3165
        # self.result() is not used, but this method must exist
William Stein's avatar
William Stein committed
3166
        return "<unused>"
3167

William Stein's avatar
William Stein committed
3168

3169
class SliceNode(ExprNode):
William Stein's avatar
William Stein committed
3170 3171 3172 3173 3174
    #  start:stop:step in subscript list
    #
    #  start     ExprNode
    #  stop      ExprNode
    #  step      ExprNode
3175

3176 3177
    subexprs = ['start', 'stop', 'step']

3178 3179
    type = py_object_type
    is_temp = 1
3180 3181

    def calculate_constant_result(self):
3182 3183 3184 3185
        self.constant_result = slice(
            self.start.constant_result,
            self.stop.constant_result,
            self.step.constant_result)
3186

3187 3188
    def compile_time_value(self, denv):
        start = self.start.compile_time_value(denv)
Stefan Behnel's avatar
Stefan Behnel committed
3189 3190
        stop = self.stop.compile_time_value(denv)
        step = self.step.compile_time_value(denv)
3191 3192 3193 3194 3195
        try:
            return slice(start, stop, step)
        except Exception, e:
            self.compile_time_value_error(e)

William Stein's avatar
William Stein committed
3196 3197 3198 3199 3200 3201 3202
    def analyse_types(self, env):
        self.start.analyse_types(env)
        self.stop.analyse_types(env)
        self.step.analyse_types(env)
        self.start = self.start.coerce_to_pyobject(env)
        self.stop = self.stop.coerce_to_pyobject(env)
        self.step = self.step.coerce_to_pyobject(env)
3203 3204 3205
        if self.start.is_literal and self.stop.is_literal and self.step.is_literal:
            self.is_literal = True
            self.is_temp = False
3206 3207 3208

    gil_message = "Constructing Python slice object"

3209 3210 3211
    def calculate_result_code(self):
        return self.result_code

William Stein's avatar
William Stein committed
3212
    def generate_result_code(self, code):
3213 3214 3215 3216 3217
        if self.is_literal:
            self.result_code = code.get_py_const(py_object_type, 'slice_', cleanup_level=2)
            code = code.get_cached_constants_writer()
            code.mark_pos(self.pos)

William Stein's avatar
William Stein committed
3218
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3219
            "%s = PySlice_New(%s, %s, %s); %s" % (
3220
                self.result(),
3221 3222
                self.start.py_result(),
                self.stop.py_result(),
William Stein's avatar
William Stein committed
3223
                self.step.py_result(),
3224
                code.error_goto_if_null(self.result(), self.pos)))
3225
        code.put_gotref(self.py_result())
3226 3227
        if self.is_literal:
            code.put_giveref(self.py_result())
William Stein's avatar
William Stein committed
3228

3229

3230
class CallNode(ExprNode):
3231

Stefan Behnel's avatar
Stefan Behnel committed
3232 3233 3234
    # allow overriding the default 'may_be_none' behaviour
    may_return_none = None

3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255
    def infer_type(self, env):
        function = self.function
        func_type = function.infer_type(env)
        if isinstance(self.function, NewExprNode):
            return PyrexTypes.CPtrType(self.function.class_type)
        if func_type.is_ptr:
            func_type = func_type.base_type
        if func_type.is_cfunction:
            return func_type.return_type
        elif func_type is type_type:
            if function.is_name and function.entry and function.entry.type:
                result_type = function.entry.type
                if result_type.is_extension_type:
                    return result_type
                elif result_type.is_builtin_type:
                    if function.entry.name == 'float':
                        return PyrexTypes.c_double_type
                    elif function.entry.name in Builtin.types_that_construct_their_instance:
                        return result_type
        return py_object_type

Robert Bradshaw's avatar
Robert Bradshaw committed
3256 3257 3258 3259 3260
    def type_dependencies(self, env):
        # TODO: Update when Danilo's C++ code merged in to handle the
        # the case of function overloading.
        return self.function.type_dependencies(env)

Stefan Behnel's avatar
Stefan Behnel committed
3261 3262 3263 3264 3265
    def may_be_none(self):
        if self.may_return_none is not None:
            return self.may_return_none
        return ExprNode.may_be_none(self)

Robert Bradshaw's avatar
Robert Bradshaw committed
3266 3267 3268 3269 3270 3271
    def analyse_as_type_constructor(self, env):
        type = self.function.analyse_as_type(env)
        if type and type.is_struct_or_union:
            args, kwds = self.explicit_args_kwds()
            items = []
            for arg, member in zip(args, type.scope.var_entries):
3272
                items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
Robert Bradshaw's avatar
Robert Bradshaw committed
3273 3274 3275 3276 3277 3278 3279
            if kwds:
                items += kwds.key_value_pairs
            self.key_value_pairs = items
            self.__class__ = DictNode
            self.analyse_types(env)
            self.coerce_to(type, env)
            return True
3280 3281 3282 3283 3284 3285 3286 3287 3288
        elif type and type.is_cpp_class:
            for arg in self.args:
                arg.analyse_types(env)
            constructor = type.scope.lookup("<init>")
            self.function = RawCNameExprNode(self.function.pos, constructor.type)
            self.function.entry = constructor
            self.function.set_cname(type.declaration_code(""))
            self.analyse_c_function_call(env)
            return True
3289

3290 3291
    def is_lvalue(self):
        return self.type.is_reference
3292

3293
    def nogil_check(self, env):
3294 3295
        func_type = self.function_type()
        if func_type.is_pyobject:
3296
            self.gil_error()
3297
        elif not getattr(func_type, 'nogil', False):
3298
            self.gil_error()
3299 3300 3301

    gil_message = "Calling gil-requiring function"

3302 3303

class SimpleCallNode(CallNode):
William Stein's avatar
William Stein committed
3304 3305 3306 3307 3308 3309 3310
    #  Function call without keyword, * or ** args.
    #
    #  function       ExprNode
    #  args           [ExprNode]
    #  arg_tuple      ExprNode or None     used internally
    #  self           ExprNode or None     used internally
    #  coerced_self   ExprNode or None     used internally
3311
    #  wrapper_call   bool                 used internally
3312
    #  has_optional_args   bool            used internally
3313
    #  nogil          bool                 used internally
3314

William Stein's avatar
William Stein committed
3315
    subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
3316

William Stein's avatar
William Stein committed
3317 3318 3319
    self = None
    coerced_self = None
    arg_tuple = None
3320
    wrapper_call = False
3321
    has_optional_args = False
3322
    nogil = False
3323
    analysed = False
3324

3325 3326 3327 3328 3329 3330 3331
    def compile_time_value(self, denv):
        function = self.function.compile_time_value(denv)
        args = [arg.compile_time_value(denv) for arg in self.args]
        try:
            return function(*args)
        except Exception, e:
            self.compile_time_value_error(e)
3332

3333
    def analyse_as_type(self, env):
3334
        attr = self.function.as_cython_attribute()
3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346
        if attr == 'pointer':
            if len(self.args) != 1:
                error(self.args.pos, "only one type allowed.")
            else:
                type = self.args[0].analyse_as_type(env)
                if not type:
                    error(self.args[0].pos, "Unknown type")
                else:
                    return PyrexTypes.CPtrType(type)

    def explicit_args_kwds(self):
        return self.args, None
3347

William Stein's avatar
William Stein committed
3348
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3349 3350
        if self.analyse_as_type_constructor(env):
            return
3351 3352 3353
        if self.analysed:
            return
        self.analysed = True
William Stein's avatar
William Stein committed
3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
        function = self.function
        function.is_called = 1
        self.function.analyse_types(env)
        if function.is_attribute and function.entry and function.entry.is_cmethod:
            # Take ownership of the object from which the attribute
            # was obtained, because we need to pass it as 'self'.
            self.self = function.obj
            function.obj = CloneNode(self.self)
        func_type = self.function_type()
        if func_type.is_pyobject:
3364 3365
            self.arg_tuple = TupleNode(self.pos, args = self.args)
            self.arg_tuple.analyse_types(env)
William Stein's avatar
William Stein committed
3366
            self.args = None
3367 3368 3369
            if func_type is Builtin.type_type and function.is_name and \
                   function.entry and \
                   function.entry.is_builtin and \
3370 3371 3372 3373 3374 3375 3376 3377 3378
                   function.entry.name in Builtin.types_that_construct_their_instance:
                # calling a builtin type that returns a specific object type
                if function.entry.name == 'float':
                    # the following will come true later on in a transform
                    self.type = PyrexTypes.c_double_type
                    self.result_ctype = PyrexTypes.c_double_type
                else:
                    self.type = Builtin.builtin_types[function.entry.name]
                    self.result_ctype = py_object_type
Stefan Behnel's avatar
Stefan Behnel committed
3379
                self.may_return_none = False
3380
            elif function.is_name and function.type_entry:
3381 3382 3383 3384 3385
                # We are calling an extension type constructor.  As
                # long as we do not support __new__(), the result type
                # is clear
                self.type = function.type_entry.type
                self.result_ctype = py_object_type
Stefan Behnel's avatar
Stefan Behnel committed
3386
                self.may_return_none = False
3387 3388
            else:
                self.type = py_object_type
William Stein's avatar
William Stein committed
3389 3390 3391 3392 3393 3394
            self.is_temp = 1
        else:
            for arg in self.args:
                arg.analyse_types(env)
            if self.self and func_type.args:
                # Coerce 'self' to the type expected by the method.
3395 3396 3397
                self_arg = func_type.args[0]
                if self_arg.not_none: # C methods must do the None test for self at *call* time
                    self.self = self.self.as_none_safe_node(
3398 3399 3400
                        "'NoneType' object has no attribute '%s'",
                        error = 'PyExc_AttributeError',
                        format_args = [self.function.entry.name])
3401
                expected_type = self_arg.type
Stefan Behnel's avatar
Stefan Behnel committed
3402 3403 3404 3405 3406
                if self_arg.accept_builtin_subtypes:
                    self.coerced_self = CMethodSelfCloneNode(self.self)
                else:
                    self.coerced_self = CloneNode(self.self)
                self.coerced_self = self.coerced_self.coerce_to(expected_type, env)
William Stein's avatar
William Stein committed
3407 3408 3409
                # Insert coerced 'self' argument into argument list.
                self.args.insert(0, self.coerced_self)
            self.analyse_c_function_call(env)
3410

William Stein's avatar
William Stein committed
3411 3412 3413 3414 3415 3416 3417
    def function_type(self):
        # Return the type of the function being called, coercing a function
        # pointer to a function if necessary.
        func_type = self.function.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        return func_type
3418

3419 3420 3421 3422 3423 3424 3425
    def is_simple(self):
        # C function calls could be considered simple, but they may
        # have side-effects that may hit when multiple operations must
        # be effected in order, e.g. when constructing the argument
        # sequence for a function call or comparing values.
        return False

William Stein's avatar
William Stein committed
3426
    def analyse_c_function_call(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3427
        if self.function.type is error_type:
3428
            self.type = error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3429
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
3430
        if self.function.type.is_cpp_class:
3431 3432
            overloaded_entry = self.function.type.scope.lookup("operator()")
            if overloaded_entry is None:
Robert Bradshaw's avatar
Robert Bradshaw committed
3433 3434 3435
                self.type = PyrexTypes.error_type
                self.result_code = "<error>"
                return
3436 3437
        elif hasattr(self.function, 'entry'):
            overloaded_entry = self.function.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
3438
        else:
3439 3440 3441 3442 3443 3444 3445 3446 3447
            overloaded_entry = None
        if overloaded_entry:
            entry = PyrexTypes.best_match(self.args, overloaded_entry.all_alternatives(), self.pos)
            if not entry:
                self.type = PyrexTypes.error_type
                self.result_code = "<error>"
                return
            self.function.entry = entry
            self.function.type = entry.type
3448 3449 3450 3451 3452 3453 3454 3455
            func_type = self.function_type()
        else:
            func_type = self.function_type()
            if not func_type.is_cfunction:
                error(self.pos, "Calling non-function type '%s'" % func_type)
                self.type = PyrexTypes.error_type
                self.result_code = "<error>"
                return
William Stein's avatar
William Stein committed
3456
        # Check no. of args
3457 3458
        max_nargs = len(func_type.args)
        expected_nargs = max_nargs - func_type.optional_arg_count
William Stein's avatar
William Stein committed
3459
        actual_nargs = len(self.args)
3460 3461 3462
        if func_type.optional_arg_count and expected_nargs != actual_nargs:
            self.has_optional_args = 1
            self.is_temp = 1
William Stein's avatar
William Stein committed
3463
        # Coerce arguments
3464
        some_args_in_temps = False
3465
        for i in xrange(min(max_nargs, actual_nargs)):
William Stein's avatar
William Stein committed
3466
            formal_type = func_type.args[i].type
3467
            arg = self.args[i].coerce_to(formal_type, env)
3468
            if arg.is_temp:
3469 3470
                if i > 0:
                    # first argument in temp doesn't impact subsequent arguments
3471
                    some_args_in_temps = True
3472
            elif arg.type.is_pyobject and not env.nogil:
3473 3474
                if i == 0 and self.self is not None:
                    # a method's cloned "self" argument is ok
3475
                    pass
3476
                elif arg.nonlocally_immutable():
3477 3478 3479
                    # plain local variables are ok
                    pass
                else:
3480 3481 3482 3483
                    # we do not safely own the argument's reference,
                    # but we must make sure it cannot be collected
                    # before we return from the function, so we create
                    # an owned temp reference to it
3484 3485
                    if i > 0: # first argument doesn't matter
                        some_args_in_temps = True
3486
                    arg = arg.coerce_to_temp(env)
3487
            self.args[i] = arg
3488
        # handle additional varargs parameters
3489
        for i in xrange(max_nargs, actual_nargs):
3490 3491 3492 3493 3494 3495 3496
            arg = self.args[i]
            if arg.type.is_pyobject:
                arg_ctype = arg.type.default_coerced_ctype()
                if arg_ctype is None:
                    error(self.args[i].pos,
                          "Python object cannot be passed as a varargs parameter")
                else:
3497
                    self.args[i] = arg = arg.coerce_to(arg_ctype, env)
3498 3499
            if arg.is_temp and i > 0:
                some_args_in_temps = True
3500 3501 3502
        if some_args_in_temps:
            # if some args are temps and others are not, they may get
            # constructed in the wrong order (temps first) => make
3503 3504 3505 3506
            # sure they are either all temps or all not temps (except
            # for the last argument, which is evaluated last in any
            # case)
            for i in xrange(actual_nargs-1):
3507 3508
                if i == 0 and self.self is not None:
                    continue # self is ok
3509
                arg = self.args[i]
3510 3511
                if arg.nonlocally_immutable():
                    # locals, C functions, unassignable types are safe.
3512
                    pass
3513 3514
                elif arg.type.is_cpp_class:
                    # Assignment has side effects, avoid.
3515 3516
                    pass
                elif env.nogil and arg.type.is_pyobject:
3517 3518 3519
                    # can't copy a Python reference into a temp in nogil
                    # env (this is safe: a construction would fail in
                    # nogil anyway)
3520 3521
                    pass
                else:
3522 3523 3524 3525 3526
                    #self.args[i] = arg.coerce_to_temp(env)
                    # instead: issue a warning
                    if i > 0 or i == 1 and self.self is not None: # skip first arg
                        warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
                        break
3527

William Stein's avatar
William Stein committed
3528
        # Calc result type and code fragment
Robert Bradshaw's avatar
Robert Bradshaw committed
3529
        if isinstance(self.function, NewExprNode):
3530
            self.type = PyrexTypes.CPtrType(self.function.class_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3531 3532
        else:
            self.type = func_type.return_type
3533

3534 3535 3536
        if self.function.is_name or self.function.is_attribute:
            if self.function.entry and self.function.entry.utility_code:
                self.is_temp = 1 # currently doesn't work for self.calculate_result_code()
3537

Stefan Behnel's avatar
Stefan Behnel committed
3538 3539 3540 3541 3542 3543
        if self.type.is_pyobject:
            self.result_ctype = py_object_type
            self.is_temp = 1
        elif func_type.exception_value is not None \
                 or func_type.exception_check:
            self.is_temp = 1
3544 3545 3546 3547
        elif self.type.is_memoryviewslice:
            self.is_temp = 1
            # func_type.exception_check = True

3548
        # Called in 'nogil' context?
3549
        self.nogil = env.nogil
3550 3551 3552 3553 3554
        if (self.nogil and
            func_type.exception_check and
            func_type.exception_check != '+'):
            env.use_utility_code(pyerr_occurred_withgil_utility_code)
        # C++ exception handler
Robert Bradshaw's avatar
Robert Bradshaw committed
3555 3556 3557 3558
        if func_type.exception_check == '+':
            if func_type.exception_value is None:
                env.use_utility_code(cpp_exception_utility_code)

William Stein's avatar
William Stein committed
3559 3560
    def calculate_result_code(self):
        return self.c_call_code()
3561

William Stein's avatar
William Stein committed
3562 3563
    def c_call_code(self):
        func_type = self.function_type()
3564
        if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
William Stein's avatar
William Stein committed
3565 3566 3567
            return "<error>"
        formal_args = func_type.args
        arg_list_code = []
3568
        args = list(zip(formal_args, self.args))
3569 3570 3571 3572
        max_nargs = len(func_type.args)
        expected_nargs = max_nargs - func_type.optional_arg_count
        actual_nargs = len(self.args)
        for formal_arg, actual_arg in args[:expected_nargs]:
William Stein's avatar
William Stein committed
3573 3574
                arg_code = actual_arg.result_as(formal_arg.type)
                arg_list_code.append(arg_code)
3575

3576 3577
        if func_type.is_overridable:
            arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
3578

3579
        if func_type.optional_arg_count:
3580
            if expected_nargs == actual_nargs:
3581
                optional_args = 'NULL'
3582
            else:
3583
                optional_args = "&%s" % self.opt_arg_struct
3584
            arg_list_code.append(optional_args)
3585

William Stein's avatar
William Stein committed
3586
        for actual_arg in self.args[len(formal_args):]:
3587 3588
            arg_list_code.append(actual_arg.result())
        result = "%s(%s)" % (self.function.result(),
Stefan Behnel's avatar
Stefan Behnel committed
3589
            ', '.join(arg_list_code))
William Stein's avatar
William Stein committed
3590
        return result
3591

William Stein's avatar
William Stein committed
3592 3593
    def generate_result_code(self, code):
        func_type = self.function_type()
3594 3595 3596
        if self.function.is_name or self.function.is_attribute:
            if self.function.entry and self.function.entry.utility_code:
                code.globalstate.use_utility_code(self.function.entry.utility_code)
William Stein's avatar
William Stein committed
3597
        if func_type.is_pyobject:
3598
            arg_code = self.arg_tuple.py_result()
William Stein's avatar
William Stein committed
3599
            code.putln(
3600
                "%s = PyObject_Call(%s, %s, NULL); %s" % (
3601
                    self.result(),
William Stein's avatar
William Stein committed
3602
                    self.function.py_result(),
3603
                    arg_code,
3604
                    code.error_goto_if_null(self.result(), self.pos)))
3605
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3606
        elif func_type.is_cfunction:
3607 3608 3609
            if self.has_optional_args:
                actual_nargs = len(self.args)
                expected_nargs = len(func_type.args) - func_type.optional_arg_count
3610 3611
                self.opt_arg_struct = code.funcstate.allocate_temp(
                    func_type.op_arg_struct.base_type, manage_ref=True)
3612 3613 3614 3615
                code.putln("%s.%s = %s;" % (
                        self.opt_arg_struct,
                        Naming.pyrex_prefix + "n",
                        len(self.args) - expected_nargs))
3616
                args = list(zip(func_type.args, self.args))
3617 3618 3619
                for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
                    code.putln("%s.%s = %s;" % (
                            self.opt_arg_struct,
3620
                            func_type.opt_arg_cname(formal_arg.name),
3621
                            actual_arg.result_as(formal_arg.type)))
William Stein's avatar
William Stein committed
3622
            exc_checks = []
3623
            if self.type.is_pyobject and self.is_temp:
3624
                exc_checks.append("!%s" % self.result())
3625 3626 3627
            elif self.type.is_memoryviewslice:
                assert self.is_temp
                exc_checks.append(self.type.error_condition(self.result()))
William Stein's avatar
William Stein committed
3628
            else:
3629 3630
                exc_val = func_type.exception_value
                exc_check = func_type.exception_check
William Stein's avatar
William Stein committed
3631
                if exc_val is not None:
3632
                    exc_checks.append("%s == %s" % (self.result(), exc_val))
William Stein's avatar
William Stein committed
3633
                if exc_check:
3634 3635
                    if self.nogil:
                        exc_checks.append("__Pyx_ErrOccurredWithGIL()")
3636
                    else:
3637
                        exc_checks.append("PyErr_Occurred()")
William Stein's avatar
William Stein committed
3638 3639
            if self.is_temp or exc_checks:
                rhs = self.c_call_code()
3640 3641
                if self.result():
                    lhs = "%s = " % self.result()
William Stein's avatar
William Stein committed
3642 3643 3644
                    if self.is_temp and self.type.is_pyobject:
                        #return_type = self.type # func_type.return_type
                        #print "SimpleCallNode.generate_result_code: casting", rhs, \
Robert Bradshaw's avatar
Robert Bradshaw committed
3645
                        #    "from", return_type, "to pyobject" ###
William Stein's avatar
William Stein committed
3646 3647 3648
                        rhs = typecast(py_object_type, self.type, rhs)
                else:
                    lhs = ""
Felix Wu's avatar
Felix Wu committed
3649
                if func_type.exception_check == '+':
Robert Bradshaw's avatar
Robert Bradshaw committed
3650 3651 3652
                    if func_type.exception_value is None:
                        raise_py_exception = "__Pyx_CppExn2PyErr()"
                    elif func_type.exception_value.type.is_pyobject:
3653 3654 3655
                        raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
                            func_type.exception_value.entry.cname,
                            func_type.exception_value.entry.cname)
Robert Bradshaw's avatar
Robert Bradshaw committed
3656 3657
                    else:
                        raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
3658 3659
                    if self.nogil:
                        raise_py_exception = 'Py_BLOCK_THREADS; %s; Py_UNBLOCK_THREADS' % raise_py_exception
Felix Wu's avatar
Felix Wu committed
3660
                    code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3661
                    "try {%s%s;} catch(...) {%s; %s}" % (
Felix Wu's avatar
Felix Wu committed
3662 3663
                        lhs,
                        rhs,
Robert Bradshaw's avatar
Robert Bradshaw committed
3664
                        raise_py_exception,
Felix Wu's avatar
Felix Wu committed
3665
                        code.error_goto(self.pos)))
3666 3667 3668 3669 3670 3671
                else:
                    if exc_checks:
                        goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
                    else:
                        goto_error = ""
                    code.putln("%s%s; %s" % (lhs, rhs, goto_error))
3672
                if self.type.is_pyobject and self.result():
3673
                    code.put_gotref(self.py_result())
3674 3675
            if self.has_optional_args:
                code.funcstate.release_temp(self.opt_arg_struct)
3676 3677 3678 3679


class PythonCapiFunctionNode(ExprNode):
    subexprs = []
3680
    def __init__(self, pos, py_name, cname, func_type, utility_code = None):
3681
        self.pos = pos
3682 3683
        self.name = py_name
        self.cname = cname
3684 3685 3686
        self.type = func_type
        self.utility_code = utility_code

3687 3688 3689
    def analyse_types(self, env):
        pass

3690 3691 3692 3693 3694
    def generate_result_code(self, code):
        if self.utility_code:
            code.globalstate.use_utility_code(self.utility_code)

    def calculate_result_code(self):
3695
        return self.cname
3696 3697 3698 3699

class PythonCapiCallNode(SimpleCallNode):
    # Python C-API Function call (only created in transforms)

Stefan Behnel's avatar
Stefan Behnel committed
3700 3701 3702 3703 3704 3705
    # By default, we assume that the call never returns None, as this
    # is true for most C-API functions in CPython.  If this does not
    # apply to a call, set the following to True (or None to inherit
    # the default behaviour).
    may_return_none = False

3706
    def __init__(self, pos, function_name, func_type,
3707
                 utility_code = None, py_name=None, **kwargs):
3708 3709 3710
        self.type = func_type.return_type
        self.result_ctype = self.type
        self.function = PythonCapiFunctionNode(
3711
            pos, py_name, function_name, func_type,
3712 3713 3714 3715 3716
            utility_code = utility_code)
        # call this last so that we can override the constructed
        # attributes above with explicit keyword arguments if required
        SimpleCallNode.__init__(self, pos, **kwargs)

William Stein's avatar
William Stein committed
3717

3718
class GeneralCallNode(CallNode):
William Stein's avatar
William Stein committed
3719 3720 3721 3722 3723 3724
    #  General Python function call, including keyword,
    #  * and ** arguments.
    #
    #  function         ExprNode
    #  positional_args  ExprNode          Tuple of positional arguments
    #  keyword_args     ExprNode or None  Dict of keyword arguments
3725

3726
    type = py_object_type
3727

3728
    subexprs = ['function', 'positional_args', 'keyword_args']
William Stein's avatar
William Stein committed
3729

3730
    nogil_check = Node.gil_error
3731

3732 3733 3734 3735 3736 3737 3738 3739
    def compile_time_value(self, denv):
        function = self.function.compile_time_value(denv)
        positional_args = self.positional_args.compile_time_value(denv)
        keyword_args = self.keyword_args.compile_time_value(denv)
        try:
            return function(*positional_args, **keyword_args)
        except Exception, e:
            self.compile_time_value_error(e)
3740

3741
    def explicit_args_kwds(self):
3742 3743
        if (self.keyword_args and not isinstance(self.keyword_args, DictNode) or
            not isinstance(self.positional_args, TupleNode)):
3744
            raise CompileError(self.pos,
3745 3746
                'Compile-time keyword arguments must be explicit.')
        return self.positional_args.args, self.keyword_args
3747

William Stein's avatar
William Stein committed
3748
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3749 3750
        if self.analyse_as_type_constructor(env):
            return
William Stein's avatar
William Stein committed
3751 3752 3753 3754
        self.function.analyse_types(env)
        self.positional_args.analyse_types(env)
        if self.keyword_args:
            self.keyword_args.analyse_types(env)
3755
        if not self.function.type.is_pyobject:
3756 3757
            if self.function.type.is_error:
                self.type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
3758
                return
3759
            if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
3760
                error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
3761 3762
            else:
                self.function = self.function.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
3763 3764
        self.positional_args = \
            self.positional_args.coerce_to_pyobject(env)
Stefan Behnel's avatar
Stefan Behnel committed
3765
        function = self.function
3766 3767 3768 3769 3770
        if function.is_name and function.type_entry:
            # We are calling an extension type constructor.  As long
            # as we do not support __new__(), the result type is clear
            self.type = function.type_entry.type
            self.result_ctype = py_object_type
Stefan Behnel's avatar
Stefan Behnel committed
3771
            self.may_return_none = False
3772 3773
        else:
            self.type = py_object_type
William Stein's avatar
William Stein committed
3774
        self.is_temp = 1
3775

William Stein's avatar
William Stein committed
3776
    def generate_result_code(self, code):
3777
        if self.type.is_error: return
3778 3779
        if self.keyword_args:
            kwargs = self.keyword_args.py_result()
William Stein's avatar
William Stein committed
3780
        else:
3781
            kwargs = 'NULL'
William Stein's avatar
William Stein committed
3782
        code.putln(
3783
            "%s = PyObject_Call(%s, %s, %s); %s" % (
3784
                self.result(),
3785 3786 3787
                self.function.py_result(),
                self.positional_args.py_result(),
                kwargs,
3788
                code.error_goto_if_null(self.result(), self.pos)))
3789
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3790 3791


3792
class AsTupleNode(ExprNode):
William Stein's avatar
William Stein committed
3793 3794 3795 3796
    #  Convert argument to tuple. Used for normalising
    #  the * argument of a function call.
    #
    #  arg    ExprNode
3797

William Stein's avatar
William Stein committed
3798
    subexprs = ['arg']
3799 3800 3801

    def calculate_constant_result(self):
        self.constant_result = tuple(self.base.constant_result)
3802

3803 3804 3805 3806 3807 3808 3809
    def compile_time_value(self, denv):
        arg = self.arg.compile_time_value(denv)
        try:
            return tuple(arg)
        except Exception, e:
            self.compile_time_value_error(e)

William Stein's avatar
William Stein committed
3810 3811 3812
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
3813
        self.type = tuple_type
William Stein's avatar
William Stein committed
3814
        self.is_temp = 1
3815

3816 3817 3818
    def may_be_none(self):
        return False

3819
    nogil_check = Node.gil_error
3820 3821
    gil_message = "Constructing Python tuple"

William Stein's avatar
William Stein committed
3822 3823
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3824
            "%s = PySequence_Tuple(%s); %s" % (
3825
                self.result(),
William Stein's avatar
William Stein committed
3826
                self.arg.py_result(),
3827
                code.error_goto_if_null(self.result(), self.pos)))
3828
        code.put_gotref(self.py_result())
3829

William Stein's avatar
William Stein committed
3830

3831
class AttributeNode(ExprNode):
William Stein's avatar
William Stein committed
3832 3833 3834 3835
    #  obj.attribute
    #
    #  obj          ExprNode
    #  attribute    string
3836
    #  needs_none_check boolean        Used if obj is an extension type.
3837
    #                                  If set to True, it is known that the type is not None.
William Stein's avatar
William Stein committed
3838 3839 3840 3841 3842 3843 3844
    #
    #  Used internally:
    #
    #  is_py_attr           boolean   Is a Python getattr operation
    #  member               string    C name of struct member
    #  is_called            boolean   Function call is being done on result
    #  entry                Entry     Symbol table entry of attribute
3845

William Stein's avatar
William Stein committed
3846 3847
    is_attribute = 1
    subexprs = ['obj']
3848

William Stein's avatar
William Stein committed
3849 3850 3851
    type = PyrexTypes.error_type
    entry = None
    is_called = 0
3852
    needs_none_check = True
3853
    is_memslice_transpose = False
William Stein's avatar
William Stein committed
3854

3855
    def as_cython_attribute(self):
Mark Florisson's avatar
Mark Florisson committed
3856 3857 3858
        if (isinstance(self.obj, NameNode) and
                self.obj.is_cython_module and not
                self.attribute == u"parallel"):
3859
            return self.attribute
Mark Florisson's avatar
Mark Florisson committed
3860

3861 3862 3863
        cy = self.obj.as_cython_attribute()
        if cy:
            return "%s.%s" % (cy, self.attribute)
3864
        return None
3865

3866 3867 3868 3869 3870 3871 3872 3873 3874
    def coerce_to(self, dst_type, env):
        #  If coercing to a generic pyobject and this is a cpdef function
        #  we can create the corresponding attribute
        if dst_type is py_object_type:
            entry = self.entry
            if entry and entry.is_cfunction and entry.as_variable:
                # must be a cpdef function
                self.is_temp = 1
                self.entry = entry.as_variable
3875
                self.analyse_as_python_attribute(env)
3876
                return self
3877
        return ExprNode.coerce_to(self, dst_type, env)
3878 3879 3880

    def calculate_constant_result(self):
        attr = self.attribute
3881
        if attr.startswith("__") and attr.endswith("__"):
3882 3883 3884
            return
        self.constant_result = getattr(self.obj.constant_result, attr)

3885 3886
    def compile_time_value(self, denv):
        attr = self.attribute
3887
        if attr.startswith("__") and attr.endswith("__"):
Stefan Behnel's avatar
Stefan Behnel committed
3888 3889
            error(self.pos,
                  "Invalid attribute name '%s' in compile-time expression" % attr)
3890
            return None
3891
        obj = self.obj.compile_time_value(denv)
3892 3893 3894 3895
        try:
            return getattr(obj, attr)
        except Exception, e:
            self.compile_time_value_error(e)
3896

Robert Bradshaw's avatar
Robert Bradshaw committed
3897 3898
    def type_dependencies(self, env):
        return self.obj.type_dependencies(env)
3899

3900 3901 3902 3903 3904 3905
    def infer_type(self, env):
        if self.analyse_as_cimported_attribute(env, 0):
            return self.entry.type
        elif self.analyse_as_unbound_cmethod(env):
            return self.entry.type
        else:
3906 3907 3908 3909 3910 3911 3912 3913
            obj_type = self.obj.infer_type(env)
            self.analyse_attribute(env, obj_type = obj_type)
            if obj_type.is_builtin_type and self.type.is_cfunction:
                # special case: C-API replacements for C methods of
                # builtin types cannot be inferred as C functions as
                # that would prevent their use as bound methods
                self.type = py_object_type
                return py_object_type
3914
            return self.type
3915

William Stein's avatar
William Stein committed
3916 3917
    def analyse_target_declaration(self, env):
        pass
3918

William Stein's avatar
William Stein committed
3919 3920
    def analyse_target_types(self, env):
        self.analyse_types(env, target = 1)
3921

William Stein's avatar
William Stein committed
3922
    def analyse_types(self, env, target = 0):
3923
        self.initialized_check = env.directives['initializedcheck']
William Stein's avatar
William Stein committed
3924
        if self.analyse_as_cimported_attribute(env, target):
3925 3926 3927 3928 3929 3930 3931
            self.entry.used = True
        elif not target and self.analyse_as_unbound_cmethod(env):
            self.entry.used = True
        else:
            self.analyse_as_ordinary_attribute(env, target)
            if self.entry:
                self.entry.used = True
3932

William Stein's avatar
William Stein committed
3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944
    def analyse_as_cimported_attribute(self, env, target):
        # Try to interpret this as a reference to an imported
        # C const, type, var or function. If successful, mutates
        # this node into a NameNode and returns 1, otherwise
        # returns 0.
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
            entry = module_scope.lookup_here(self.attribute)
            if entry and (
                entry.is_cglobal or entry.is_cfunction
                or entry.is_type or entry.is_const):
                    self.mutate_into_name_node(env, entry, target)
3945
                    entry.used = 1
William Stein's avatar
William Stein committed
3946 3947
                    return 1
        return 0
3948

William Stein's avatar
William Stein committed
3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964
    def analyse_as_unbound_cmethod(self, env):
        # Try to interpret this as a reference to an unbound
        # C method of an extension type. If successful, mutates
        # this node into a NameNode and returns 1, otherwise
        # returns 0.
        type = self.obj.analyse_as_extension_type(env)
        if type:
            entry = type.scope.lookup_here(self.attribute)
            if entry and entry.is_cmethod:
                # Create a temporary entry describing the C method
                # as an ordinary function.
                ubcm_entry = Symtab.Entry(entry.name,
                    "%s->%s" % (type.vtabptr_cname, entry.cname),
                    entry.type)
                ubcm_entry.is_cfunction = 1
                ubcm_entry.func_cname = entry.func_cname
3965
                ubcm_entry.is_unbound_cmethod = 1
William Stein's avatar
William Stein committed
3966 3967 3968
                self.mutate_into_name_node(env, ubcm_entry, None)
                return 1
        return 0
3969

3970 3971 3972
    def analyse_as_type(self, env):
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
3973
            return module_scope.lookup_type(self.attribute)
3974
        if not self.obj.is_string_literal:
Robert Bradshaw's avatar
Robert Bradshaw committed
3975
            base_type = self.obj.analyse_as_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3976
            if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
Robert Bradshaw's avatar
Robert Bradshaw committed
3977
                return base_type.scope.lookup_type(self.attribute)
3978
        return None
3979

William Stein's avatar
William Stein committed
3980 3981 3982 3983 3984 3985 3986 3987 3988
    def analyse_as_extension_type(self, env):
        # Try to interpret this as a reference to an extension type
        # in a cimported module. Returns the extension type, or None.
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
            entry = module_scope.lookup_here(self.attribute)
            if entry and entry.is_type and entry.type.is_extension_type:
                return entry.type
        return None
3989

William Stein's avatar
William Stein committed
3990 3991 3992 3993 3994 3995 3996 3997 3998
    def analyse_as_module(self, env):
        # Try to interpret this as a reference to a cimported module
        # in another cimported module. Returns the module scope, or None.
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
            entry = module_scope.lookup_here(self.attribute)
            if entry and entry.as_module:
                return entry.as_module
        return None
3999

William Stein's avatar
William Stein committed
4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010
    def mutate_into_name_node(self, env, entry, target):
        # Mutate this node into a NameNode and complete the
        # analyse_types phase.
        self.__class__ = NameNode
        self.name = self.attribute
        self.entry = entry
        del self.obj
        del self.attribute
        if target:
            NameNode.analyse_target_types(self, env)
        else:
4011
            NameNode.analyse_rvalue_entry(self, env)
4012

William Stein's avatar
William Stein committed
4013 4014 4015 4016
    def analyse_as_ordinary_attribute(self, env, target):
        self.obj.analyse_types(env)
        self.analyse_attribute(env)
        if self.entry and self.entry.is_cmethod and not self.is_called:
4017 4018
#            error(self.pos, "C method can only be called")
            pass
4019 4020
        ## Reference to C array turns into pointer to first element.
        #while self.type.is_array:
Robert Bradshaw's avatar
Robert Bradshaw committed
4021
        #    self.type = self.type.element_ptr_type()
William Stein's avatar
William Stein committed
4022 4023 4024 4025
        if self.is_py_attr:
            if not target:
                self.is_temp = 1
                self.result_ctype = py_object_type
4026 4027
        elif target and self.obj.type.is_builtin_type:
            error(self.pos, "Assignment to an immutable object field")
4028 4029
        #elif self.type.is_memoryviewslice and not target:
        #    self.is_temp = True
4030

Robert Bradshaw's avatar
Robert Bradshaw committed
4031
    def analyse_attribute(self, env, obj_type = None):
William Stein's avatar
William Stein committed
4032 4033 4034
        # Look up attribute and set self.type and self.member.
        self.is_py_attr = 0
        self.member = self.attribute
Robert Bradshaw's avatar
Robert Bradshaw committed
4035 4036 4037 4038 4039 4040 4041
        if obj_type is None:
            if self.obj.type.is_string:
                self.obj = self.obj.coerce_to_pyobject(env)
            obj_type = self.obj.type
        else:
            if obj_type.is_string:
                obj_type = py_object_type
4042
        if obj_type.is_ptr or obj_type.is_array:
William Stein's avatar
William Stein committed
4043 4044
            obj_type = obj_type.base_type
            self.op = "->"
4045
        elif obj_type.is_extension_type or obj_type.is_builtin_type:
William Stein's avatar
William Stein committed
4046 4047 4048 4049 4050 4051
            self.op = "->"
        else:
            self.op = "."
        if obj_type.has_attributes:
            entry = None
            if obj_type.attributes_known():
4052 4053
                if (obj_type.is_memoryviewslice and not
                        obj_type.scope.lookup_here(self.attribute)):
4054 4055 4056 4057 4058 4059 4060 4061
                    if self.attribute == 'T':
                        self.is_memslice_transpose = True
                        self.is_temp = True
                        self.use_managed_ref = True
                        self.type = self.obj.type
                        return
                    else:
                        obj_type.declare_attribute(self.attribute)
William Stein's avatar
William Stein committed
4062
                entry = obj_type.scope.lookup_here(self.attribute)
Robert Bradshaw's avatar
Robert Bradshaw committed
4063 4064
                if entry and entry.is_member:
                    entry = None
William Stein's avatar
William Stein committed
4065
            else:
4066 4067
                error(self.pos,
                    "Cannot select attribute of incomplete type '%s'"
William Stein's avatar
William Stein committed
4068
                    % obj_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
4069 4070
                self.type = PyrexTypes.error_type
                return
William Stein's avatar
William Stein committed
4071 4072
            self.entry = entry
            if entry:
4073 4074
                if obj_type.is_extension_type and entry.name == "__weakref__":
                    error(self.pos, "Illegal use of special attribute __weakref__")
4075 4076
                # methods need the normal attribute lookup
                # because they do not have struct entries
4077 4078 4079 4080
                if entry.is_variable or entry.is_cmethod:
                    self.type = entry.type
                    self.member = entry.cname
                    return
William Stein's avatar
William Stein committed
4081 4082 4083 4084 4085
                else:
                    # If it's not a variable or C method, it must be a Python
                    # method of an extension type, so we treat it like a Python
                    # attribute.
                    pass
4086
        # If we get here, the base object is not a struct/union/extension
William Stein's avatar
William Stein committed
4087 4088 4089
        # type, or it is an extension type and the attribute is either not
        # declared or is declared as a Python method. Treat it as a Python
        # attribute reference.
Robert Bradshaw's avatar
Robert Bradshaw committed
4090
        self.analyse_as_python_attribute(env, obj_type)
Stefan Behnel's avatar
Stefan Behnel committed
4091

Robert Bradshaw's avatar
Robert Bradshaw committed
4092 4093 4094
    def analyse_as_python_attribute(self, env, obj_type = None):
        if obj_type is None:
            obj_type = self.obj.type
4095 4096
        # mangle private '__*' Python attributes used inside of a class
        self.attribute = env.mangle_class_private_name(self.attribute)
4097
        self.member = self.attribute
4098 4099
        self.type = py_object_type
        self.is_py_attr = 1
4100
        if not obj_type.is_pyobject and not obj_type.is_error:
4101
            if obj_type.can_coerce_to_pyobject(env):
4102 4103 4104 4105 4106
                self.obj = self.obj.coerce_to_pyobject(env)
            else:
                error(self.pos,
                      "Object of type '%s' has no attribute '%s'" %
                      (obj_type, self.attribute))
4107

4108
    def nogil_check(self, env):
4109
        if self.is_py_attr:
4110
            self.gil_error()
4111 4112 4113
        elif self.type.is_memoryviewslice:
            import MemoryView
            MemoryView.err_if_nogil_initialized_check(self.pos, env, 'attribute')
4114

4115 4116
    gil_message = "Accessing Python attribute"

William Stein's avatar
William Stein committed
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127
    def is_simple(self):
        if self.obj:
            return self.result_in_temp() or self.obj.is_simple()
        else:
            return NameNode.is_simple(self)

    def is_lvalue(self):
        if self.obj:
            return 1
        else:
            return NameNode.is_lvalue(self)
4128

William Stein's avatar
William Stein committed
4129 4130 4131 4132 4133
    def is_ephemeral(self):
        if self.obj:
            return self.obj.is_ephemeral()
        else:
            return NameNode.is_ephemeral(self)
4134

William Stein's avatar
William Stein committed
4135 4136
    def calculate_result_code(self):
        #print "AttributeNode.calculate_result_code:", self.member ###
4137
        #print "...obj node =", self.obj, "code", self.obj.result() ###
William Stein's avatar
William Stein committed
4138 4139 4140 4141 4142
        #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
        obj = self.obj
        obj_code = obj.result_as(obj.type)
        #print "...obj_code =", obj_code ###
        if self.entry and self.entry.is_cmethod:
Stefan Behnel's avatar
Stefan Behnel committed
4143
            if obj.type.is_extension_type and not self.entry.is_builtin_cmethod:
4144 4145
                if self.entry.final_func_cname:
                    return self.entry.final_func_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
4146
                return "((struct %s *)%s%s%s)->%s" % (
4147
                    obj.type.vtabstruct_cname, obj_code, self.op,
Robert Bradshaw's avatar
Robert Bradshaw committed
4148 4149 4150
                    obj.type.vtabslot_cname, self.member)
            else:
                return self.member
4151
        elif obj.type.is_complex:
4152
            return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
William Stein's avatar
William Stein committed
4153
        else:
4154 4155 4156
            if obj.type.is_builtin_type and self.entry and self.entry.is_variable:
                # accessing a field of a builtin type, need to cast better than result_as() does
                obj_code = obj.type.cast_code(obj.result(), to_object_struct = True)
William Stein's avatar
William Stein committed
4157
            return "%s%s%s" % (obj_code, self.op, self.member)
4158

William Stein's avatar
William Stein committed
4159 4160
    def generate_result_code(self, code):
        if self.is_py_attr:
4161 4162
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
4163
                    self.result(),
4164
                    self.obj.py_result(),
4165
                    code.intern_identifier(self.attribute),
4166
                    code.error_goto_if_null(self.result(), self.pos)))
4167
            code.put_gotref(self.py_result())
4168
        elif self.type.is_memoryviewslice:
4169 4170 4171 4172 4173 4174 4175 4176 4177
            if self.is_memslice_transpose:
                # transpose the slice
                for access, packing in self.type.axes:
                    if access == 'ptr':
                        error(self.pos, "Transposing not supported for slices "
                                        "with indirect dimensions")
                        return

                code.putln("%s = %s;" % (self.result(), self.obj.result()))
Mark Florisson's avatar
Mark Florisson committed
4178
                if self.obj.is_name or self.obj.is_attribute and self.obj.is_memslice_transpose:
4179 4180 4181 4182 4183
                    code.put_incref_memoryviewslice(self.result(), have_gil=True)

                T = "__pyx_memslice_transpose(&%s) == 0"
                code.putln(code.error_goto_if(T % self.result(), self.pos))
            elif self.initialized_check:
4184 4185 4186 4187 4188 4189
                code.putln(
                    'if (unlikely(!%s.memview)) {'
                        'PyErr_SetString(PyExc_AttributeError,'
                                        '"Memoryview is not initialized");'
                        '%s'
                    '}' % (self.result(), code.error_goto(self.pos)))
4190
        else:
4191 4192 4193 4194 4195 4196 4197 4198
            # result_code contains what is needed, but we may need to insert
            # a check and raise an exception
            if self.obj.type.is_extension_type:
                if self.needs_none_check and code.globalstate.directives['nonecheck']:
                    self.put_nonecheck(code)
            elif self.entry and self.entry.is_cmethod and self.entry.utility_code:
                # C method implemented as function call with utility code
                code.globalstate.use_utility_code(self.entry.utility_code)
4199

William Stein's avatar
William Stein committed
4200 4201 4202
    def generate_assignment_code(self, rhs, code):
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
4203
            code.put_error_if_neg(self.pos,
4204 4205
                'PyObject_SetAttr(%s, %s, %s)' % (
                    self.obj.py_result(),
4206
                    code.intern_identifier(self.attribute),
4207
                    rhs.py_result()))
William Stein's avatar
William Stein committed
4208
            rhs.generate_disposal_code(code)
4209
            rhs.free_temps(code)
4210 4211 4212 4213 4214
        elif self.obj.type.is_complex:
            code.putln("__Pyx_SET_C%s(%s, %s);" % (
                self.member.upper(),
                self.obj.result_as(self.obj.type),
                rhs.result_as(self.ctype())))
William Stein's avatar
William Stein committed
4215
        else:
4216
            if (self.obj.type.needs_nonecheck()
4217 4218 4219 4220
                  and self.needs_none_check
                  and code.globalstate.directives['nonecheck']):
                self.put_nonecheck(code)

4221
            select_code = self.result()
4222
            if self.type.is_pyobject and self.use_managed_ref:
William Stein's avatar
William Stein committed
4223
                rhs.make_owned_reference(code)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4224
                code.put_giveref(rhs.py_result())
4225
                code.put_gotref(select_code)
William Stein's avatar
William Stein committed
4226
                code.put_decref(select_code, self.ctype())
4227
            elif self.type.is_memoryviewslice:
4228
                import MemoryView
4229
                MemoryView.put_assign_to_memviewslice(
Mark Florisson's avatar
Mark Florisson committed
4230 4231
                        select_code, rhs.result(), self.type, code,
                        incref_rhs=rhs.is_name)
4232

4233
            if not self.type.is_memoryviewslice:
4234 4235 4236 4237 4238
                code.putln(
                    "%s = %s;" % (
                        select_code,
                        rhs.result_as(self.ctype())))
                        #rhs.result()))
William Stein's avatar
William Stein committed
4239
            rhs.generate_post_assignment_code(code)
4240
            rhs.free_temps(code)
William Stein's avatar
William Stein committed
4241
        self.obj.generate_disposal_code(code)
4242
        self.obj.free_temps(code)
4243

William Stein's avatar
William Stein committed
4244 4245
    def generate_deletion_code(self, code):
        self.obj.generate_evaluation_code(code)
4246
        if self.is_py_attr or (isinstance(self.entry.scope, Symtab.PropertyScope)
4247
                               and u'__del__' in self.entry.scope.entries):
4248 4249 4250
            code.put_error_if_neg(self.pos,
                'PyObject_DelAttr(%s, %s)' % (
                    self.obj.py_result(),
4251
                    code.intern_identifier(self.attribute)))
William Stein's avatar
William Stein committed
4252 4253 4254
        else:
            error(self.pos, "Cannot delete C attribute of extension type")
        self.obj.generate_disposal_code(code)
4255
        self.obj.free_temps(code)
4256

4257 4258 4259 4260 4261
    def annotate(self, code):
        if self.is_py_attr:
            code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
        else:
            code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
William Stein's avatar
William Stein committed
4262

4263 4264
    def put_nonecheck(self, code):
        code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
4265 4266 4267 4268 4269 4270 4271
        if self.obj.type.is_extension_type:
            test = "%s == Py_None" % self.obj.result_as(PyrexTypes.py_object_type)
        elif self.obj.type.is_memoryviewslice:
            test = "!%s.memview" % self.obj.result()
        else:
            assert False
        code.putln("if (%s) {" % code.unlikely(test))
4272 4273 4274 4275
        code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
        code.putln(code.error_goto(self.pos))
        code.putln("}")

4276

William Stein's avatar
William Stein committed
4277 4278 4279 4280 4281 4282
#-------------------------------------------------------------------
#
#  Constructor nodes
#
#-------------------------------------------------------------------

4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297
class StarredTargetNode(ExprNode):
    #  A starred expression like "*a"
    #
    #  This is only allowed in sequence assignment targets such as
    #
    #      a, *b = (1,2,3,4)    =>     a = 1 ; b = [2,3,4]
    #
    #  and will be removed during type analysis (or generate an error
    #  if it's found at unexpected places).
    #
    #  target          ExprNode

    subexprs = ['target']
    is_starred = 1
    type = py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4298
    is_temp = 1
4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326

    def __init__(self, pos, target):
        self.pos = pos
        self.target = target

    def analyse_declarations(self, env):
        error(self.pos, "can use starred expression only as assignment target")
        self.target.analyse_declarations(env)

    def analyse_types(self, env):
        error(self.pos, "can use starred expression only as assignment target")
        self.target.analyse_types(env)
        self.type = self.target.type

    def analyse_target_declaration(self, env):
        self.target.analyse_target_declaration(env)

    def analyse_target_types(self, env):
        self.target.analyse_target_types(env)
        self.type = self.target.type

    def calculate_result_code(self):
        return ""

    def generate_result_code(self, code):
        pass


4327
class SequenceNode(ExprNode):
William Stein's avatar
William Stein committed
4328 4329 4330 4331 4332 4333
    #  Base class for list and tuple constructor nodes.
    #  Contains common code for performing sequence unpacking.
    #
    #  args                    [ExprNode]
    #  unpacked_items          [ExprNode] or None
    #  coerced_unpacked_items  [ExprNode] or None
4334
    # mult_factor              ExprNode     the integer number of content repetitions ([1,2]*3)
4335

4336
    subexprs = ['args', 'mult_factor']
4337

William Stein's avatar
William Stein committed
4338 4339
    is_sequence_constructor = 1
    unpacked_items = None
4340
    mult_factor = None
4341

4342 4343 4344
    def compile_time_value_list(self, denv):
        return [arg.compile_time_value(denv) for arg in self.args]

4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358
    def replace_starred_target_node(self):
        # replace a starred node in the targets by the contained expression
        self.starred_assignment = False
        args = []
        for arg in self.args:
            if arg.is_starred:
                if self.starred_assignment:
                    error(arg.pos, "more than 1 starred expression in assignment")
                self.starred_assignment = True
                arg = arg.target
                arg.is_starred = True
            args.append(arg)
        self.args = args

William Stein's avatar
William Stein committed
4359
    def analyse_target_declaration(self, env):
4360
        self.replace_starred_target_node()
William Stein's avatar
William Stein committed
4361 4362 4363
        for arg in self.args:
            arg.analyse_target_declaration(env)

4364
    def analyse_types(self, env, skip_children=False):
William Stein's avatar
William Stein committed
4365 4366
        for i in range(len(self.args)):
            arg = self.args[i]
4367
            if not skip_children: arg.analyse_types(env)
William Stein's avatar
William Stein committed
4368
            self.args[i] = arg.coerce_to_pyobject(env)
4369 4370 4371
        if self.mult_factor:
            self.mult_factor.analyse_types(env)
            if not self.mult_factor.type.is_int:
4372
                self.mult_factor = self.mult_factor.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
4373
        self.is_temp = 1
Stefan Behnel's avatar
Stefan Behnel committed
4374
        # not setting self.type here, subtypes do this
4375

4376 4377 4378
    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
4379
    def analyse_target_types(self, env):
4380 4381
        if self.mult_factor:
            error(arg.pos, "can't assign to multiplied sequence")
4382
        self.unpacked_items = []
William Stein's avatar
William Stein committed
4383
        self.coerced_unpacked_items = []
4384
        self.any_coerced_items = False
William Stein's avatar
William Stein committed
4385 4386
        for arg in self.args:
            arg.analyse_target_types(env)
4387 4388 4389 4390 4391 4392
            if arg.is_starred:
                if not arg.type.assignable_from(Builtin.list_type):
                    error(arg.pos,
                          "starred target must have Python object (list) type")
                if arg.type is py_object_type:
                    arg.type = Builtin.list_type
William Stein's avatar
William Stein committed
4393 4394
            unpacked_item = PyTempNode(self.pos, env)
            coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
4395 4396
            if unpacked_item is not coerced_unpacked_item:
                self.any_coerced_items = True
William Stein's avatar
William Stein committed
4397 4398 4399
            self.unpacked_items.append(unpacked_item)
            self.coerced_unpacked_items.append(coerced_unpacked_item)
        self.type = py_object_type
4400

William Stein's avatar
William Stein committed
4401 4402
    def generate_result_code(self, code):
        self.generate_operation_code(code)
4403

4404 4405 4406 4407 4408 4409
    def generate_sequence_packing_code(self, code, target=None, plain=False):
        if target is None:
            target = self.result()
        py_multiply = self.mult_factor and not self.mult_factor.type.is_int
        if plain or py_multiply:
            mult_factor = None
4410
        else:
4411 4412 4413 4414 4415 4416
            mult_factor = self.mult_factor
        if mult_factor:
            mult = mult_factor.result()
            if isinstance(mult_factor.constant_result, (int,long)) \
                   and mult_factor.constant_result > 0:
                size_factor = ' * %s' % mult_factor.constant_result
4417 4418 4419 4420 4421
            else:
                size_factor = ' * ((%s<0) ? 0:%s)' % (mult, mult)
        else:
            size_factor = ''
            mult = ''
4422 4423 4424 4425 4426 4427 4428

        if self.type is Builtin.list_type:
            create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM'
        elif self.type is Builtin.tuple_type:
            create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM'
        else:
            raise InternalError("sequence unpacking for unexpected type %s" % self.type)
4429 4430
        arg_count = len(self.args)
        code.putln("%s = %s(%s%s); %s" % (
4431 4432 4433 4434
            target, create_func, arg_count, size_factor,
            code.error_goto_if_null(target, self.pos)))
        code.put_gotref(target)

4435
        if mult:
4436 4437 4438 4439
            # FIXME: can't use a temp variable here as the code may
            # end up in the constant building function.  Temps
            # currently don't work there.

4440 4441
            #counter = code.funcstate.allocate_temp(mult_factor.type, manage_ref=False)
            counter = Naming.quick_temp_cname
4442 4443
            code.putln('{ Py_ssize_t %s;' % counter)
            if arg_count == 1:
Stefan Behnel's avatar
Stefan Behnel committed
4444
                offset = counter
4445
            else:
Stefan Behnel's avatar
Stefan Behnel committed
4446
                offset = '%s * %s' % (counter, arg_count)
4447 4448 4449 4450 4451 4452 4453 4454 4455
            code.putln('for (%s=0; %s < %s; %s++) {' % (
                counter, counter, mult, counter
                ))
        else:
            offset = ''
        for i in xrange(arg_count):
            arg = self.args[i]
            if mult or not arg.result_in_temp():
                code.put_incref(arg.result(), arg.ctype())
Stefan Behnel's avatar
Stefan Behnel committed
4456
            code.putln("%s(%s, %s, %s);" % (
4457
                set_item_func,
4458
                target,
Stefan Behnel's avatar
Stefan Behnel committed
4459
                (offset and i) and ('%s + %s' % (offset, i)) or (offset or i),
4460 4461 4462 4463
                arg.py_result()))
            code.put_giveref(arg.py_result())
        if mult:
            code.putln('}')
4464 4465
            #code.funcstate.release_temp(counter)
            code.putln('}')
4466
        elif py_multiply and not plain:
4467
            code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' % (
4468 4469 4470 4471 4472 4473 4474
                Naming.quick_temp_cname, target, self.mult_factor.py_result(),
                code.error_goto_if_null(Naming.quick_temp_cname, self.pos)
                ))
            code.put_gotref(Naming.quick_temp_cname)
            code.put_decref(target, py_object_type)
            code.putln('%s = %s;' % (target, Naming.quick_temp_cname))
            code.putln('}')
4475 4476

    def generate_subexpr_disposal_code(self, code):
4477
        if self.mult_factor and self.mult_factor.type.is_int:
4478 4479 4480 4481 4482 4483 4484 4485 4486
            super(SequenceNode, self).generate_subexpr_disposal_code(code)
        else:
            # We call generate_post_assignment_code here instead
            # of generate_disposal_code, because values were stored
            # in the tuple using a reference-stealing operation.
            for arg in self.args:
                arg.generate_post_assignment_code(code)
                # Should NOT call free_temps -- this is invoked by the default
                # generate_evaluation_code which will do that.
4487 4488
            if self.mult_factor:
                self.mult_factor.generate_disposal_code(code)
4489

William Stein's avatar
William Stein committed
4490
    def generate_assignment_code(self, rhs, code):
4491 4492 4493
        if self.starred_assignment:
            self.generate_starred_assignment_code(rhs, code)
        else:
4494
            self.generate_parallel_assignment_code(rhs, code)
4495 4496 4497 4498 4499

        for item in self.unpacked_items:
            item.release(code)
        rhs.free_temps(code)

4500 4501 4502 4503 4504
    _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
        PyrexTypes.py_object_type, [
            PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None),
            ]))

4505
    def generate_parallel_assignment_code(self, rhs, code):
4506 4507 4508
        # Need to work around the fact that generate_evaluation_code
        # allocates the temps in a rather hacky way -- the assignment
        # is evaluated twice, within each if-block.
4509 4510
        for item in self.unpacked_items:
            item.allocate(code)
4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538
        special_unpack = (rhs.type is py_object_type
                          or rhs.type in (tuple_type, list_type)
                          or not rhs.type.is_builtin_type)
        if special_unpack:
            tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result()
            list_check  = 'PyList_CheckExact(%s)' % rhs.py_result()
            if rhs.type is list_type:
                sequence_types = ['List']
                sequence_type_test = list_check
            elif rhs.type is tuple_type:
                sequence_types = ['Tuple']
                sequence_type_test = tuple_check
            else:
                sequence_types = ['Tuple', 'List']
                sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check)
            code.putln("if (%s) {" % sequence_type_test)
            code.putln("PyObject* sequence = %s;" % rhs.py_result())
            if len(sequence_types) == 2:
                code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0])
            self.generate_special_parallel_unpacking_code(code, sequence_types[0])
            if len(sequence_types) == 2:
                code.putln("} else {")
                self.generate_special_parallel_unpacking_code(code, sequence_types[1])
                code.putln("}")
            for item in self.unpacked_items:
                code.put_incref(item.result(), item.ctype())
            rhs.generate_disposal_code(code)
            code.putln("} else {")
4539 4540
        else:
            code.putln("{")
Robert Bradshaw's avatar
Robert Bradshaw committed
4541

4542
        if special_unpack and rhs.type is tuple_type:
4543 4544 4545 4546
            code.globalstate.use_utility_code(tuple_unpacking_error_code)
            code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
                        rhs.py_result(), len(self.args)))
            code.putln(code.error_goto(self.pos))
4547
        else:
4548
            self.generate_generic_parallel_unpacking_code(code, rhs)
4549
        code.putln("}")
4550

4551 4552 4553 4554 4555
        for value_node in self.coerced_unpacked_items:
            value_node.generate_evaluation_code(code)
        for i in range(len(self.args)):
            self.args[i].generate_assignment_code(
                self.coerced_unpacked_items[i], code)
4556

4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568
    def generate_special_parallel_unpacking_code(self, code, sequence_type):
        code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
        code.globalstate.use_utility_code(raise_too_many_values_to_unpack)
        code.putln("if (unlikely(Py%s_GET_SIZE(sequence) != %d)) {" % (
            sequence_type, len(self.args)))
        code.putln("if (Py%s_GET_SIZE(sequence) > %d) __Pyx_RaiseTooManyValuesError(%d);" % (
            sequence_type, len(self.args), len(self.args)))
        code.putln("else __Pyx_RaiseNeedMoreValuesError(Py%s_GET_SIZE(sequence));" % sequence_type)
        code.putln(code.error_goto(self.pos))
        code.putln("}")
        for i, item in enumerate(self.unpacked_items):
            code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % (item.result(), sequence_type, i))
4569

4570 4571 4572
    def generate_generic_parallel_unpacking_code(self, code, rhs):
        code.globalstate.use_utility_code(iternext_unpacking_end_utility_code)
        code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
4573
        code.putln("Py_ssize_t index = -1;") # must be at the start of a C block!
4574

4575 4576 4577 4578 4579 4580 4581 4582
        iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
        code.putln(
            "%s = PyObject_GetIter(%s); %s" % (
                iterator_temp,
                rhs.py_result(),
                code.error_goto_if_null(iterator_temp, self.pos)))
        code.put_gotref(iterator_temp)
        rhs.generate_disposal_code(code)
4583

4584 4585 4586
        iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False)
        code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (
            iternext_func, iterator_temp))
William Stein's avatar
William Stein committed
4587

4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616
        unpacking_error_label = code.new_label('unpacking_failed')
        code.use_label(unpacking_error_label)
        unpack_code = "%s(%s)" % (iternext_func, iterator_temp)
        for i in range(len(self.args)):
            item = self.unpacked_items[i]
            code.putln(
                "index = %d; %s = %s; if (unlikely(!%s)) goto %s;" % (
                    i,
                    item.result(),
                    typecast(item.ctype(), py_object_type, unpack_code),
                    item.result(),
                    unpacking_error_label))
            code.put_gotref(item.py_result())
        code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s(%s), %d)" % (
            iternext_func,
            iterator_temp,
            len(self.args)))
        code.put_decref_clear(iterator_temp, py_object_type)
        code.funcstate.release_temp(iterator_temp)
        code.funcstate.release_temp(iternext_func)
        unpacking_done_label = code.new_label('unpacking_done')
        code.put_goto(unpacking_done_label)

        code.put_label(unpacking_error_label)
        code.put_decref_clear(iterator_temp, py_object_type)
        code.putln("if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear();")
        code.putln("if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index);")
        code.putln(code.error_goto(self.pos))
        code.put_label(unpacking_done_label)
4617 4618 4619 4620 4621 4622 4623 4624 4625

    def generate_starred_assignment_code(self, rhs, code):
        for i, arg in enumerate(self.args):
            if arg.is_starred:
                starred_target = self.unpacked_items[i]
                fixed_args_left  = self.args[:i]
                fixed_args_right = self.args[i+1:]
                break

4626
        iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4627 4628
        code.putln(
            "%s = PyObject_GetIter(%s); %s" % (
4629
                iterator_temp,
4630
                rhs.py_result(),
4631 4632
                code.error_goto_if_null(iterator_temp, self.pos)))
        code.put_gotref(iterator_temp)
4633 4634
        rhs.generate_disposal_code(code)

4635
        for item in self.unpacked_items:
4636
            item.allocate(code)
4637
        code.globalstate.use_utility_code(unpacking_utility_code)
4638 4639 4640
        for i in range(len(fixed_args_left)):
            item = self.unpacked_items[i]
            unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
4641
                iterator_temp, i)
4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652
            code.putln(
                "%s = %s; %s" % (
                    item.result(),
                    typecast(item.ctype(), py_object_type, unpack_code),
                    code.error_goto_if_null(item.result(), self.pos)))
            code.put_gotref(item.py_result())
            value_node = self.coerced_unpacked_items[i]
            value_node.generate_evaluation_code(code)

        target_list = starred_target.result()
        code.putln("%s = PySequence_List(%s); %s" % (
4653
            target_list, iterator_temp,
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671
            code.error_goto_if_null(target_list, self.pos)))
        code.put_gotref(target_list)
        if fixed_args_right:
            code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
            unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
            code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
                (target_list, len(unpacked_right_args))))
            code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
                     len(fixed_args_left), target_list,
                     code.error_goto(self.pos)))
            code.putln('}')
            for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
                                                       self.coerced_unpacked_items[::-1])):
                code.putln(
                    "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
                        arg.py_result(),
                        target_list, target_list))
                # resize the list the hard way
4672
                code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
4673 4674 4675
                code.put_gotref(arg.py_result())
                coerced_arg.generate_evaluation_code(code)

4676 4677
        code.put_decref_clear(iterator_temp, py_object_type)
        code.funcstate.release_temp(iterator_temp)
4678 4679 4680 4681 4682

        for i in range(len(self.args)):
            self.args[i].generate_assignment_code(
                self.coerced_unpacked_items[i], code)

4683 4684 4685 4686 4687 4688 4689 4690
    def annotate(self, code):
        for arg in self.args:
            arg.annotate(code)
        if self.unpacked_items:
            for arg in self.unpacked_items:
                arg.annotate(code)
            for arg in self.coerced_unpacked_items:
                arg.annotate(code)
William Stein's avatar
William Stein committed
4691 4692 4693 4694


class TupleNode(SequenceNode):
    #  Tuple constructor.
4695

4696
    type = tuple_type
4697
    is_partly_literal = False
4698 4699 4700

    gil_message = "Constructing Python tuple"

4701
    def analyse_types(self, env, skip_children=False):
Robert Bradshaw's avatar
Robert Bradshaw committed
4702
        if len(self.args) == 0:
4703 4704
            self.is_temp = False
            self.is_literal = True
Robert Bradshaw's avatar
Robert Bradshaw committed
4705
        else:
4706
            SequenceNode.analyse_types(self, env, skip_children)
4707 4708 4709 4710
            for child in self.args:
                if not child.is_literal:
                    break
            else:
4711 4712 4713 4714 4715 4716 4717
                if not self.mult_factor or self.mult_factor.is_literal and \
                       isinstance(self.mult_factor.constant_result, (int, long)):
                    self.is_temp = False
                    self.is_literal = True
                else:
                    self.is_temp = True
                    self.is_partly_literal = True
4718

Stefan Behnel's avatar
Stefan Behnel committed
4719 4720 4721 4722
    def is_simple(self):
        # either temp or constant => always simple
        return True

4723 4724 4725 4726
    def nonlocally_immutable(self):
        # either temp or constant => always safe
        return True

Robert Bradshaw's avatar
Robert Bradshaw committed
4727 4728
    def calculate_result_code(self):
        if len(self.args) > 0:
4729
            return self.result_code
Robert Bradshaw's avatar
Robert Bradshaw committed
4730 4731
        else:
            return Naming.empty_tuple
William Stein's avatar
William Stein committed
4732

4733 4734 4735 4736
    def calculate_constant_result(self):
        self.constant_result = tuple([
                arg.constant_result for arg in self.args])

4737 4738 4739 4740 4741 4742
    def compile_time_value(self, denv):
        values = self.compile_time_value_list(denv)
        try:
            return tuple(values)
        except Exception, e:
            self.compile_time_value_error(e)
4743

William Stein's avatar
William Stein committed
4744
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4745 4746 4747
        if len(self.args) == 0:
            # result_code is Naming.empty_tuple
            return
4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760
        if self.is_partly_literal:
            # underlying tuple is const, but factor is not
            tuple_target = code.get_py_const(py_object_type, 'tuple_', cleanup_level=2)
            const_code = code.get_cached_constants_writer()
            const_code.mark_pos(self.pos)
            self.generate_sequence_packing_code(const_code, tuple_target, plain=True)
            const_code.put_giveref(tuple_target)
            code.putln('%s = PyNumber_Multiply(%s, %s); %s' % (
                self.result(), tuple_target, self.mult_factor.py_result(),
                code.error_goto_if_null(self.result(), self.pos)
                ))
            code.put_gotref(self.py_result())
        elif self.is_literal:
4761 4762
            # non-empty cached tuple => result is global constant,
            # creation code goes into separate code writer
4763
            self.result_code = code.get_py_const(py_object_type, 'tuple_', cleanup_level=2)
4764 4765
            code = code.get_cached_constants_writer()
            code.mark_pos(self.pos)
4766
            self.generate_sequence_packing_code(code)
4767
            code.put_giveref(self.py_result())
4768 4769
        else:
            self.generate_sequence_packing_code(code)
4770

William Stein's avatar
William Stein committed
4771 4772 4773

class ListNode(SequenceNode):
    #  List constructor.
4774

4775 4776
    # obj_conversion_errors    [PyrexError]   used internally
    # orignial_args            [ExprNode]     used internally
4777

4778
    obj_conversion_errors = []
Stefan Behnel's avatar
Stefan Behnel committed
4779
    type = list_type
4780

4781
    gil_message = "Constructing Python list"
4782

Robert Bradshaw's avatar
Robert Bradshaw committed
4783
    def type_dependencies(self, env):
4784
        return ()
4785

4786 4787 4788
    def infer_type(self, env):
        # TOOD: Infer non-object list arrays.
        return list_type
4789

4790
    def analyse_expressions(self, env):
4791
        SequenceNode.analyse_expressions(self, env)
4792 4793
        self.coerce_to_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
4794
    def analyse_types(self, env):
4795 4796 4797 4798 4799
        hold_errors()
        self.original_args = list(self.args)
        SequenceNode.analyse_types(self, env)
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
4800

Robert Bradshaw's avatar
Robert Bradshaw committed
4801 4802
    def coerce_to(self, dst_type, env):
        if dst_type.is_pyobject:
4803 4804 4805
            for err in self.obj_conversion_errors:
                report_error(err)
            self.obj_conversion_errors = []
Robert Bradshaw's avatar
Robert Bradshaw committed
4806 4807
            if not self.type.subtype_of(dst_type):
                error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
4808 4809
        elif self.mult_factor:
            error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type)
4810
        elif dst_type.is_ptr and dst_type.base_type is not PyrexTypes.c_void_type:
Robert Bradshaw's avatar
Robert Bradshaw committed
4811
            base_type = dst_type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4812
            self.type = PyrexTypes.CArrayType(base_type, len(self.args))
4813
            for i in range(len(self.original_args)):
Robert Bradshaw's avatar
Robert Bradshaw committed
4814
                arg = self.args[i]
4815 4816
                if isinstance(arg, CoerceToPyTypeNode):
                    arg = arg.arg
Robert Bradshaw's avatar
Robert Bradshaw committed
4817
                self.args[i] = arg.coerce_to(base_type, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4818 4819 4820 4821 4822 4823
        elif dst_type.is_struct:
            if len(self.args) > len(dst_type.scope.var_entries):
                error(self.pos, "Too may members for '%s'" % dst_type)
            else:
                if len(self.args) < len(dst_type.scope.var_entries):
                    warning(self.pos, "Too few members for '%s'" % dst_type, 1)
4824 4825 4826
                for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
                    if isinstance(arg, CoerceToPyTypeNode):
                        arg = arg.arg
Robert Bradshaw's avatar
Robert Bradshaw committed
4827 4828
                    self.args[i] = arg.coerce_to(member.type, env)
            self.type = dst_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4829 4830 4831 4832
        else:
            self.type = error_type
            error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
        return self
4833

Robert Bradshaw's avatar
Robert Bradshaw committed
4834 4835
    def release_temp(self, env):
        if self.type.is_array:
4836 4837
            # To be valid C++, we must allocate the memory on the stack
            # manually and be sure not to reuse it for something else.
Robert Bradshaw's avatar
Robert Bradshaw committed
4838 4839 4840
            pass
        else:
            SequenceNode.release_temp(self, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4841

4842
    def calculate_constant_result(self):
4843 4844
        if self.mult_factor:
            raise ValueError() # may exceed the compile time memory
4845 4846 4847
        self.constant_result = [
            arg.constant_result for arg in self.args]

4848
    def compile_time_value(self, denv):
4849 4850 4851 4852
        l = self.compile_time_value_list(denv)
        if self.mult_factor:
            l *= self.mult_factor.compile_time_value(denv)
        return l
4853

William Stein's avatar
William Stein committed
4854
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4855
        if self.type.is_pyobject:
4856 4857
            for err in self.obj_conversion_errors:
                report_error(err)
4858
            self.generate_sequence_packing_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4859 4860 4861 4862 4863 4864
        elif self.type.is_array:
            for i, arg in enumerate(self.args):
                code.putln("%s[%s] = %s;" % (
                                self.result(),
                                i,
                                arg.result()))
Robert Bradshaw's avatar
Robert Bradshaw committed
4865
        elif self.type.is_struct:
Robert Bradshaw's avatar
Robert Bradshaw committed
4866 4867 4868 4869 4870
            for arg, member in zip(self.args, self.type.scope.var_entries):
                code.putln("%s.%s = %s;" % (
                        self.result(),
                        member.cname,
                        arg.result()))
4871 4872
        else:
            raise InternalError("List type never specified")
4873

Robert Bradshaw's avatar
Robert Bradshaw committed
4874

4875 4876 4877 4878 4879 4880 4881 4882 4883
class ScopedExprNode(ExprNode):
    # Abstract base class for ExprNodes that have their own local
    # scope, such as generator expressions.
    #
    # expr_scope    Scope  the inner scope of the expression

    subexprs = []
    expr_scope = None

4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902
    # does this node really have a local scope, e.g. does it leak loop
    # variables or not?  non-leaking Py3 behaviour is default, except
    # for list comprehensions where the behaviour differs in Py2 and
    # Py3 (set in Parsing.py based on parser context)
    has_local_scope = True

    def init_scope(self, outer_scope, expr_scope=None):
        if expr_scope is not None:
            self.expr_scope = expr_scope
        elif self.has_local_scope:
            self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
        else:
            self.expr_scope = None

    def analyse_declarations(self, env):
        self.init_scope(env)

    def analyse_scoped_declarations(self, env):
        # this is called with the expr_scope as env
4903 4904
        pass

4905 4906
    def analyse_types(self, env):
        # no recursion here, the children will be analysed separately below
4907 4908 4909 4910 4911 4912
        pass

    def analyse_scoped_expressions(self, env):
        # this is called with the expr_scope as env
        pass

4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959
    def generate_evaluation_code(self, code):
        # set up local variables and free their references on exit
        generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code
        if not self.has_local_scope or not self.expr_scope.var_entries:
            # no local variables => delegate, done
            generate_inner_evaluation_code(code)
            return

        code.putln('{ /* enter inner scope */')
        py_entries = []
        for entry in self.expr_scope.var_entries:
            if not entry.in_closure:
                code.put_var_declaration(entry)
                if entry.type.is_pyobject and entry.used:
                    py_entries.append(entry)
        if not py_entries:
            # no local Python references => no cleanup required
            generate_inner_evaluation_code(code)
            code.putln('} /* exit inner scope */')
            return

        # must free all local Python references at each exit point
        old_loop_labels = tuple(code.new_loop_labels())
        old_error_label = code.new_error_label()

        generate_inner_evaluation_code(code)

        # normal (non-error) exit
        for entry in py_entries:
            code.put_var_decref(entry)

        # error/loop body exit points
        exit_scope = code.new_label('exit_scope')
        code.put_goto(exit_scope)
        for label, old_label in ([(code.error_label, old_error_label)] +
                                 list(zip(code.get_loop_labels(), old_loop_labels))):
            if code.label_used(label):
                code.put_label(label)
                for entry in py_entries:
                    code.put_var_decref(entry)
                code.put_goto(old_label)
        code.put_label(exit_scope)
        code.putln('} /* exit inner scope */')

        code.set_loop_labels(old_loop_labels)
        code.error_label = old_error_label

4960 4961

class ComprehensionNode(ScopedExprNode):
4962
    subexprs = ["target"]
4963
    child_attrs = ["loop"]
4964

4965 4966
    def infer_type(self, env):
        return self.target.infer_type(env)
4967 4968 4969

    def analyse_declarations(self, env):
        self.append.target = self # this is used in the PyList_Append of the inner loop
4970 4971
        self.init_scope(env)

4972 4973
    def analyse_scoped_declarations(self, env):
        self.loop.analyse_declarations(env)
4974

4975 4976 4977
    def analyse_types(self, env):
        self.target.analyse_expressions(env)
        self.type = self.target.type
4978 4979
        if not self.has_local_scope:
            self.loop.analyse_expressions(env)
4980

4981 4982 4983
    def analyse_scoped_expressions(self, env):
        if self.has_local_scope:
            self.loop.analyse_expressions(env)
4984

4985 4986 4987
    def may_be_none(self):
        return False

4988 4989
    def calculate_result_code(self):
        return self.target.result()
4990

4991 4992
    def generate_result_code(self, code):
        self.generate_operation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4993

4994 4995 4996
    def generate_operation_code(self, code):
        self.loop.generate_execution_code(code)

4997 4998
    def annotate(self, code):
        self.loop.annotate(code)
4999 5000


5001
class ComprehensionAppendNode(Node):
5002 5003
    # Need to be careful to avoid infinite recursion:
    # target must not be in child_attrs/subexprs
5004 5005

    child_attrs = ['expr']
5006 5007

    type = PyrexTypes.c_int_type
5008

5009 5010
    def analyse_expressions(self, env):
        self.expr.analyse_expressions(env)
5011
        if not self.expr.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
5012
            self.expr = self.expr.coerce_to_pyobject(env)
5013

5014
    def generate_execution_code(self, code):
5015 5016 5017 5018 5019 5020 5021
        if self.target.type is list_type:
            function = "PyList_Append"
        elif self.target.type is set_type:
            function = "PySet_Add"
        else:
            raise InternalError(
                "Invalid type for comprehension node: %s" % self.target.type)
5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036

        self.expr.generate_evaluation_code(code)
        code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % (
            function,
            self.target.result(),
            self.expr.result()
            ), self.pos))
        self.expr.generate_disposal_code(code)
        self.expr.free_temps(code)

    def generate_function_definitions(self, env, code):
        self.expr.generate_function_definitions(env, code)

    def annotate(self, code):
        self.expr.annotate(code)
5037 5038

class DictComprehensionAppendNode(ComprehensionAppendNode):
5039
    child_attrs = ['key_expr', 'value_expr']
5040

5041 5042
    def analyse_expressions(self, env):
        self.key_expr.analyse_expressions(env)
5043 5044
        if not self.key_expr.type.is_pyobject:
            self.key_expr = self.key_expr.coerce_to_pyobject(env)
5045
        self.value_expr.analyse_expressions(env)
5046 5047 5048
        if not self.value_expr.type.is_pyobject:
            self.value_expr = self.value_expr.coerce_to_pyobject(env)

5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068
    def generate_execution_code(self, code):
        self.key_expr.generate_evaluation_code(code)
        self.value_expr.generate_evaluation_code(code)
        code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % (
            self.target.result(),
            self.key_expr.result(),
            self.value_expr.result()
            ), self.pos))
        self.key_expr.generate_disposal_code(code)
        self.key_expr.free_temps(code)
        self.value_expr.generate_disposal_code(code)
        self.value_expr.free_temps(code)

    def generate_function_definitions(self, env, code):
        self.key_expr.generate_function_definitions(env, code)
        self.value_expr.generate_function_definitions(env, code)

    def annotate(self, code):
        self.key_expr.annotate(code)
        self.value_expr.annotate(code)
5069 5070


5071 5072 5073 5074 5075
class InlinedGeneratorExpressionNode(ScopedExprNode):
    # An inlined generator expression for which the result is
    # calculated inside of the loop.  This will only be created by
    # transforms when replacing builtin calls on generator
    # expressions.
5076
    #
5077 5078 5079
    # loop           ForStatNode      the for-loop, not containing any YieldExprNodes
    # result_node    ResultRefNode    the reference to the result value temp
    # orig_func      String           the name of the builtin function this node replaces
5080

5081
    child_attrs = ["loop"]
5082
    loop_analysed = False
5083 5084
    type = py_object_type

5085 5086
    def analyse_scoped_declarations(self, env):
        self.loop.analyse_declarations(env)
5087

5088 5089 5090 5091 5092 5093
    def may_be_none(self):
        return False

    def annotate(self, code):
        self.loop.annotate(code)

5094 5095
    def infer_type(self, env):
        return self.result_node.infer_type(env)
5096 5097

    def analyse_types(self, env):
5098 5099 5100
        if not self.has_local_scope:
            self.loop_analysed = True
            self.loop.analyse_expressions(env)
5101 5102 5103
        self.type = self.result_node.type
        self.is_temp = True

5104 5105
    def analyse_scoped_expressions(self, env):
        self.loop_analysed = True
5106 5107
        if self.has_local_scope:
            self.loop.analyse_expressions(env)
5108

5109
    def coerce_to(self, dst_type, env):
5110 5111 5112 5113 5114 5115
        if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed:
            # We can optimise by dropping the aggregation variable and
            # the add operations into C.  This can only be done safely
            # before analysing the loop body, after that, the result
            # reference type will have infected expressions and
            # assignments.
5116 5117
            self.result_node.type = self.type = dst_type
            return self
5118
        return super(InlinedGeneratorExpressionNode, self).coerce_to(dst_type, env)
5119

5120 5121 5122 5123 5124
    def generate_result_code(self, code):
        self.result_node.result_code = self.result()
        self.loop.generate_execution_code(code)


5125
class SetNode(ExprNode):
5126 5127
    #  Set constructor.

5128 5129
    type = set_type

5130 5131 5132
    subexprs = ['args']

    gil_message = "Constructing Python set"
5133

5134 5135 5136 5137 5138 5139 5140 5141
    def analyse_types(self, env):
        for i in range(len(self.args)):
            arg = self.args[i]
            arg.analyse_types(env)
            self.args[i] = arg.coerce_to_pyobject(env)
        self.type = set_type
        self.is_temp = 1

5142 5143 5144
    def may_be_none(self):
        return False

5145 5146 5147 5148
    def calculate_constant_result(self):
        self.constant_result = set([
                arg.constant_result for arg in self.args])

5149 5150 5151 5152 5153 5154 5155 5156
    def compile_time_value(self, denv):
        values = [arg.compile_time_value(denv) for arg in self.args]
        try:
            return set(values)
        except Exception, e:
            self.compile_time_value_error(e)

    def generate_evaluation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
5157
        code.globalstate.use_utility_code(Builtin.py_set_utility_code)
5158 5159 5160 5161 5162
        self.allocate_temp_result(code)
        code.putln(
            "%s = PySet_New(0); %s" % (
                self.result(),
                code.error_goto_if_null(self.result(), self.pos)))
5163
        code.put_gotref(self.py_result())
5164 5165 5166 5167 5168 5169 5170 5171
        for arg in self.args:
            arg.generate_evaluation_code(code)
            code.putln(
                code.error_goto_if_neg(
                    "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
                    self.pos))
            arg.generate_disposal_code(code)
            arg.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
5172

William Stein's avatar
William Stein committed
5173

5174
class DictNode(ExprNode):
William Stein's avatar
William Stein committed
5175 5176
    #  Dictionary constructor.
    #
Vitja Makarov's avatar
Vitja Makarov committed
5177 5178
    #  key_value_pairs     [DictItemNode]
    #  exclude_null_values [boolean]          Do not add NULL values to dict
5179 5180
    #
    # obj_conversion_errors    [PyrexError]   used internally
5181

5182
    subexprs = ['key_value_pairs']
5183
    is_temp = 1
Vitja Makarov's avatar
Vitja Makarov committed
5184
    exclude_null_values = False
5185
    type = dict_type
5186

5187
    obj_conversion_errors = []
5188 5189 5190 5191

    def calculate_constant_result(self):
        self.constant_result = dict([
                item.constant_result for item in self.key_value_pairs])
5192

5193
    def compile_time_value(self, denv):
Robert Bradshaw's avatar
Robert Bradshaw committed
5194 5195
        pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
            for item in self.key_value_pairs]
5196 5197 5198 5199
        try:
            return dict(pairs)
        except Exception, e:
            self.compile_time_value_error(e)
5200

Robert Bradshaw's avatar
Robert Bradshaw committed
5201
    def type_dependencies(self, env):
5202
        return ()
5203

5204 5205 5206 5207
    def infer_type(self, env):
        # TOOD: Infer struct constructors.
        return dict_type

William Stein's avatar
William Stein committed
5208
    def analyse_types(self, env):
5209
        hold_errors()
Robert Bradshaw's avatar
Robert Bradshaw committed
5210 5211
        for item in self.key_value_pairs:
            item.analyse_types(env)
5212 5213
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
5214 5215 5216

    def may_be_none(self):
        return False
5217

5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231
    def coerce_to(self, dst_type, env):
        if dst_type.is_pyobject:
            self.release_errors()
            if not self.type.subtype_of(dst_type):
                error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
        elif dst_type.is_struct_or_union:
            self.type = dst_type
            if not dst_type.is_struct and len(self.key_value_pairs) != 1:
                error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
            elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
                warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
            for item in self.key_value_pairs:
                if isinstance(item.key, CoerceToPyTypeNode):
                    item.key = item.key.arg
5232
                if not item.key.is_string_literal:
5233
                    error(item.key.pos, "Invalid struct field identifier")
5234
                    item.key = StringNode(item.key.pos, value="<error>")
5235
                else:
Stefan Behnel's avatar
Stefan Behnel committed
5236 5237
                    key = str(item.key.value) # converts string literals to unicode in Py3
                    member = dst_type.scope.lookup_here(key)
5238
                    if not member:
Stefan Behnel's avatar
Stefan Behnel committed
5239
                        error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
5240 5241 5242 5243 5244 5245 5246 5247 5248
                    else:
                        value = item.value
                        if isinstance(value, CoerceToPyTypeNode):
                            value = value.arg
                        item.value = value.coerce_to(member.type, env)
        else:
            self.type = error_type
            error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
        return self
5249

5250 5251 5252 5253
    def release_errors(self):
        for err in self.obj_conversion_errors:
            report_error(err)
        self.obj_conversion_errors = []
5254 5255 5256

    gil_message = "Constructing Python dict"

William Stein's avatar
William Stein committed
5257 5258 5259
    def generate_evaluation_code(self, code):
        #  Custom method used here because key-value
        #  pairs are evaluated and used one at a time.
5260 5261
        code.mark_pos(self.pos)
        self.allocate_temp_result(code)
5262 5263 5264 5265 5266 5267
        if self.type.is_pyobject:
            self.release_errors()
            code.putln(
                "%s = PyDict_New(); %s" % (
                    self.result(),
                    code.error_goto_if_null(self.result(), self.pos)))
5268
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
5269 5270
        for item in self.key_value_pairs:
            item.generate_evaluation_code(code)
5271
            if self.type.is_pyobject:
Vitja Makarov's avatar
Vitja Makarov committed
5272 5273
                if self.exclude_null_values:
                    code.putln('if (%s) {' % item.value.py_result())
5274
                code.put_error_if_neg(self.pos,
5275 5276 5277 5278
                    "PyDict_SetItem(%s, %s, %s)" % (
                        self.result(),
                        item.key.py_result(),
                        item.value.py_result()))
Vitja Makarov's avatar
Vitja Makarov committed
5279 5280
                if self.exclude_null_values:
                    code.putln('}')
5281 5282 5283
            else:
                code.putln("%s.%s = %s;" % (
                        self.result(),
5284
                        item.key.value,
5285
                        item.value.result()))
Robert Bradshaw's avatar
Robert Bradshaw committed
5286
            item.generate_disposal_code(code)
5287
            item.free_temps(code)
5288

5289
    def annotate(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
5290 5291
        for item in self.key_value_pairs:
            item.annotate(code)
5292

5293
class DictItemNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
5294 5295 5296 5297 5298
    # Represents a single item in a DictNode
    #
    # key          ExprNode
    # value        ExprNode
    subexprs = ['key', 'value']
5299

5300
    nogil_check = None # Parent DictNode takes care of it
5301

5302 5303 5304
    def calculate_constant_result(self):
        self.constant_result = (
            self.key.constant_result, self.value.constant_result)
5305

Robert Bradshaw's avatar
Robert Bradshaw committed
5306 5307 5308 5309 5310
    def analyse_types(self, env):
        self.key.analyse_types(env)
        self.value.analyse_types(env)
        self.key = self.key.coerce_to_pyobject(env)
        self.value = self.value.coerce_to_pyobject(env)
5311

Robert Bradshaw's avatar
Robert Bradshaw committed
5312 5313 5314
    def generate_evaluation_code(self, code):
        self.key.generate_evaluation_code(code)
        self.value.generate_evaluation_code(code)
Stefan Behnel's avatar
Stefan Behnel committed
5315

5316 5317 5318
    def generate_disposal_code(self, code):
        self.key.generate_disposal_code(code)
        self.value.generate_disposal_code(code)
5319 5320 5321 5322

    def free_temps(self, code):
        self.key.free_temps(code)
        self.value.free_temps(code)
5323

5324 5325
    def __iter__(self):
        return iter([self.key, self.value])
William Stein's avatar
William Stein committed
5326

5327

5328 5329 5330 5331 5332 5333 5334
class ModuleNameMixin(object):
    def set_mod_name(self, env):
        self.module_name = env.global_scope().qualified_name

    def get_py_mod_name(self, code):
        return code.get_py_string_const(
                 self.module_name, identifier=True)
Stefan Behnel's avatar
Stefan Behnel committed
5335

5336
class ClassNode(ExprNode, ModuleNameMixin):
William Stein's avatar
William Stein committed
5337 5338 5339 5340
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs a class object given
    #  a name, tuple of bases and class dictionary.
    #
Stefan Behnel's avatar
Stefan Behnel committed
5341
    #  name         EncodedString      Name of the class
William Stein's avatar
William Stein committed
5342 5343 5344
    #  bases        ExprNode           Base class tuple
    #  dict         ExprNode           Class dict (not owned by this node)
    #  doc          ExprNode or None   Doc string
5345
    #  module_name  EncodedString      Name of defining module
5346

5347
    subexprs = ['bases', 'doc']
5348

William Stein's avatar
William Stein committed
5349 5350 5351 5352 5353 5354 5355 5356
    def analyse_types(self, env):
        self.bases.analyse_types(env)
        if self.doc:
            self.doc.analyse_types(env)
            self.doc = self.doc.coerce_to_pyobject(env)
        self.type = py_object_type
        self.is_temp = 1
        env.use_utility_code(create_class_utility_code);
5357 5358
        #TODO(craig,haoyu) This should be moved to a better place
        self.set_mod_name(env)
5359

5360
    def may_be_none(self):
Stefan Behnel's avatar
Stefan Behnel committed
5361
        return True
5362

5363 5364
    gil_message = "Constructing Python class"

William Stein's avatar
William Stein committed
5365
    def generate_result_code(self, code):
5366
        cname = code.intern_identifier(self.name)
5367

William Stein's avatar
William Stein committed
5368
        if self.doc:
5369
            code.put_error_if_neg(self.pos,
Robert Bradshaw's avatar
Robert Bradshaw committed
5370
                'PyDict_SetItemString(%s, "__doc__", %s)' % (
William Stein's avatar
William Stein committed
5371
                    self.dict.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
5372
                    self.doc.py_result()))
5373
        py_mod_name = self.get_py_mod_name(code)
William Stein's avatar
William Stein committed
5374
        code.putln(
5375
            '%s = __Pyx_CreateClass(%s, %s, %s, %s); %s' % (
5376
                self.result(),
William Stein's avatar
William Stein committed
5377 5378
                self.bases.py_result(),
                self.dict.py_result(),
5379
                cname,
5380
                py_mod_name,
5381
                code.error_goto_if_null(self.result(), self.pos)))
5382
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5383

Stefan Behnel's avatar
Stefan Behnel committed
5384

5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402
class Py3ClassNode(ExprNode):
    #  Helper class used in the implementation of Python3+
    #  class definitions. Constructs a class object given
    #  a name, tuple of bases and class dictionary.
    #
    #  name         EncodedString      Name of the class
    #  dict         ExprNode           Class dict (not owned by this node)
    #  module_name  EncodedString      Name of defining module

    subexprs = []

    def analyse_types(self, env):
        self.type = py_object_type
        self.is_temp = 1

    def may_be_none(self):
        return True

5403
    gil_message = "Constructing Python class"
5404 5405

    def generate_result_code(self, code):
5406
        code.globalstate.use_utility_code(create_py3class_utility_code)
5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419
        cname = code.intern_identifier(self.name)
        code.putln(
            '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s); %s' % (
                self.result(),
                self.metaclass.result(),
                cname,
                self.bases.py_result(),
                self.dict.py_result(),
                self.mkw.py_result(),
                code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.py_result())

class KeywordArgsNode(ExprNode):
5420
    #  Helper class for keyword arguments.
5421
    #
5422 5423
    #  starstar_arg      DictNode
    #  keyword_args      [DictItemNode]
5424

5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450
    subexprs = ['starstar_arg', 'keyword_args']
    is_temp = 1
    type = dict_type

    def calculate_constant_result(self):
        result = dict(self.starstar_arg.constant_result)
        for item in self.keyword_args:
            key, value = item.constant_result
            if key in result:
                raise ValueError("duplicate keyword argument found: %s" % key)
            result[key] = value
        self.constant_result = result

    def compile_time_value(self, denv):
        result = self.starstar_arg.compile_time_value(denv)
        pairs = [ (item.key.compile_time_value(denv), item.value.compile_time_value(denv))
                  for item in self.keyword_args ]
        try:
            result = dict(result)
            for key, value in pairs:
                if key in result:
                    raise ValueError("duplicate keyword argument found: %s" % key)
                result[key] = value
        except Exception, e:
            self.compile_time_value_error(e)
        return result
5451

5452 5453 5454 5455 5456
    def type_dependencies(self, env):
        return ()

    def infer_type(self, env):
        return dict_type
5457 5458

    def analyse_types(self, env):
5459 5460 5461 5462 5463 5464
        self.starstar_arg.analyse_types(env)
        self.starstar_arg = self.starstar_arg.coerce_to_pyobject(env).as_none_safe_node(
            # FIXME: CPython's error message starts with the runtime function name
            'argument after ** must be a mapping, not NoneType')
        for item in self.keyword_args:
            item.analyse_types(env)
5465

5466 5467
    def may_be_none(self):
        return False
5468

5469 5470 5471 5472 5473 5474 5475 5476 5477 5478
    gil_message = "Constructing Python dict"

    def generate_evaluation_code(self, code):
        code.mark_pos(self.pos)
        self.allocate_temp_result(code)
        self.starstar_arg.generate_evaluation_code(code)
        if self.starstar_arg.type is not Builtin.dict_type:
            # CPython supports calling functions with non-dicts, so do we
            code.putln('if (likely(PyDict_Check(%s))) {' %
                       self.starstar_arg.py_result())
5479 5480 5481 5482 5483 5484
        if self.keyword_args:
            code.putln(
                "%s = PyDict_Copy(%s); %s" % (
                    self.result(),
                    self.starstar_arg.py_result(),
                    code.error_goto_if_null(self.result(), self.pos)))
5485
            code.put_gotref(self.py_result())
5486
        else:
5487 5488 5489 5490 5491 5492
            code.putln("%s = %s;" % (
                self.result(),
                self.starstar_arg.py_result()))
            code.put_incref(self.result(), py_object_type)
        if self.starstar_arg.type is not Builtin.dict_type:
            code.putln('} else {')
5493
            code.putln(
5494 5495
                "%s = PyObject_CallFunctionObjArgs("
                "(PyObject*)&PyDict_Type, %s, NULL); %s" % (
5496
                    self.result(),
5497
                    self.starstar_arg.py_result(),
5498
                    code.error_goto_if_null(self.result(), self.pos)))
5499
            code.put_gotref(self.py_result())
5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529
            code.putln('}')
        self.starstar_arg.generate_disposal_code(code)
        self.starstar_arg.free_temps(code)

        if not self.keyword_args:
            return

        code.globalstate.use_utility_code(Nodes.raise_double_keywords_utility_code)
        for item in self.keyword_args:
            item.generate_evaluation_code(code)
            code.putln("if (unlikely(PyDict_GetItem(%s, %s))) {" % (
                    self.result(),
                    item.key.py_result()))
            # FIXME: find out function name at runtime!
            code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % (
                item.key.py_result(),
                code.error_goto(self.pos)))
            code.putln("}")
            code.put_error_if_neg(self.pos,
                "PyDict_SetItem(%s, %s, %s)" % (
                    self.result(),
                    item.key.py_result(),
                    item.value.py_result()))
            item.generate_disposal_code(code)
            item.free_temps(code)

    def annotate(self, code):
        self.starstar_arg.annotate(code)
        for item in self.keyword_args:
            item.annotate(code)
5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597

class PyClassMetaclassNode(ExprNode):
    # Helper class holds Python3 metaclass object
    #
    #  bases        ExprNode           Base class tuple (not owned by this node)
    #  mkw          ExprNode           Class keyword arguments (not owned by this node)

    subexprs = []

    def analyse_types(self, env):
        self.type = py_object_type
        self.is_temp = True

    def may_be_none(self):
        return True

    def generate_result_code(self, code):
        code.putln(
            "%s = __Pyx_Py3MetaclassGet(%s, %s); %s" % (
                self.result(),
                self.bases.result(),
                self.mkw.result(),
                code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.py_result())

class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
    # Helper class holds Python3 namespace object
    #
    # All this are not owned by this node
    #  metaclass    ExprNode           Metaclass object
    #  bases        ExprNode           Base class tuple
    #  mkw          ExprNode           Class keyword arguments
    #  doc          ExprNode or None   Doc string (owned)

    subexprs = ['doc']

    def analyse_types(self, env):
        self.bases.analyse_types(env)
        if self.doc:
            self.doc.analyse_types(env)
            self.doc = self.doc.coerce_to_pyobject(env)
        self.type = py_object_type
        self.is_temp = 1
        #TODO(craig,haoyu) This should be moved to a better place
        self.set_mod_name(env)

    def may_be_none(self):
        return True

    def generate_result_code(self, code):
        cname = code.intern_identifier(self.name)
        py_mod_name = self.get_py_mod_name(code)
        if self.doc:
            doc_code = self.doc.result()
        else:
            doc_code = '(PyObject *) NULL'
        code.putln(
            "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s); %s" % (
                self.result(),
                self.metaclass.result(),
                self.bases.result(),
                cname,
                self.mkw.result(),
                py_mod_name,
                doc_code,
                code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.py_result())

Robert Bradshaw's avatar
Robert Bradshaw committed
5598 5599 5600 5601 5602 5603 5604
class BoundMethodNode(ExprNode):
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs an bound method
    #  object from a class and a function.
    #
    #  function      ExprNode   Function object
    #  self_object   ExprNode   self object
5605

Robert Bradshaw's avatar
Robert Bradshaw committed
5606
    subexprs = ['function']
5607

Robert Bradshaw's avatar
Robert Bradshaw committed
5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623
    def analyse_types(self, env):
        self.function.analyse_types(env)
        self.type = py_object_type
        self.is_temp = 1

    gil_message = "Constructing an bound method"

    def generate_result_code(self, code):
        code.putln(
            "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
                self.result(),
                self.function.py_result(),
                self.self_object.py_result(),
                self.self_object.py_result(),
                code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5624

5625
class UnboundMethodNode(ExprNode):
William Stein's avatar
William Stein committed
5626 5627 5628 5629 5630
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs an unbound method
    #  object from a class and a function.
    #
    #  function      ExprNode   Function object
5631

5632 5633
    type = py_object_type
    is_temp = 1
5634

William Stein's avatar
William Stein committed
5635
    subexprs = ['function']
5636

William Stein's avatar
William Stein committed
5637 5638
    def analyse_types(self, env):
        self.function.analyse_types(env)
5639

5640 5641 5642
    def may_be_none(self):
        return False

5643 5644
    gil_message = "Constructing an unbound method"

William Stein's avatar
William Stein committed
5645
    def generate_result_code(self, code):
5646
        class_cname = code.pyclass_stack[-1].classobj.result()
William Stein's avatar
William Stein committed
5647
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
5648
            "%s = PyMethod_New(%s, 0, %s); %s" % (
5649
                self.result(),
William Stein's avatar
William Stein committed
5650
                self.function.py_result(),
5651
                class_cname,
5652
                code.error_goto_if_null(self.result(), self.pos)))
5653
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5654

Robert Bradshaw's avatar
Robert Bradshaw committed
5655

5656
class PyCFunctionNode(ExprNode, ModuleNameMixin):
William Stein's avatar
William Stein committed
5657 5658 5659 5660
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs a PyCFunction object
    #  from a PyMethodDef struct.
    #
5661
    #  pymethdef_cname   string             PyMethodDef structure
Robert Bradshaw's avatar
Robert Bradshaw committed
5662
    #  self_object       ExprNode or None
Robert Bradshaw's avatar
Robert Bradshaw committed
5663
    #  binding           bool
5664
    #  module_name       EncodedString      Name of defining module
5665 5666 5667
    #  code_object       CodeObjectNode     the PyCodeObject creator node

    subexprs = ['code_object']
Stefan Behnel's avatar
Stefan Behnel committed
5668

Robert Bradshaw's avatar
Robert Bradshaw committed
5669
    self_object = None
5670
    code_object = None
Robert Bradshaw's avatar
Robert Bradshaw committed
5671
    binding = False
5672

5673 5674
    type = py_object_type
    is_temp = 1
5675

William Stein's avatar
William Stein committed
5676
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
5677 5678
        if self.binding:
            env.use_utility_code(binding_cfunc_utility_code)
5679

5680 5681 5682
        #TODO(craig,haoyu) This should be moved to a better place
        self.set_mod_name(env)

5683 5684
    def may_be_none(self):
        return False
5685

5686 5687
    gil_message = "Constructing Python function"

Stefan Behnel's avatar
Stefan Behnel committed
5688
    def self_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5689 5690 5691 5692
        if self.self_object is None:
            self_result = "NULL"
        else:
            self_result = self.self_object.py_result()
Stefan Behnel's avatar
Stefan Behnel committed
5693 5694 5695
        return self_result

    def generate_result_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
5696
        if self.binding:
5697
            constructor = "__Pyx_CyFunction_NewEx"
5698 5699 5700 5701
            if self.code_object:
                code_object_result = ', ' + self.code_object.py_result()
            else:
                code_object_result = ', NULL'
Robert Bradshaw's avatar
Robert Bradshaw committed
5702
        else:
5703
            constructor = "PyCFunction_NewEx"
5704
            code_object_result = ''
5705
        py_mod_name = self.get_py_mod_name(code)
William Stein's avatar
William Stein committed
5706
        code.putln(
5707
            '%s = %s(&%s, %s, %s%s); %s' % (
5708
                self.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
5709
                constructor,
William Stein's avatar
William Stein committed
5710
                self.pymethdef_cname,
Stefan Behnel's avatar
Stefan Behnel committed
5711
                self.self_result_code(),
5712
                py_mod_name,
5713
                code_object_result,
5714
                code.error_goto_if_null(self.result(), self.pos)))
5715
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5716

Stefan Behnel's avatar
Stefan Behnel committed
5717 5718 5719
class InnerFunctionNode(PyCFunctionNode):
    # Special PyCFunctionNode that depends on a closure class
    #
Vitja Makarov's avatar
Vitja Makarov committed
5720

Robert Bradshaw's avatar
Robert Bradshaw committed
5721
    binding = True
Vitja Makarov's avatar
Vitja Makarov committed
5722 5723
    needs_self_code = True

Stefan Behnel's avatar
Stefan Behnel committed
5724
    def self_result_code(self):
Vitja Makarov's avatar
Vitja Makarov committed
5725 5726 5727
        if self.needs_self_code:
            return "((PyObject*)%s)" % (Naming.cur_scope_cname)
        return "NULL"
Stefan Behnel's avatar
Stefan Behnel committed
5728

5729 5730 5731 5732
class CodeObjectNode(ExprNode):
    # Create a PyCodeObject for a CyFunction instance.
    #
    # def_node   DefNode    the Python function node
5733
    # varnames   TupleNode  a tuple with all local variable names
5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744

    subexprs = ['varnames']
    is_temp = False

    def __init__(self, def_node):
        ExprNode.__init__(self, def_node.pos, def_node=def_node)
        args = list(def_node.args)
        if def_node.star_arg:
            args.append(def_node.star_arg)
        if def_node.starstar_arg:
            args.append(def_node.starstar_arg)
5745
        local_vars = [ arg for arg in def_node.local_scope.var_entries
5746
                       if arg.name ]
5747 5748
        self.varnames = TupleNode(
            def_node.pos,
5749
            args = [ IdentifierStringNode(arg.pos, value=arg.name)
5750
                     for arg in args + local_vars ],
5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775
            is_temp = 0,
            is_literal = 1)

    def calculate_result_code(self):
        return self.result_code

    def generate_result_code(self, code):
        self.result_code = code.get_py_const(py_object_type, 'codeobj_', cleanup_level=2)

        code = code.get_cached_constants_writer()
        code.mark_pos(self.pos)
        func = self.def_node
        func_name = code.get_py_string_const(
            func.name, identifier=True, is_str=False, unicode_value=func.name)
        # FIXME: better way to get the module file path at module init time? Encoding to use?
        file_path = StringEncoding.BytesLiteral(func.pos[0].get_filenametable_entry().encode('utf8'))
        file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True)

        code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, 0, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % (
            self.result_code,
            len(func.args),            # argcount
            func.num_kwonly_args,      # kwonlyargcount (Py3 only)
            len(self.varnames.args),   # nlocals
            Naming.empty_bytes,        # code
            Naming.empty_tuple,        # consts
5776 5777
            Naming.empty_tuple,        # names (FIXME)
            self.varnames.result(),    # varnames
5778 5779 5780 5781 5782 5783 5784 5785 5786 5787
            Naming.empty_tuple,        # freevars (FIXME)
            Naming.empty_tuple,        # cellvars (FIXME)
            file_path_const,           # filename
            func_name,                 # name
            self.pos[1],               # firstlineno
            Naming.empty_bytes,        # lnotab
            code.error_goto_if_null(self.result_code, self.pos),
            ))


Stefan Behnel's avatar
Stefan Behnel committed
5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803
class LambdaNode(InnerFunctionNode):
    # Lambda expression node (only used as a function reference)
    #
    # args          [CArgDeclNode]         formal arguments
    # star_arg      PyArgDeclNode or None  * argument
    # starstar_arg  PyArgDeclNode or None  ** argument
    # lambda_name   string                 a module-globally unique lambda name
    # result_expr   ExprNode
    # def_node      DefNode                the underlying function 'def' node

    child_attrs = ['def_node']

    def_node = None
    name = StringEncoding.EncodedString('<lambda>')

    def analyse_declarations(self, env):
5804 5805
        self.def_node.no_assignment_synthesis = True
        self.def_node.pymethdef_required = True
Stefan Behnel's avatar
Stefan Behnel committed
5806 5807 5808 5809
        self.def_node.analyse_declarations(env)
        self.pymethdef_cname = self.def_node.entry.pymethdef_cname
        env.add_lambda_def(self.def_node)

5810 5811 5812 5813 5814 5815 5816 5817
    def analyse_types(self, env):
        self.def_node.analyse_expressions(env)
        super(LambdaNode, self).analyse_types(env)

    def generate_result_code(self, code):
        self.def_node.generate_execution_code(code)
        super(LambdaNode, self).generate_result_code(code)

5818

5819 5820 5821 5822 5823 5824 5825 5826
class GeneratorExpressionNode(LambdaNode):
    # A generator expression, e.g.  (i for i in range(10))
    #
    # Result is a generator.
    #
    # loop      ForStatNode   the for-loop, containing a YieldExprNode
    # def_node  DefNode       the underlying generator 'def' node

5827
    name = StringEncoding.EncodedString('genexpr')
5828 5829 5830
    binding = False

    def analyse_declarations(self, env):
5831 5832 5833
        super(GeneratorExpressionNode, self).analyse_declarations(env)
        # No pymethdef required
        self.def_node.pymethdef_required = False
5834 5835
        # Force genexpr signature
        self.def_node.entry.signature = TypeSlots.pyfunction_noargs
5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846

    def generate_result_code(self, code):
        code.putln(
            '%s = %s(%s, NULL); %s' % (
                self.result(),
                self.def_node.entry.func_cname,
                self.self_result_code(),
                code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.py_result())


5847 5848 5849 5850 5851
class YieldExprNode(ExprNode):
    # Yield expression node
    #
    # arg         ExprNode   the value to return from the generator
    # label_name  string     name of the C label used for this yield
5852
    # label_num   integer    yield label number
5853 5854 5855

    subexprs = ['arg']
    type = py_object_type
5856
    label_num = 0
5857 5858

    def analyse_types(self, env):
5859 5860
        if not self.label_num:
            error(self.pos, "'yield' not supported here")
5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881
        self.is_temp = 1
        if self.arg is not None:
            self.arg.analyse_types(env)
            if not self.arg.type.is_pyobject:
                self.arg = self.arg.coerce_to_pyobject(env)

    def generate_evaluation_code(self, code):
        self.label_name = code.new_label('resume_from_yield')
        code.use_label(self.label_name)
        if self.arg:
            self.arg.generate_evaluation_code(code)
            self.arg.make_owned_reference(code)
            code.putln(
                "%s = %s;" % (
                    Naming.retval_cname,
                    self.arg.result_as(py_object_type)))
            self.arg.generate_post_assignment_code(code)
            #self.arg.generate_disposal_code(code)
            self.arg.free_temps(code)
        else:
            code.put_init_to_py_none(Naming.retval_cname, py_object_type)
5882
        saved = []
5883
        code.funcstate.closure_temps.reset()
5884
        for cname, type, manage_ref in code.funcstate.temps_in_use():
5885
            save_cname = code.funcstate.closure_temps.allocate_temp(type)
5886 5887 5888 5889
            saved.append((cname, save_cname, type))
            if type.is_pyobject:
                code.put_xgiveref(cname)
            code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cname))
5890

5891
        code.put_xgiveref(Naming.retval_cname)
5892
        code.put_finish_refcount_context()
Stefan Behnel's avatar
Stefan Behnel committed
5893
        code.putln("/* return from generator, yielding value */")
5894 5895 5896
        code.putln("%s->%s.resume_label = %d;" % (Naming.cur_scope_cname, Naming.obj_base_cname, self.label_num))
        code.putln("return %s;" % Naming.retval_cname);
        code.put_label(self.label_name)
5897 5898 5899 5900 5901 5902
        for cname, save_cname, type in saved:
            code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname))
            if type.is_pyobject:
                code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname))
            if type.is_pyobject:
                code.put_xgotref(cname)
5903 5904 5905 5906 5907 5908 5909 5910
        if self.result_is_used:
            self.allocate_temp_result(code)
            code.putln('%s = %s; %s' %
                       (self.result(), Naming.sent_value_cname,
                        code.error_goto_if_null(self.result(), self.pos)))
            code.put_incref(self.result(), py_object_type)
        else:
            code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos))
5911

Vitja Makarov's avatar
Vitja Makarov committed
5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927

class GlobalsExprNode(AtomicExprNode):
    type = dict_type
    is_temp = 1

    def analyse_types(self, env):
        env.use_utility_code(Builtin.globals_utility_code)

    gil_message = "Constructing globals dict"

    def generate_result_code(self, code):
        code.putln('%s = __Pyx_Globals(); %s' % (
            self.result(),
            code.error_goto_if_null(self.result(), self.pos)))
        code.put_gotref(self.result())

Vitja Makarov's avatar
Vitja Makarov committed
5928

5929
class FuncLocalsExprNode(DictNode):
Vitja Makarov's avatar
Vitja Makarov committed
5930 5931 5932 5933 5934 5935 5936 5937
    def __init__(self, pos, env):
        local_vars = [var.name for var in env.entries.values() if var.name]
        items = [DictItemNode(pos, key=IdentifierStringNode(pos, value=var),
                              value=NameNode(pos, name=var, allow_null=True))
                 for var in local_vars]
        DictNode.__init__(self, pos, key_value_pairs=items,
                          exclude_null_values=True)

5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962

class PyClassLocalsExprNode(AtomicExprNode):
    def __init__(self, pos, pyclass_dict):
        AtomicExprNode.__init__(self, pos)
        self.pyclass_dict = pyclass_dict

    def analyse_types(self, env):
        self.type = self.pyclass_dict.type
        self.is_tmep = 0

    def result(self):
        return self.pyclass_dict.result()

    def generate_result_code(self, code):
        pass


def LocalsExprNode(pos, scope_node, env):
    if env.is_module_scope:
        return GlobalsExprNode(pos)
    if env.is_py_class_scope:
        return PyClassLocalsExprNode(pos, scope_node.dict)
    return FuncLocalsExprNode(pos, env)


William Stein's avatar
William Stein committed
5963 5964 5965 5966 5967 5968
#-------------------------------------------------------------------
#
#  Unary operator nodes
#
#-------------------------------------------------------------------

5969 5970 5971 5972 5973 5974 5975
compile_time_unary_operators = {
    'not': operator.not_,
    '~': operator.inv,
    '-': operator.neg,
    '+': operator.pos,
}

5976
class UnopNode(ExprNode):
William Stein's avatar
William Stein committed
5977 5978 5979 5980 5981 5982 5983 5984 5985 5986
    #  operator     string
    #  operand      ExprNode
    #
    #  Processing during analyse_expressions phase:
    #
    #    analyse_c_operation
    #      Called when the operand is not a pyobject.
    #      - Check operand type and coerce if needed.
    #      - Determine result type and result code fragment.
    #      - Allocate temporary for result if needed.
5987

William Stein's avatar
William Stein committed
5988
    subexprs = ['operand']
Robert Bradshaw's avatar
Robert Bradshaw committed
5989
    infix = True
5990 5991 5992 5993

    def calculate_constant_result(self):
        func = compile_time_unary_operators[self.operator]
        self.constant_result = func(self.operand.constant_result)
5994

5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005
    def compile_time_value(self, denv):
        func = compile_time_unary_operators.get(self.operator)
        if not func:
            error(self.pos,
                "Unary '%s' not supported in compile-time expression"
                    % self.operator)
        operand = self.operand.compile_time_value(denv)
        try:
            return func(operand)
        except Exception, e:
            self.compile_time_value_error(e)
6006

6007
    def infer_type(self, env):
6008 6009 6010 6011 6012
        operand_type = self.operand.infer_type(env)
        if operand_type.is_pyobject:
            return py_object_type
        else:
            return operand_type
6013

William Stein's avatar
William Stein committed
6014 6015 6016 6017 6018 6019
    def analyse_types(self, env):
        self.operand.analyse_types(env)
        if self.is_py_operation():
            self.coerce_operand_to_pyobject(env)
            self.type = py_object_type
            self.is_temp = 1
6020 6021
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
6022 6023
        else:
            self.analyse_c_operation(env)
6024

William Stein's avatar
William Stein committed
6025
    def check_const(self):
6026
        return self.operand.check_const()
6027

William Stein's avatar
William Stein committed
6028 6029
    def is_py_operation(self):
        return self.operand.type.is_pyobject
6030

6031
    def nogil_check(self, env):
6032
        if self.is_py_operation():
6033
            self.gil_error()
6034

Danilo Freitas's avatar
Danilo Freitas committed
6035
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
6036
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
6037
        return type.is_cpp_class
6038

William Stein's avatar
William Stein committed
6039 6040
    def coerce_operand_to_pyobject(self, env):
        self.operand = self.operand.coerce_to_pyobject(env)
6041

William Stein's avatar
William Stein committed
6042 6043 6044
    def generate_result_code(self, code):
        if self.operand.type.is_pyobject:
            self.generate_py_operation_code(code)
6045

William Stein's avatar
William Stein committed
6046 6047 6048
    def generate_py_operation_code(self, code):
        function = self.py_operation_function()
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
6049
            "%s = %s(%s); %s" % (
6050 6051
                self.result(),
                function,
William Stein's avatar
William Stein committed
6052
                self.operand.py_result(),
6053
                code.error_goto_if_null(self.result(), self.pos)))
6054
        code.put_gotref(self.py_result())
6055

William Stein's avatar
William Stein committed
6056 6057 6058 6059 6060 6061
    def type_error(self):
        if not self.operand.type.is_error:
            error(self.pos, "Invalid operand type for '%s' (%s)" %
                (self.operator, self.operand.type))
        self.type = PyrexTypes.error_type

Danilo Freitas's avatar
Danilo Freitas committed
6062
    def analyse_cpp_operation(self, env):
6063
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
6064
        if type.is_ptr:
Danilo Freitas's avatar
Danilo Freitas committed
6065
            type = type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
6066
        function = type.scope.lookup("operator%s" % self.operator)
Danilo Freitas's avatar
Danilo Freitas committed
6067 6068
        if not function:
            error(self.pos, "'%s' operator not defined for %s"
6069
                % (self.operator, type))
Danilo Freitas's avatar
Danilo Freitas committed
6070 6071
            self.type_error()
            return
6072 6073 6074 6075
        func_type = function.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        self.type = func_type.return_type
Danilo Freitas's avatar
Danilo Freitas committed
6076

William Stein's avatar
William Stein committed
6077

6078
class NotNode(ExprNode):
William Stein's avatar
William Stein committed
6079 6080 6081
    #  'not' operator
    #
    #  operand   ExprNode
6082

6083
    type = PyrexTypes.c_bint_type
6084

6085
    subexprs = ['operand']
6086

6087 6088 6089
    def calculate_constant_result(self):
        self.constant_result = not self.operand.constant_result

6090 6091 6092 6093 6094 6095 6096
    def compile_time_value(self, denv):
        operand = self.operand.compile_time_value(denv)
        try:
            return not operand
        except Exception, e:
            self.compile_time_value_error(e)

6097 6098
    def infer_type(self, env):
        return PyrexTypes.c_bint_type
6099

William Stein's avatar
William Stein committed
6100 6101 6102
    def analyse_types(self, env):
        self.operand.analyse_types(env)
        self.operand = self.operand.coerce_to_boolean(env)
6103

William Stein's avatar
William Stein committed
6104
    def calculate_result_code(self):
6105
        return "(!%s)" % self.operand.result()
6106

William Stein's avatar
William Stein committed
6107 6108 6109 6110 6111 6112
    def generate_result_code(self, code):
        pass


class UnaryPlusNode(UnopNode):
    #  unary '+' operator
6113

William Stein's avatar
William Stein committed
6114
    operator = '+'
6115

William Stein's avatar
William Stein committed
6116
    def analyse_c_operation(self, env):
Lisandro Dalcin's avatar
Lisandro Dalcin committed
6117
        self.type = PyrexTypes.widest_numeric_type(
Robert Bradshaw's avatar
Robert Bradshaw committed
6118
            self.operand.type, PyrexTypes.c_int_type)
6119

William Stein's avatar
William Stein committed
6120 6121
    def py_operation_function(self):
        return "PyNumber_Positive"
6122

William Stein's avatar
William Stein committed
6123
    def calculate_result_code(self):
6124 6125 6126 6127
        if self.is_cpp_operation():
            return "(+%s)" % self.operand.result()
        else:
            return self.operand.result()
William Stein's avatar
William Stein committed
6128 6129 6130 6131


class UnaryMinusNode(UnopNode):
    #  unary '-' operator
6132

William Stein's avatar
William Stein committed
6133
    operator = '-'
6134

William Stein's avatar
William Stein committed
6135 6136
    def analyse_c_operation(self, env):
        if self.operand.type.is_numeric:
6137 6138
            self.type = PyrexTypes.widest_numeric_type(
                self.operand.type, PyrexTypes.c_int_type)
6139 6140
        elif self.operand.type.is_enum:
            self.type = PyrexTypes.c_int_type
William Stein's avatar
William Stein committed
6141 6142
        else:
            self.type_error()
Robert Bradshaw's avatar
Robert Bradshaw committed
6143
        if self.type.is_complex:
6144
            self.infix = False
6145

William Stein's avatar
William Stein committed
6146 6147
    def py_operation_function(self):
        return "PyNumber_Negative"
6148

William Stein's avatar
William Stein committed
6149
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
6150 6151 6152 6153
        if self.infix:
            return "(-%s)" % self.operand.result()
        else:
            return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
William Stein's avatar
William Stein committed
6154

6155 6156 6157 6158 6159
    def get_constant_c_result_code(self):
        value = self.operand.get_constant_c_result_code()
        if value:
            return "(-%s)" % (value)

William Stein's avatar
William Stein committed
6160 6161 6162 6163 6164
class TildeNode(UnopNode):
    #  unary '~' operator

    def analyse_c_operation(self, env):
        if self.operand.type.is_int:
6165 6166
            self.type = PyrexTypes.widest_numeric_type(
                self.operand.type, PyrexTypes.c_int_type)
6167 6168
        elif self.operand.type.is_enum:
            self.type = PyrexTypes.c_int_type
William Stein's avatar
William Stein committed
6169 6170 6171 6172 6173
        else:
            self.type_error()

    def py_operation_function(self):
        return "PyNumber_Invert"
6174

William Stein's avatar
William Stein committed
6175
    def calculate_result_code(self):
6176
        return "(~%s)" % self.operand.result()
William Stein's avatar
William Stein committed
6177 6178


6179 6180
class CUnopNode(UnopNode):

Robert Bradshaw's avatar
Robert Bradshaw committed
6181 6182 6183
    def is_py_operation(self):
        return False

6184 6185
class DereferenceNode(CUnopNode):
    #  unary * operator
6186 6187

    operator = '*'
6188

Robert Bradshaw's avatar
Robert Bradshaw committed
6189 6190 6191 6192 6193 6194 6195 6196
    def analyse_c_operation(self, env):
        if self.operand.type.is_ptr:
            self.type = self.operand.type.base_type
        else:
            self.type_error()

    def calculate_result_code(self):
        return "(*%s)" % self.operand.result()
William Stein's avatar
William Stein committed
6197 6198


6199 6200
class DecrementIncrementNode(CUnopNode):
    #  unary ++/-- operator
6201

6202
    def analyse_c_operation(self, env):
6203 6204 6205 6206
        if self.operand.type.is_numeric:
            self.type = PyrexTypes.widest_numeric_type(
                self.operand.type, PyrexTypes.c_int_type)
        elif self.operand.type.is_ptr:
6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220
            self.type = self.operand.type
        else:
            self.type_error()

    def calculate_result_code(self):
        if self.is_prefix:
            return "(%s%s)" % (self.operator, self.operand.result())
        else:
            return "(%s%s)" % (self.operand.result(), self.operator)

def inc_dec_constructor(is_prefix, operator):
    return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds)


6221
class AmpersandNode(ExprNode):
William Stein's avatar
William Stein committed
6222 6223 6224
    #  The C address-of operator.
    #
    #  operand  ExprNode
6225

William Stein's avatar
William Stein committed
6226
    subexprs = ['operand']
6227

6228 6229
    def infer_type(self, env):
        return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
William Stein's avatar
William Stein committed
6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240

    def analyse_types(self, env):
        self.operand.analyse_types(env)
        argtype = self.operand.type
        if not (argtype.is_cfunction or self.operand.is_lvalue()):
            self.error("Taking address of non-lvalue")
            return
        if argtype.is_pyobject:
            self.error("Cannot take address of Python variable")
            return
        self.type = PyrexTypes.c_ptr_type(argtype)
6241

William Stein's avatar
William Stein committed
6242
    def check_const(self):
6243
        return self.operand.check_const_addr()
6244

William Stein's avatar
William Stein committed
6245 6246 6247 6248
    def error(self, mess):
        error(self.pos, mess)
        self.type = PyrexTypes.error_type
        self.result_code = "<error>"
6249

William Stein's avatar
William Stein committed
6250
    def calculate_result_code(self):
6251
        return "(&%s)" % self.operand.result()
William Stein's avatar
William Stein committed
6252 6253 6254

    def generate_result_code(self, code):
        pass
6255

William Stein's avatar
William Stein committed
6256 6257 6258 6259 6260 6261 6262 6263

unop_node_classes = {
    "+":  UnaryPlusNode,
    "-":  UnaryMinusNode,
    "~":  TildeNode,
}

def unop_node(pos, operator, operand):
6264
    # Construct unnop node of appropriate class for
William Stein's avatar
William Stein committed
6265
    # given operator.
6266
    if isinstance(operand, IntNode) and operator == '-':
6267
        return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)))
Robert Bradshaw's avatar
Robert Bradshaw committed
6268 6269
    elif isinstance(operand, UnopNode) and operand.operator == operator:
        warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
6270 6271
    return unop_node_classes[operator](pos,
        operator = operator,
William Stein's avatar
William Stein committed
6272 6273 6274
        operand = operand)


6275
class TypecastNode(ExprNode):
William Stein's avatar
William Stein committed
6276 6277
    #  C type cast
    #
6278
    #  operand      ExprNode
William Stein's avatar
William Stein committed
6279 6280
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
6281 6282 6283
    #
    #  If used from a transform, one can if wanted specify the attribute
    #  "type" directly and leave base_type and declarator to None
6284

William Stein's avatar
William Stein committed
6285
    subexprs = ['operand']
6286
    base_type = declarator = type = None
6287

Robert Bradshaw's avatar
Robert Bradshaw committed
6288
    def type_dependencies(self, env):
6289
        return ()
6290

Robert Bradshaw's avatar
Robert Bradshaw committed
6291
    def infer_type(self, env):
6292 6293 6294 6295
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
        return self.type
6296

William Stein's avatar
William Stein committed
6297
    def analyse_types(self, env):
6298 6299 6300
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
6301 6302 6303 6304
        if self.type.is_cfunction:
            error(self.pos,
                "Cannot cast to a function type")
            self.type = PyrexTypes.error_type
William Stein's avatar
William Stein committed
6305 6306 6307
        self.operand.analyse_types(env)
        to_py = self.type.is_pyobject
        from_py = self.operand.type.is_pyobject
6308 6309
        if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
            error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
William Stein's avatar
William Stein committed
6310
        if to_py and not from_py:
6311 6312 6313 6314 6315 6316
            if self.type is bytes_type and self.operand.type.is_int:
                # FIXME: the type cast node isn't needed in this case
                # and can be dropped once analyse_types() can return a
                # different node
                self.operand = CoerceIntToBytesNode(self.operand, env)
            elif self.operand.type.can_coerce_to_pyobject(env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6317
                self.result_ctype = py_object_type
6318
                self.operand = self.operand.coerce_to_pyobject(env)
6319
            else:
6320 6321 6322 6323
                if self.operand.type.is_ptr:
                    if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
                        error(self.pos, "Python objects cannot be cast from pointers of primitive types")
                else:
6324
                    # Should this be an error?
6325
                    warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
6326
                self.operand = self.operand.coerce_to_simple(env)
6327
        elif from_py and not to_py:
6328
            if self.type.create_from_py_utility_code(env):
6329
                self.operand = self.operand.coerce_to(self.type, env)
6330 6331 6332
            elif self.type.is_ptr:
                if not (self.type.base_type.is_void or self.type.base_type.is_struct):
                    error(self.pos, "Python objects cannot be cast to pointers of primitive types")
6333 6334
            else:
                warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
6335 6336
        elif from_py and to_py:
            if self.typecheck and self.type.is_extension_type:
6337
                self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
6338 6339
        elif self.type.is_complex and self.operand.type.is_complex:
            self.operand = self.operand.coerce_to_simple(env)
6340

Stefan Behnel's avatar
Stefan Behnel committed
6341
    def is_simple(self):
6342 6343
        # either temp or a C cast => no side effects other than the operand's
        return self.operand.is_simple()
Stefan Behnel's avatar
Stefan Behnel committed
6344

6345 6346 6347
    def nonlocally_immutable(self):
        return self.operand.nonlocally_immutable()

6348 6349 6350
    def nogil_check(self, env):
        if self.type and self.type.is_pyobject and self.is_temp:
            self.gil_error()
6351

William Stein's avatar
William Stein committed
6352
    def check_const(self):
6353
        return self.operand.check_const()
Stefan Behnel's avatar
Stefan Behnel committed
6354 6355

    def calculate_constant_result(self):
6356 6357 6358
        # we usually do not know the result of a type cast at code
        # generation time
        pass
6359

William Stein's avatar
William Stein committed
6360
    def calculate_result_code(self):
6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371
        if self.type.is_complex:
            operand_result = self.operand.result()
            if self.operand.type.is_complex:
                real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result)
                imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result)
            else:
                real_part = self.type.real_type.cast_code(operand_result)
                imag_part = "0"
            return "%s(%s, %s)" % (
                    self.type.from_parts,
                    real_part,
6372
                    imag_part)
6373 6374
        else:
            return self.type.cast_code(self.operand.result())
6375

6376 6377 6378 6379
    def get_constant_c_result_code(self):
        operand_result = self.operand.get_constant_c_result_code()
        if operand_result:
            return self.type.cast_code(operand_result)
6380

William Stein's avatar
William Stein committed
6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391
    def result_as(self, type):
        if self.type.is_pyobject and not self.is_temp:
            #  Optimise away some unnecessary casting
            return self.operand.result_as(type)
        else:
            return ExprNode.result_as(self, type)

    def generate_result_code(self, code):
        if self.is_temp:
            code.putln(
                "%s = (PyObject *)%s;" % (
6392 6393 6394
                    self.result(),
                    self.operand.result()))
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
6395 6396


6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408
ERR_START = "Start may not be given"
ERR_NOT_STOP = "Stop must be provided to indicate shape"
ERR_STEPS = ("Strides may only be given to indicate contiguity. "
             "Consider slicing it after conversion")
ERR_NOT_POINTER = "Can only create cython.array from pointer"
ERR_BASE_TYPE = "Pointer base type does not match cython.array base type"

class CythonArrayNode(ExprNode):
    """
    Used when a pointer of base_type is cast to a memoryviewslice with that
    base type. i.e.

6409
        <int[:M:1, :N]> p
6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468

    creates a fortran-contiguous cython.array.

    We leave the type set to object so coercions to object are more efficient
    and less work. Acquiring a memoryviewslice from this will be just as
    efficient. ExprNode.coerce_to() will do the additional typecheck on
    self.compile_time_type
    """

    subexprs = ['operand', 'shapes']

    shapes = None
    is_temp = True
    mode = "c"

    shape_type = PyrexTypes.c_py_ssize_t_type

    def analyse_types(self, env):
        import MemoryView

        self.type = error_type
        self.shapes = []

        for axis_no, axis in enumerate(self.base_type_node.axes):
            if not axis.start.is_none:
                return error(axis.start.pos, ERR_START)

            if axis.stop.is_none:
                return error(axis.pos, ERR_NOT_STOP)

            axis.stop.analyse_types(env)
            shape = axis.stop.coerce_to(self.shape_type, env)
            if not shape.is_literal:
                shape.coerce_to_temp(env)

            self.shapes.append(shape)

            if not axis.stop.type.is_int:
                return error(axis.stop.pos, "Expected an integer type")

            first_or_last = axis_no in (0, len(self.base_type_node.axes) - 1)
            if not axis.step.is_none and first_or_last:
                axis.step.analyse_types(env)
                if (not axis.step.type.is_int and axis.step.is_literal and not
                        axis.step.type.is_error):
                    return error(axis.step.pos, "Expected an integer literal")

                if axis.step.compile_time_value(env) != 1:
                    return error(axis.step.pos, ERR_STEPS)

                if axis_no == 0:
                    self.mode = "fortran"

            elif axis.step and not first_or_last:
                return error(axis.step.pos, ERR_STEPS)

        self.operand.analyse_types(env)
        array_dtype = self.base_type_node.base_type_node.analyse(env)

6469 6470
        MemoryView.validate_memslice_dtype(self.pos, array_dtype)

6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487
        if not self.operand.type.is_ptr:
            return error(self.operand.pos, ERR_NOT_POINTER)

        elif not self.operand.type.base_type.same_as(array_dtype):
            return error(self.operand.pos, ERR_BASE_TYPE)

        if not self.operand.is_name:
            self.operand = self.operand.coerce_to_temp(env)

        axes = [('direct', 'follow')] * len(self.base_type_node.axes)
        if self.mode == "fortran":
            axes[0] = ('direct', 'contig')
        else:
            axes[-1] = ('direct', 'contig')

        self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes)
        #self.type = py_object_type
6488
        self.type = self.get_cython_array_type(env)
6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499
        assert self.type

        env.use_utility_code(MemoryView.cython_array_utility_code)
        env.use_utility_code(MemoryView.typeinfo_to_format_code)

    def allocate_temp_result(self, code):
        if self.temp_code:
            raise RuntimeError("temp allocated mulitple times")

        self.temp_code = code.funcstate.allocate_temp(self.type, True)

6500 6501 6502 6503 6504 6505
    def infer_type(self, env):
        return self.get_cython_array_type(env)

    def get_cython_array_type(self, env):
        return env.global_scope().context.cython_scope.lookup("array").type

6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540
    def generate_result_code(self, code):
        import Buffer

        shapes = [self.shape_type.cast_code(shape.result())
                      for shape in self.shapes]
        dtype = self.coercion_type.dtype

        shapes_temp = code.funcstate.allocate_temp(py_object_type, True)
        format_temp = code.funcstate.allocate_temp(py_object_type, True)

        itemsize = "sizeof(%s)" % dtype.declaration_code("")
        type_info = Buffer.get_type_information_cname(code, dtype)

        code.putln("if (!%s) {" % self.operand.result())
        code.putln(    'PyErr_SetString(PyExc_ValueError,'
                            '"Cannot create cython.array from NULL pointer");')
        code.putln(code.error_goto(self.operand.pos))
        code.putln("}")

        code.putln("%s = __pyx_format_from_typeinfo(&%s);" %
                                                (format_temp, type_info))
        code.putln('%s = Py_BuildValue("(%s)", %s);' % (shapes_temp,
                                                        "n" * len(shapes),
                                                        ", ".join(shapes)))

        err = "!%s || !%s || !PyBytes_Check(%s)" % (format_temp, shapes_temp,
                                                    format_temp)
        code.putln(code.error_goto_if(err, self.pos))
        code.put_gotref(format_temp)
        code.put_gotref(shapes_temp)

        tup = (self.result(), shapes_temp, itemsize, format_temp,
               self.mode, self.operand.result())
        code.putln('%s = __pyx_array_new('
                            '%s, %s, PyBytes_AS_STRING(%s), '
6541
                            '(char *) "%s", (char *) %s);' % tup)
6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552
        code.putln(code.error_goto_if_null(self.result(), self.pos))
        code.put_gotref(self.result())

        def dispose(temp):
            code.put_decref_clear(temp, py_object_type)
            code.funcstate.release_temp(temp)

        dispose(shapes_temp)
        dispose(format_temp)


6553
class SizeofNode(ExprNode):
William Stein's avatar
William Stein committed
6554
    #  Abstract base class for sizeof(x) expression nodes.
6555

6556
    type = PyrexTypes.c_size_t_type
William Stein's avatar
William Stein committed
6557 6558

    def check_const(self):
6559
        return True
William Stein's avatar
William Stein committed
6560 6561 6562 6563 6564 6565 6566 6567 6568 6569

    def generate_result_code(self, code):
        pass


class SizeofTypeNode(SizeofNode):
    #  C sizeof function applied to a type
    #
    #  base_type   CBaseTypeNode
    #  declarator  CDeclaratorNode
6570

William Stein's avatar
William Stein committed
6571
    subexprs = []
6572
    arg_type = None
6573

William Stein's avatar
William Stein committed
6574
    def analyse_types(self, env):
6575 6576
        # we may have incorrectly interpreted a dotted name as a type rather than an attribute
        # this could be better handled by more uniformly treating types as runtime-available objects
6577
        if 0 and self.base_type.module_path:
6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588
            path = self.base_type.module_path
            obj = env.lookup(path[0])
            if obj.as_module is None:
                operand = NameNode(pos=self.pos, name=path[0])
                for attr in path[1:]:
                    operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
                operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
                self.operand = operand
                self.__class__ = SizeofVarNode
                self.analyse_types(env)
                return
6589 6590 6591 6592
        if self.arg_type is None:
            base_type = self.base_type.analyse(env)
            _, arg_type = self.declarator.analyse(base_type, env)
            self.arg_type = arg_type
6593
        self.check_type()
6594

6595 6596
    def check_type(self):
        arg_type = self.arg_type
6597
        if arg_type.is_pyobject and not arg_type.is_extension_type:
William Stein's avatar
William Stein committed
6598 6599 6600 6601 6602
            error(self.pos, "Cannot take sizeof Python object")
        elif arg_type.is_void:
            error(self.pos, "Cannot take sizeof void")
        elif not arg_type.is_complete():
            error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
6603

William Stein's avatar
William Stein committed
6604
    def calculate_result_code(self):
6605 6606 6607 6608 6609 6610
        if self.arg_type.is_extension_type:
            # the size of the pointer is boring
            # we want the size of the actual struct
            arg_code = self.arg_type.declaration_code("", deref=1)
        else:
            arg_code = self.arg_type.declaration_code("")
William Stein's avatar
William Stein committed
6611
        return "(sizeof(%s))" % arg_code
6612

William Stein's avatar
William Stein committed
6613 6614 6615 6616 6617

class SizeofVarNode(SizeofNode):
    #  C sizeof function applied to a variable
    #
    #  operand   ExprNode
6618

William Stein's avatar
William Stein committed
6619
    subexprs = ['operand']
6620

William Stein's avatar
William Stein committed
6621
    def analyse_types(self, env):
6622 6623 6624 6625 6626 6627 6628 6629 6630
        # We may actually be looking at a type rather than a variable...
        # If we are, traditional analysis would fail...
        operand_as_type = self.operand.analyse_as_type(env)
        if operand_as_type:
            self.arg_type = operand_as_type
            self.__class__ = SizeofTypeNode
            self.check_type()
        else:
            self.operand.analyse_types(env)
6631

William Stein's avatar
William Stein committed
6632
    def calculate_result_code(self):
6633
        return "(sizeof(%s))" % self.operand.result()
6634

William Stein's avatar
William Stein committed
6635 6636 6637
    def generate_result_code(self, code):
        pass

Robert Bradshaw's avatar
Robert Bradshaw committed
6638
class TypeofNode(ExprNode):
6639 6640 6641
    #  Compile-time type of an expression, as a string.
    #
    #  operand   ExprNode
Robert Bradshaw's avatar
Robert Bradshaw committed
6642
    #  literal   StringNode # internal
6643

Robert Bradshaw's avatar
Robert Bradshaw committed
6644 6645
    literal = None
    type = py_object_type
6646

Stefan Behnel's avatar
Stefan Behnel committed
6647
    subexprs = ['literal'] # 'operand' will be ignored after type analysis!
6648

6649 6650
    def analyse_types(self, env):
        self.operand.analyse_types(env)
6651 6652
        self.literal = StringNode(
            self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
Robert Bradshaw's avatar
Robert Bradshaw committed
6653 6654
        self.literal.analyse_types(env)
        self.literal = self.literal.coerce_to_pyobject(env)
6655 6656 6657 6658

    def may_be_none(self):
        return False

6659
    def generate_evaluation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
6660
        self.literal.generate_evaluation_code(code)
6661

Robert Bradshaw's avatar
Robert Bradshaw committed
6662 6663
    def calculate_result_code(self):
        return self.literal.calculate_result_code()
William Stein's avatar
William Stein committed
6664 6665 6666 6667 6668 6669 6670

#-------------------------------------------------------------------
#
#  Binary operator nodes
#
#-------------------------------------------------------------------

Stefan Behnel's avatar
Stefan Behnel committed
6671 6672 6673
def _not_in(x, seq):
    return x not in seq

6674 6675 6676
compile_time_binary_operators = {
    '<': operator.lt,
    '<=': operator.le,
6677
    '==': operator.eq,
6678 6679 6680 6681 6682 6683 6684
    '!=': operator.ne,
    '>=': operator.ge,
    '>': operator.gt,
    'is': operator.is_,
    'is_not': operator.is_not,
    '+': operator.add,
    '&': operator.and_,
6685
    '/': operator.truediv,
6686 6687 6688 6689 6690 6691 6692 6693 6694
    '//': operator.floordiv,
    '<<': operator.lshift,
    '%': operator.mod,
    '*': operator.mul,
    '|': operator.or_,
    '**': operator.pow,
    '>>': operator.rshift,
    '-': operator.sub,
    '^': operator.xor,
Stefan Behnel's avatar
Stefan Behnel committed
6695 6696
    'in': operator.contains,
    'not_in': _not_in,
6697 6698 6699 6700 6701 6702 6703
}

def get_compile_time_binop(node):
    func = compile_time_binary_operators.get(node.operator)
    if not func:
        error(node.pos,
            "Binary '%s' not supported in compile-time expression"
6704
                % node.operator)
6705 6706
    return func

6707
class BinopNode(ExprNode):
William Stein's avatar
William Stein committed
6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718
    #  operator     string
    #  operand1     ExprNode
    #  operand2     ExprNode
    #
    #  Processing during analyse_expressions phase:
    #
    #    analyse_c_operation
    #      Called when neither operand is a pyobject.
    #      - Check operand types and coerce if needed.
    #      - Determine result type and result code fragment.
    #      - Allocate temporary for result if needed.
6719

William Stein's avatar
William Stein committed
6720
    subexprs = ['operand1', 'operand2']
6721
    inplace = False
6722 6723 6724 6725 6726 6727 6728

    def calculate_constant_result(self):
        func = compile_time_binary_operators[self.operator]
        self.constant_result = func(
            self.operand1.constant_result,
            self.operand2.constant_result)

6729 6730 6731 6732 6733 6734 6735 6736
    def compile_time_value(self, denv):
        func = get_compile_time_binop(self)
        operand1 = self.operand1.compile_time_value(denv)
        operand2 = self.operand2.compile_time_value(denv)
        try:
            return func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)
6737

6738 6739
    def infer_type(self, env):
        return self.result_type(self.operand1.infer_type(env),
Robert Bradshaw's avatar
Robert Bradshaw committed
6740
                                self.operand2.infer_type(env))
6741

William Stein's avatar
William Stein committed
6742 6743 6744
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
6745
        self.analyse_operation(env)
6746

Robert Bradshaw's avatar
Robert Bradshaw committed
6747
    def analyse_operation(self, env):
William Stein's avatar
William Stein committed
6748 6749
        if self.is_py_operation():
            self.coerce_operands_to_pyobjects(env)
6750 6751 6752
            self.type = self.result_type(self.operand1.type,
                                         self.operand2.type)
            assert self.type.is_pyobject
William Stein's avatar
William Stein committed
6753
            self.is_temp = 1
DaniloFreitas's avatar
DaniloFreitas committed
6754 6755
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
6756 6757
        else:
            self.analyse_c_operation(env)
6758

William Stein's avatar
William Stein committed
6759
    def is_py_operation(self):
6760
        return self.is_py_operation_types(self.operand1.type, self.operand2.type)
6761

6762 6763 6764
    def is_py_operation_types(self, type1, type2):
        return type1.is_pyobject or type2.is_pyobject

DaniloFreitas's avatar
DaniloFreitas committed
6765
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
6766 6767
        return (self.operand1.type.is_cpp_class
            or self.operand2.type.is_cpp_class)
6768

6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784
    def analyse_cpp_operation(self, env):
        type1 = self.operand1.type
        type2 = self.operand2.type
        entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
        if not entry:
            self.type_error()
            return
        func_type = entry.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        if len(func_type.args) == 1:
            self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
        else:
            self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
            self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
        self.type = func_type.return_type
6785

6786 6787
    def result_type(self, type1, type2):
        if self.is_py_operation_types(type1, type2):
6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805
            if type2.is_string:
                type2 = Builtin.bytes_type
            if type1.is_string:
                type1 = Builtin.bytes_type
            elif self.operator == '%' \
                     and type1 in (Builtin.str_type, Builtin.unicode_type):
                # note that  b'%s' % b'abc'  doesn't work in Py3
                return type1
            if type1.is_builtin_type:
                if type1 is type2:
                    if self.operator in '**%+|&^':
                        # FIXME: at least these operators should be safe - others?
                        return type1
                elif self.operator == '*':
                    if type1 in (Builtin.bytes_type, Builtin.str_type, Builtin.unicode_type):
                        return type1
                    # multiplication of containers/numbers with an
                    # integer value always (?) returns the same type
6806
                    if type2.is_int:
6807
                        return type1
6808 6809 6810 6811
            elif type2.is_builtin_type and type1.is_int and self.operator == '*':
                # multiplication of containers/numbers with an
                # integer value always (?) returns the same type
                return type2
6812 6813 6814
            return py_object_type
        else:
            return self.compute_c_result_type(type1, type2)
6815

6816
    def nogil_check(self, env):
6817
        if self.is_py_operation():
6818
            self.gil_error()
6819

William Stein's avatar
William Stein committed
6820 6821 6822
    def coerce_operands_to_pyobjects(self, env):
        self.operand1 = self.operand1.coerce_to_pyobject(env)
        self.operand2 = self.operand2.coerce_to_pyobject(env)
6823

William Stein's avatar
William Stein committed
6824
    def check_const(self):
6825
        return self.operand1.check_const() and self.operand2.check_const()
6826

William Stein's avatar
William Stein committed
6827 6828 6829 6830
    def generate_result_code(self, code):
        #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
        if self.operand1.type.is_pyobject:
            function = self.py_operation_function()
6831
            if self.operator == '**':
William Stein's avatar
William Stein committed
6832 6833 6834 6835
                extra_args = ", Py_None"
            else:
                extra_args = ""
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
6836
                "%s = %s(%s, %s%s); %s" % (
6837 6838
                    self.result(),
                    function,
William Stein's avatar
William Stein committed
6839 6840 6841
                    self.operand1.py_result(),
                    self.operand2.py_result(),
                    extra_args,
6842
                    code.error_goto_if_null(self.result(), self.pos)))
6843
            code.put_gotref(self.py_result())
6844

William Stein's avatar
William Stein committed
6845 6846 6847 6848
    def type_error(self):
        if not (self.operand1.type.is_error
                or self.operand2.type.is_error):
            error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
6849
                (self.operator, self.operand1.type,
William Stein's avatar
William Stein committed
6850 6851 6852 6853
                    self.operand2.type))
        self.type = PyrexTypes.error_type


Robert Bradshaw's avatar
Robert Bradshaw committed
6854
class CBinopNode(BinopNode):
6855

Robert Bradshaw's avatar
Robert Bradshaw committed
6856 6857 6858 6859
    def analyse_types(self, env):
        BinopNode.analyse_types(self, env)
        if self.is_py_operation():
            self.type = PyrexTypes.error_type
6860

Robert Bradshaw's avatar
Robert Bradshaw committed
6861 6862
    def py_operation_function():
        return ""
6863

Robert Bradshaw's avatar
Robert Bradshaw committed
6864 6865
    def calculate_result_code(self):
        return "(%s %s %s)" % (
6866 6867
            self.operand1.result(),
            self.operator,
Robert Bradshaw's avatar
Robert Bradshaw committed
6868 6869 6870 6871 6872 6873 6874 6875
            self.operand2.result())


def c_binop_constructor(operator):
    def make_binop_node(pos, **operands):
        return CBinopNode(pos, operator=operator, **operands)
    return make_binop_node

William Stein's avatar
William Stein committed
6876 6877
class NumBinopNode(BinopNode):
    #  Binary operation taking numeric arguments.
6878

Robert Bradshaw's avatar
Robert Bradshaw committed
6879
    infix = True
6880

William Stein's avatar
William Stein committed
6881 6882 6883 6884 6885 6886
    def analyse_c_operation(self, env):
        type1 = self.operand1.type
        type2 = self.operand2.type
        self.type = self.compute_c_result_type(type1, type2)
        if not self.type:
            self.type_error()
6887
            return
6888
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
6889
            self.infix = False
6890
        if not self.infix or (type1.is_numeric and type2.is_numeric):
6891 6892
            self.operand1 = self.operand1.coerce_to(self.type, env)
            self.operand2 = self.operand2.coerce_to(self.type, env)
6893

William Stein's avatar
William Stein committed
6894 6895
    def compute_c_result_type(self, type1, type2):
        if self.c_types_okay(type1, type2):
6896 6897 6898 6899 6900
            widest_type = PyrexTypes.widest_numeric_type(type1, type2)
            if widest_type is PyrexTypes.c_bint_type:
                if self.operator not in '|^&':
                    # False + False == 0 # not False!
                    widest_type = PyrexTypes.c_int_type
6901 6902 6903
            else:
                widest_type = PyrexTypes.widest_numeric_type(
                    widest_type, PyrexTypes.c_int_type)
6904
            return widest_type
William Stein's avatar
William Stein committed
6905 6906
        else:
            return None
6907

6908 6909 6910 6911 6912 6913 6914 6915 6916 6917
    def may_be_none(self):
        type1 = self.operand1.type
        type2 = self.operand2.type
        if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type:
            # XXX: I can't think of any case where a binary operation
            # on builtin types evaluates to None - add a special case
            # here if there is one.
            return False
        return super(NumBinopNode, self).may_be_none()

6918 6919 6920 6921 6922 6923 6924
    def get_constant_c_result_code(self):
        value1 = self.operand1.get_constant_c_result_code()
        value2 = self.operand2.get_constant_c_result_code()
        if value1 and value2:
            return "(%s %s %s)" % (value1, self.operator, value2)
        else:
            return None
6925

William Stein's avatar
William Stein committed
6926
    def c_types_okay(self, type1, type2):
6927 6928 6929
        #print "NumBinopNode.c_types_okay:", type1, type2 ###
        return (type1.is_numeric  or type1.is_enum) \
            and (type2.is_numeric  or type2.is_enum)
William Stein's avatar
William Stein committed
6930 6931

    def calculate_result_code(self):
6932 6933
        if self.infix:
            return "(%s %s %s)" % (
6934 6935
                self.operand1.result(),
                self.operator,
6936 6937
                self.operand2.result())
        else:
6938 6939 6940
            func = self.type.binary_op(self.operator)
            if func is None:
                error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
6941
            return "%s(%s, %s)" % (
6942
                func,
6943 6944
                self.operand1.result(),
                self.operand2.result())
6945

6946
    def is_py_operation_types(self, type1, type2):
Stefan Behnel's avatar
Stefan Behnel committed
6947 6948
        return (type1.is_unicode_char or
                type2.is_unicode_char or
6949
                BinopNode.is_py_operation_types(self, type1, type2))
6950

William Stein's avatar
William Stein committed
6951
    def py_operation_function(self):
6952 6953 6954 6955
        fuction = self.py_functions[self.operator]
        if self.inplace:
            fuction = fuction.replace('PyNumber_', 'PyNumber_InPlace')
        return fuction
William Stein's avatar
William Stein committed
6956 6957

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
6958 6959 6960
        "|":        "PyNumber_Or",
        "^":        "PyNumber_Xor",
        "&":        "PyNumber_And",
6961 6962
        "<<":       "PyNumber_Lshift",
        ">>":       "PyNumber_Rshift",
Robert Bradshaw's avatar
Robert Bradshaw committed
6963 6964 6965 6966
        "+":        "PyNumber_Add",
        "-":        "PyNumber_Subtract",
        "*":        "PyNumber_Multiply",
        "/":        "__Pyx_PyNumber_Divide",
6967
        "//":       "PyNumber_FloorDivide",
Robert Bradshaw's avatar
Robert Bradshaw committed
6968
        "%":        "PyNumber_Remainder",
6969
        "**":       "PyNumber_Power"
William Stein's avatar
William Stein committed
6970 6971 6972 6973
    }

class IntBinopNode(NumBinopNode):
    #  Binary operation taking integer arguments.
6974

William Stein's avatar
William Stein committed
6975
    def c_types_okay(self, type1, type2):
6976 6977 6978
        #print "IntBinopNode.c_types_okay:", type1, type2 ###
        return (type1.is_int or type1.is_enum) \
            and (type2.is_int or type2.is_enum)
William Stein's avatar
William Stein committed
6979

6980

William Stein's avatar
William Stein committed
6981 6982
class AddNode(NumBinopNode):
    #  '+' operator.
6983

6984 6985 6986
    def is_py_operation_types(self, type1, type2):
        if type1.is_string and type2.is_string:
            return 1
William Stein's avatar
William Stein committed
6987
        else:
6988
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
6989 6990

    def compute_c_result_type(self, type1, type2):
6991 6992
        #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
        if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
William Stein's avatar
William Stein committed
6993
            return type1
6994
        elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
William Stein's avatar
William Stein committed
6995 6996 6997 6998 6999 7000 7001 7002
            return type2
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class SubNode(NumBinopNode):
    #  '-' operator.
7003

William Stein's avatar
William Stein committed
7004
    def compute_c_result_type(self, type1, type2):
7005
        if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
William Stein's avatar
William Stein committed
7006
            return type1
7007
        elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
William Stein's avatar
William Stein committed
7008 7009 7010 7011 7012 7013 7014 7015
            return PyrexTypes.c_int_type
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class MulNode(NumBinopNode):
    #  '*' operator.
7016

7017
    def is_py_operation_types(self, type1, type2):
William Stein's avatar
William Stein committed
7018 7019 7020 7021
        if (type1.is_string and type2.is_int) \
            or (type2.is_string and type1.is_int):
                return 1
        else:
7022
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
7023 7024


7025 7026
class DivNode(NumBinopNode):
    #  '/' or '//' operator.
7027

7028
    cdivision = None
7029 7030
    truedivision = None   # == "unknown" if operator == '/'
    ctruedivision = False
Robert Bradshaw's avatar
Robert Bradshaw committed
7031
    cdivision_warnings = False
7032
    zerodivision_check = None
7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054

    def find_compile_time_binary_operator(self, op1, op2):
        func = compile_time_binary_operators[self.operator]
        if self.operator == '/' and self.truedivision is None:
            # => true div for floats, floor div for integers
            if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
                func = compile_time_binary_operators['//']
        return func

    def calculate_constant_result(self):
        op1 = self.operand1.constant_result
        op2 = self.operand2.constant_result
        func = self.find_compile_time_binary_operator(op1, op2)
        self.constant_result = func(
            self.operand1.constant_result,
            self.operand2.constant_result)

    def compile_time_value(self, denv):
        operand1 = self.operand1.compile_time_value(denv)
        operand2 = self.operand2.compile_time_value(denv)
        try:
            func = self.find_compile_time_binary_operator(
Robert Bradshaw's avatar
Robert Bradshaw committed
7055
                operand1, operand2)
7056 7057 7058 7059
            return func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)

Robert Bradshaw's avatar
Robert Bradshaw committed
7060
    def analyse_operation(self, env):
7061 7062 7063 7064
        if self.cdivision or env.directives['cdivision']:
            self.ctruedivision = False
        else:
            self.ctruedivision = self.truedivision
Robert Bradshaw's avatar
Robert Bradshaw committed
7065
        NumBinopNode.analyse_operation(self, env)
7066 7067
        if self.is_cpp_operation():
            self.cdivision = True
7068
        if not self.type.is_pyobject:
7069 7070
            self.zerodivision_check = (
                self.cdivision is None and not env.directives['cdivision']
7071
                and (not self.operand2.has_constant_result() or
7072
                     self.operand2.constant_result == 0))
7073 7074 7075 7076
            if self.zerodivision_check or env.directives['cdivision_warnings']:
                # Need to check ahead of time to warn or raise zero division error
                self.operand1 = self.operand1.coerce_to_simple(env)
                self.operand2 = self.operand2.coerce_to_simple(env)
7077 7078
                if env.nogil:
                    error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
7079 7080 7081 7082 7083 7084 7085 7086 7087

    def compute_c_result_type(self, type1, type2):
        if self.operator == '/' and self.ctruedivision:
            if not type1.is_float and not type2.is_float:
                widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
                widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
                return widest_type
        return NumBinopNode.compute_c_result_type(self, type1, type2)

7088 7089 7090 7091 7092
    def zero_division_message(self):
        if self.type.is_int:
            return "integer division or modulo by zero"
        else:
            return "float division"
Robert Bradshaw's avatar
Robert Bradshaw committed
7093

7094
    def generate_evaluation_code(self, code):
7095
        if not self.type.is_pyobject and not self.type.is_complex:
7096
            if self.cdivision is None:
7097
                self.cdivision = (code.globalstate.directives['cdivision']
7098 7099 7100
                                    or not self.type.signed
                                    or self.type.is_float)
            if not self.cdivision:
7101
                code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
7102
        NumBinopNode.generate_evaluation_code(self, code)
7103
        self.generate_div_warning_code(code)
7104

7105
    def generate_div_warning_code(self, code):
7106 7107
        if not self.type.is_pyobject:
            if self.zerodivision_check:
7108 7109 7110 7111 7112
                if not self.infix:
                    zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
                else:
                    zero_test = "%s == 0" % self.operand2.result()
                code.putln("if (unlikely(%s)) {" % zero_test)
7113 7114 7115
                code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
                code.putln(code.error_goto(self.pos))
                code.putln("}")
7116 7117 7118
                if self.type.is_int and self.type.signed and self.operator != '%':
                    code.globalstate.use_utility_code(division_overflow_test_code)
                    code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
7119
                                    self.type.declaration_code(''),
7120 7121 7122 7123 7124
                                    self.operand2.result(),
                                    self.operand1.result()))
                    code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
                    code.putln(code.error_goto(self.pos))
                    code.putln("}")
Robert Bradshaw's avatar
Robert Bradshaw committed
7125
            if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
7126 7127 7128 7129 7130
                code.globalstate.use_utility_code(cdivision_warning_utility_code)
                code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
                                self.operand1.result(),
                                self.operand2.result()))
                code.putln(code.set_error_info(self.pos));
7131 7132 7133 7134 7135 7136
                code.put("if (__Pyx_cdivision_warning(%(FILENAME)s, "
                                                     "%(LINENO)s)) " % {
                    'FILENAME': Naming.filename_cname,
                    'LINENO':  Naming.lineno_cname,
                    })

7137 7138
                code.put_goto(code.error_label)
                code.putln("}")
7139

Robert Bradshaw's avatar
Robert Bradshaw committed
7140
    def calculate_result_code(self):
7141 7142 7143
        if self.type.is_complex:
            return NumBinopNode.calculate_result_code(self)
        elif self.type.is_float and self.operator == '//':
7144
            return "floor(%s / %s)" % (
7145
                self.operand1.result(),
7146
                self.operand2.result())
7147 7148 7149 7150 7151 7152 7153 7154 7155
        elif self.truedivision or self.cdivision:
            op1 = self.operand1.result()
            op2 = self.operand2.result()
            if self.truedivision:
                if self.type != self.operand1.type:
                    op1 = self.type.cast_code(op1)
                if self.type != self.operand2.type:
                    op2 = self.type.cast_code(op2)
            return "(%s / %s)" % (op1, op2)
7156 7157
        else:
            return "__Pyx_div_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
7158
                    self.type.specialization_name(),
7159
                    self.operand1.result(),
7160
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
7161 7162


Robert Bradshaw's avatar
Robert Bradshaw committed
7163
class ModNode(DivNode):
William Stein's avatar
William Stein committed
7164
    #  '%' operator.
7165

7166 7167 7168 7169
    def is_py_operation_types(self, type1, type2):
        return (type1.is_string
            or type2.is_string
            or NumBinopNode.is_py_operation_types(self, type1, type2))
William Stein's avatar
William Stein committed
7170

7171 7172 7173 7174 7175
    def zero_division_message(self):
        if self.type.is_int:
            return "integer division or modulo by zero"
        else:
            return "float divmod()"
7176

7177
    def generate_evaluation_code(self, code):
7178 7179 7180 7181 7182
        if not self.type.is_pyobject:
            if self.cdivision is None:
                self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
            if not self.cdivision:
                if self.type.is_int:
7183
                    code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
7184
                else:
7185 7186
                    code.globalstate.use_utility_code(
                        mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
7187
        NumBinopNode.generate_evaluation_code(self, code)
7188
        self.generate_div_warning_code(code)
7189

Robert Bradshaw's avatar
Robert Bradshaw committed
7190
    def calculate_result_code(self):
7191 7192 7193 7194
        if self.cdivision:
            if self.type.is_float:
                return "fmod%s(%s, %s)" % (
                    self.type.math_h_modifier,
7195
                    self.operand1.result(),
7196 7197 7198
                    self.operand2.result())
            else:
                return "(%s %% %s)" % (
7199
                    self.operand1.result(),
7200
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
7201
        else:
7202
            return "__Pyx_mod_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
7203
                    self.type.specialization_name(),
7204
                    self.operand1.result(),
7205
                    self.operand2.result())
William Stein's avatar
William Stein committed
7206 7207 7208

class PowNode(NumBinopNode):
    #  '**' operator.
7209

Robert Bradshaw's avatar
Robert Bradshaw committed
7210 7211
    def analyse_c_operation(self, env):
        NumBinopNode.analyse_c_operation(self, env)
7212
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
7213 7214 7215 7216 7217 7218 7219
            if self.type.real_type.is_float:
                self.operand1 = self.operand1.coerce_to(self.type, env)
                self.operand2 = self.operand2.coerce_to(self.type, env)
                self.pow_func = "__Pyx_c_pow" + self.type.real_type.math_h_modifier
            else:
                error(self.pos, "complex int powers not supported")
                self.pow_func = "<error>"
7220
        elif self.type.is_float:
7221
            self.pow_func = "pow" + self.type.math_h_modifier
William Stein's avatar
William Stein committed
7222
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
7223 7224
            self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
            env.use_utility_code(
7225
                    int_pow_utility_code.specialize(func_name=self.pow_func,
Robert Bradshaw's avatar
Robert Bradshaw committed
7226
                                                type=self.type.declaration_code('')))
7227

William Stein's avatar
William Stein committed
7228
    def calculate_result_code(self):
7229 7230 7231 7232 7233 7234
        # Work around MSVC overloading ambiguity.
        def typecast(operand):
            if self.type == operand.type:
                return operand.result()
            else:
                return self.type.cast_code(operand.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
7235
        return "%s(%s, %s)" % (
7236 7237
            self.pow_func,
            typecast(self.operand1),
7238
            typecast(self.operand2))
7239

William Stein's avatar
William Stein committed
7240

Craig Citro's avatar
Craig Citro committed
7241
# Note: This class is temporarily "shut down" into an ineffective temp
7242 7243
# allocation mode.
#
Craig Citro's avatar
Craig Citro committed
7244 7245 7246
# More sophisticated temp reuse was going on before, one could have a
# look at adding this again after /all/ classes are converted to the
# new temp scheme. (The temp juggling cannot work otherwise).
7247
class BoolBinopNode(ExprNode):
William Stein's avatar
William Stein committed
7248 7249 7250 7251 7252
    #  Short-circuiting boolean operation.
    #
    #  operator     string
    #  operand1     ExprNode
    #  operand2     ExprNode
7253

7254
    subexprs = ['operand1', 'operand2']
7255

7256
    def infer_type(self, env):
7257 7258
        type1 = self.operand1.infer_type(env)
        type2 = self.operand2.infer_type(env)
7259
        return PyrexTypes.independent_spanning_type(type1, type2)
7260

Stefan Behnel's avatar
Stefan Behnel committed
7261 7262 7263 7264 7265 7266
    def may_be_none(self):
        if self.operator == 'or':
            return self.operand2.may_be_none()
        else:
            return self.operand1.may_be_none() or self.operand2.may_be_none()

7267 7268 7269 7270 7271 7272 7273 7274 7275
    def calculate_constant_result(self):
        if self.operator == 'and':
            self.constant_result = \
                self.operand1.constant_result and \
                self.operand2.constant_result
        else:
            self.constant_result = \
                self.operand1.constant_result or \
                self.operand2.constant_result
7276

7277 7278 7279 7280 7281 7282 7283
    def compile_time_value(self, denv):
        if self.operator == 'and':
            return self.operand1.compile_time_value(denv) \
                and self.operand2.compile_time_value(denv)
        else:
            return self.operand1.compile_time_value(denv) \
                or self.operand2.compile_time_value(denv)
7284

7285
    def coerce_to_boolean(self, env):
7286 7287 7288 7289 7290 7291 7292
        return BoolBinopNode(
            self.pos,
            operator = self.operator,
            operand1 = self.operand1.coerce_to_boolean(env),
            operand2 = self.operand2.coerce_to_boolean(env),
            type = PyrexTypes.c_bint_type,
            is_temp = self.is_temp)
7293

William Stein's avatar
William Stein committed
7294 7295 7296
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
7297
        self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
7298 7299
        self.operand1 = self.operand1.coerce_to(self.type, env)
        self.operand2 = self.operand2.coerce_to(self.type, env)
7300

William Stein's avatar
William Stein committed
7301 7302
        # For what we're about to do, it's vital that
        # both operands be temp nodes.
7303 7304
        self.operand1 = self.operand1.coerce_to_simple(env)
        self.operand2 = self.operand2.coerce_to_simple(env)
William Stein's avatar
William Stein committed
7305
        self.is_temp = 1
7306 7307 7308

    gil_message = "Truth-testing Python object"

William Stein's avatar
William Stein committed
7309
    def check_const(self):
7310
        return self.operand1.check_const() and self.operand2.check_const()
7311

William Stein's avatar
William Stein committed
7312
    def generate_evaluation_code(self, code):
7313
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
7314
        self.operand1.generate_evaluation_code(code)
7315
        test_result, uses_temp = self.generate_operand1_test(code)
William Stein's avatar
William Stein committed
7316 7317 7318 7319 7320 7321 7322 7323
        if self.operator == 'and':
            sense = ""
        else:
            sense = "!"
        code.putln(
            "if (%s%s) {" % (
                sense,
                test_result))
7324 7325
        if uses_temp:
            code.funcstate.release_temp(test_result)
7326
        self.operand1.generate_disposal_code(code)
William Stein's avatar
William Stein committed
7327
        self.operand2.generate_evaluation_code(code)
7328
        self.allocate_temp_result(code)
7329
        self.operand2.make_owned_reference(code)
7330
        code.putln("%s = %s;" % (self.result(), self.operand2.result()))
7331 7332
        self.operand2.generate_post_assignment_code(code)
        self.operand2.free_temps(code)
7333
        code.putln("} else {")
7334
        self.operand1.make_owned_reference(code)
7335
        code.putln("%s = %s;" % (self.result(), self.operand1.result()))
7336 7337
        self.operand1.generate_post_assignment_code(code)
        self.operand1.free_temps(code)
7338
        code.putln("}")
7339

William Stein's avatar
William Stein committed
7340 7341 7342
    def generate_operand1_test(self, code):
        #  Generate code to test the truth of the first operand.
        if self.type.is_pyobject:
7343 7344
            test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
                                                       manage_ref=False)
William Stein's avatar
William Stein committed
7345
            code.putln(
7346
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
William Stein's avatar
William Stein committed
7347 7348
                    test_result,
                    self.operand1.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
7349
                    code.error_goto_if_neg(test_result, self.pos)))
William Stein's avatar
William Stein committed
7350
        else:
7351
            test_result = self.operand1.result()
7352
        return (test_result, self.type.is_pyobject)
William Stein's avatar
William Stein committed
7353 7354


7355
class CondExprNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
7356 7357 7358 7359 7360
    #  Short-circuiting conditional expression.
    #
    #  test        ExprNode
    #  true_val    ExprNode
    #  false_val   ExprNode
7361

7362 7363
    true_val = None
    false_val = None
7364

Robert Bradshaw's avatar
Robert Bradshaw committed
7365
    subexprs = ['test', 'true_val', 'false_val']
7366

Robert Bradshaw's avatar
Robert Bradshaw committed
7367 7368
    def type_dependencies(self, env):
        return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
7369

Robert Bradshaw's avatar
Robert Bradshaw committed
7370
    def infer_type(self, env):
7371 7372
        return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
                                                    self.false_val.infer_type(env))
7373 7374 7375 7376 7377 7378 7379

    def calculate_constant_result(self):
        if self.test.constant_result:
            self.constant_result = self.true_val.constant_result
        else:
            self.constant_result = self.false_val.constant_result

Robert Bradshaw's avatar
Robert Bradshaw committed
7380 7381 7382 7383 7384
    def analyse_types(self, env):
        self.test.analyse_types(env)
        self.test = self.test.coerce_to_boolean(env)
        self.true_val.analyse_types(env)
        self.false_val.analyse_types(env)
7385
        self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
7386 7387 7388 7389 7390
        if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
            self.true_val = self.true_val.coerce_to(self.type, env)
            self.false_val = self.false_val.coerce_to(self.type, env)
        self.is_temp = 1
        if self.type == PyrexTypes.error_type:
Robert Bradshaw's avatar
Robert Bradshaw committed
7391
            self.type_error()
7392

Robert Bradshaw's avatar
Robert Bradshaw committed
7393 7394 7395 7396 7397
    def type_error(self):
        if not (self.true_val.type.is_error or self.false_val.type.is_error):
            error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
                (self.true_val.type, self.false_val.type))
        self.type = PyrexTypes.error_type
7398

Robert Bradshaw's avatar
Robert Bradshaw committed
7399
    def check_const(self):
7400
        return (self.test.check_const()
7401 7402
            and self.true_val.check_const()
            and self.false_val.check_const())
7403

Robert Bradshaw's avatar
Robert Bradshaw committed
7404
    def generate_evaluation_code(self, code):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7405 7406
        # Because subexprs may not be evaluated we can use a more optimal
        # subexpr allocation strategy than the default, so override evaluation_code.
7407

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7408
        code.mark_pos(self.pos)
7409
        self.allocate_temp_result(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
7410
        self.test.generate_evaluation_code(code)
7411
        code.putln("if (%s) {" % self.test.result() )
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7412
        self.eval_and_get(code, self.true_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
7413
        code.putln("} else {")
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7414
        self.eval_and_get(code, self.false_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
7415 7416
        code.putln("}")
        self.test.generate_disposal_code(code)
7417
        self.test.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
7418

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7419 7420 7421 7422 7423 7424 7425
    def eval_and_get(self, code, expr):
        expr.generate_evaluation_code(code)
        expr.make_owned_reference(code)
        code.putln("%s = %s;" % (self.result(), expr.result()))
        expr.generate_post_assignment_code(code)
        expr.free_temps(code)

7426 7427 7428 7429 7430 7431 7432 7433 7434 7435
richcmp_constants = {
    "<" : "Py_LT",
    "<=": "Py_LE",
    "==": "Py_EQ",
    "!=": "Py_NE",
    "<>": "Py_NE",
    ">" : "Py_GT",
    ">=": "Py_GE",
}

7436
class CmpNode(object):
William Stein's avatar
William Stein committed
7437 7438
    #  Mixin class containing code common to PrimaryCmpNodes
    #  and CascadedCmpNodes.
7439 7440 7441

    special_bool_cmp_function = None

Stefan Behnel's avatar
typo  
Stefan Behnel committed
7442
    def infer_type(self, env):
7443 7444
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type
7445 7446 7447 7448 7449

    def calculate_cascaded_constant_result(self, operand1_result):
        func = compile_time_binary_operators[self.operator]
        operand2_result = self.operand2.constant_result
        result = func(operand1_result, operand2_result)
7450 7451 7452 7453 7454 7455 7456
        if self.cascade:
            self.cascade.calculate_cascaded_constant_result(operand2_result)
            if self.cascade.constant_result:
                self.constant_result = result and self.cascade.constant_result
        else:
            self.constant_result = result

7457 7458
    def cascaded_compile_time_value(self, operand1, denv):
        func = get_compile_time_binop(self)
7459
        operand2 = self.operand2.compile_time_value(denv)
7460 7461 7462 7463
        try:
            result = func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)
7464
            result = None
7465 7466 7467
        if result:
            cascade = self.cascade
            if cascade:
7468
                # FIXME: I bet this must call cascaded_compile_time_value()
7469
                result = result and cascade.cascaded_compile_time_value(operand2, denv)
7470 7471
        return result

7472
    def is_cpp_comparison(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
7473
        return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
7474

7475
    def find_common_int_type(self, env, op, operand1, operand2):
7476 7477 7478 7479 7480 7481
        # type1 != type2 and at least one of the types is not a C int
        type1 = operand1.type
        type2 = operand2.type
        type1_can_be_int = False
        type2_can_be_int = False

7482
        if operand1.is_string_literal and operand1.can_coerce_to_char_literal():
7483
            type1_can_be_int = True
7484
        if operand2.is_string_literal and operand2.can_coerce_to_char_literal():
7485 7486 7487 7488
            type2_can_be_int = True

        if type1.is_int:
            if type2_can_be_int:
7489
                return type1
7490 7491
        elif type2.is_int:
            if type1_can_be_int:
7492
                return type2
7493 7494
        elif type1_can_be_int:
            if type2_can_be_int:
7495
                return PyrexTypes.c_uchar_type
William Stein's avatar
William Stein committed
7496

7497
        return None
7498

7499
    def find_common_type(self, env, op, operand1, common_type=None):
7500
        operand2 = self.operand2
William Stein's avatar
William Stein committed
7501 7502
        type1 = operand1.type
        type2 = operand2.type
7503

7504 7505
        new_common_type = None

Stefan Behnel's avatar
Stefan Behnel committed
7506
        # catch general errors
7507 7508 7509
        if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
               type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
            error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
7510
            new_common_type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
7511 7512

        # try to use numeric comparisons where possible
7513
        elif type1.is_complex or type2.is_complex:
7514 7515 7516
            if op not in ('==', '!=') \
               and (type1.is_complex or type1.is_numeric) \
               and (type2.is_complex or type2.is_numeric):
7517 7518
                error(self.pos, "complex types are unordered")
                new_common_type = error_type
7519
            elif type1.is_pyobject:
7520 7521 7522
                new_common_type = type1
            elif type2.is_pyobject:
                new_common_type = type2
7523
            else:
7524
                new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
7525 7526
        elif type1.is_numeric and type2.is_numeric:
            new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
7527
        elif common_type is None or not common_type.is_pyobject:
7528
            new_common_type = self.find_common_int_type(env, op, operand1, operand2)
7529 7530

        if new_common_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
7531
            # fall back to generic type compatibility tests
7532
            if type1 == type2:
7533 7534 7535 7536 7537 7538
                new_common_type = type1
            elif type1.is_pyobject or type2.is_pyobject:
                if type2.is_numeric or type2.is_string:
                    if operand2.check_for_coercion_error(type1):
                        new_common_type = error_type
                    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
7539
                        new_common_type = py_object_type
7540 7541 7542 7543
                elif type1.is_numeric or type1.is_string:
                    if operand1.check_for_coercion_error(type2):
                        new_common_type = error_type
                    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
7544 7545 7546
                        new_common_type = py_object_type
                elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
                    new_common_type = py_object_type
7547 7548 7549 7550
                else:
                    # one Python type and one non-Python type, not assignable
                    self.invalid_types_error(operand1, op, operand2)
                    new_common_type = error_type
7551 7552 7553 7554
            elif type1.assignable_from(type2):
                new_common_type = type1
            elif type2.assignable_from(type1):
                new_common_type = type2
7555 7556 7557 7558
            else:
                # C types that we couldn't handle up to here are an error
                self.invalid_types_error(operand1, op, operand2)
                new_common_type = error_type
7559

7560 7561 7562 7563 7564 7565
        if new_common_type.is_string and (isinstance(operand1, BytesNode) or
                                          isinstance(operand2, BytesNode)):
            # special case when comparing char* to bytes literal: must
            # compare string values!
            new_common_type = bytes_type

Stefan Behnel's avatar
Stefan Behnel committed
7566
        # recursively merge types
7567
        if common_type is None or new_common_type.is_error:
7568
            common_type = new_common_type
William Stein's avatar
William Stein committed
7569
        else:
7570 7571 7572
            # we could do a lot better by splitting the comparison
            # into a non-Python part and a Python part, but this is
            # safer for now
7573
            common_type = PyrexTypes.spanning_type(common_type, new_common_type)
7574 7575

        if self.cascade:
7576
            common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
7577

7578 7579
        return common_type

7580 7581 7582 7583
    def invalid_types_error(self, operand1, op, operand2):
        error(self.pos, "Invalid types for '%s' (%s, %s)" %
              (op, operand1.type, operand2.type))

Stefan Behnel's avatar
Stefan Behnel committed
7584
    def is_python_comparison(self):
7585 7586 7587 7588 7589
        return (not self.is_ptr_contains()
            and not self.is_c_string_contains()
            and (self.has_python_operands()
                 or (self.cascade and self.cascade.is_python_comparison())
                 or self.operator in ('in', 'not_in')))
Stefan Behnel's avatar
Stefan Behnel committed
7590

7591 7592 7593 7594 7595 7596
    def coerce_operands_to(self, dst_type, env):
        operand2 = self.operand2
        if operand2.type != dst_type:
            self.operand2 = operand2.coerce_to(dst_type, env)
        if self.cascade:
            self.cascade.coerce_operands_to(dst_type, env)
7597

7598
    def is_python_result(self):
7599
        return ((self.has_python_operands() and
7600
                 self.special_bool_cmp_function is None and
7601
                 self.operator not in ('is', 'is_not', 'in', 'not_in') and
7602 7603
                 not self.is_c_string_contains() and
                 not self.is_ptr_contains())
7604
            or (self.cascade and self.cascade.is_python_result()))
William Stein's avatar
William Stein committed
7605

7606 7607
    def is_c_string_contains(self):
        return self.operator in ('in', 'not_in') and \
7608 7609
               ((self.operand1.type.is_int
                 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
Stefan Behnel's avatar
Stefan Behnel committed
7610
                (self.operand1.type.is_unicode_char
7611
                 and self.operand2.type is unicode_type))
7612

7613 7614
    def is_ptr_contains(self):
        if self.operator in ('in', 'not_in'):
7615 7616 7617
            container_type = self.operand2.type
            return (container_type.is_ptr or container_type.is_array) \
                and not container_type.is_string
7618

7619 7620 7621 7622 7623 7624 7625 7626
    def find_special_bool_compare_function(self, env):
        if self.operator in ('==', '!='):
            type1, type2 = self.operand1.type, self.operand2.type
            if type1.is_pyobject and type2.is_pyobject:
                if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type:
                    env.use_utility_code(pyunicode_equals_utility_code)
                    self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals"
                    return True
7627 7628 7629 7630 7631 7632 7633 7634
                elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type:
                    env.use_utility_code(pybytes_equals_utility_code)
                    self.special_bool_cmp_function = "__Pyx_PyBytes_Equals"
                    return True
                elif type1 is Builtin.str_type or type2 is Builtin.str_type:
                    env.use_utility_code(pystr_equals_utility_code)
                    self.special_bool_cmp_function = "__Pyx_PyString_Equals"
                    return True
7635 7636
        return False

7637
    def generate_operation_code(self, code, result_code,
William Stein's avatar
William Stein committed
7638
            operand1, op , operand2):
7639
        if self.type.is_pyobject:
7640 7641 7642
            coerce_result = "__Pyx_PyBool_FromLong"
        else:
            coerce_result = ""
7643
        if 'not' in op:
7644
            negation = "!"
7645
        else:
7646
            negation = ""
7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663
        if self.special_bool_cmp_function:
            if operand1.type.is_pyobject:
                result1 = operand1.py_result()
            else:
                result1 = operand1.result()
            if operand2.type.is_pyobject:
                result2 = operand2.py_result()
            else:
                result2 = operand2.result()
            code.putln("%s = %s(%s, %s, %s); %s" % (
                result_code,
                self.special_bool_cmp_function,
                result1,
                result2,
                richcmp_constants[op],
                code.error_goto_if_neg(result_code, self.pos)))
        elif op == 'in' or op == 'not_in':
Stefan Behnel's avatar
typo  
Stefan Behnel committed
7664
            code.globalstate.use_utility_code(contains_utility_code)
7665
            if self.type.is_pyobject:
7666
                coerce_result = "__Pyx_PyBoolOrNull_FromLong"
7667
            if op == 'not_in':
7668
                negation = "__Pyx_NegateNonNeg"
7669
            if operand2.type is dict_type:
7670
                method = "PyDict_Contains"
7671
            else:
7672
                method = "PySequence_Contains"
7673
            if self.type.is_pyobject:
7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684
                error_clause = code.error_goto_if_null
                got_ref = "__Pyx_XGOTREF(%s); " % result_code
            else:
                error_clause = code.error_goto_if_neg
                got_ref = ""
            code.putln(
                "%s = %s(%s(%s(%s, %s))); %s%s" % (
                    result_code,
                    coerce_result,
                    negation,
                    method,
7685 7686
                    operand2.py_result(),
                    operand1.py_result(),
7687 7688
                    got_ref,
                    error_clause(result_code, self.pos)))
William Stein's avatar
William Stein committed
7689 7690
        elif (operand1.type.is_pyobject
            and op not in ('is', 'is_not')):
7691
                code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
7692 7693 7694
                        result_code,
                        operand1.py_result(),
                        operand2.py_result(),
7695 7696
                        richcmp_constants[op],
                        code.error_goto_if_null(result_code, self.pos)))
7697
                code.put_gotref(result_code)
7698
        elif operand1.type.is_complex:
7699
            if op == "!=":
7700
                negation = "!"
7701
            else:
7702
                negation = ""
7703
            code.putln("%s = %s(%s%s(%s, %s));" % (
7704
                result_code,
7705 7706
                coerce_result,
                negation,
7707 7708
                operand1.type.unary_op('eq'),
                operand1.result(),
7709
                operand2.result()))
William Stein's avatar
William Stein committed
7710
        else:
7711 7712 7713 7714 7715
            type1 = operand1.type
            type2 = operand2.type
            if (type1.is_extension_type or type2.is_extension_type) \
                    and not type1.same_as(type2):
                common_type = py_object_type
7716 7717
            elif type1.is_numeric:
                common_type = PyrexTypes.widest_numeric_type(type1, type2)
7718
            else:
7719 7720 7721
                common_type = type1
            code1 = operand1.result_as(common_type)
            code2 = operand2.result_as(common_type)
7722
            code.putln("%s = %s(%s %s %s);" % (
7723 7724 7725 7726
                result_code,
                coerce_result,
                code1,
                self.c_operator(op),
7727 7728
                code2))

William Stein's avatar
William Stein committed
7729 7730 7731 7732 7733 7734 7735
    def c_operator(self, op):
        if op == 'is':
            return "=="
        elif op == 'is_not':
            return "!="
        else:
            return op
7736

Stefan Behnel's avatar
typo  
Stefan Behnel committed
7737
contains_utility_code = UtilityCode(
7738
proto="""
7739 7740
static CYTHON_INLINE int __Pyx_NegateNonNeg(int b) {
    return unlikely(b < 0) ? b : !b;
Lisandro Dalcin's avatar
Lisandro Dalcin committed
7741
}
7742
static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
7743 7744 7745 7746
    return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
}
""")

7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762
char_in_bytes_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character) {
    const Py_ssize_t length = PyBytes_GET_SIZE(bytes);
    char* char_start = PyBytes_AS_STRING(bytes);
    char* pos;
    for (pos=char_start; pos < char_start+length; pos++) {
        if (character == pos[0]) return 1;
    }
    return 0;
}
""")

7763 7764 7765
py_ucs4_in_unicode_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character); /*proto*/
7766
static CYTHON_INLINE int __Pyx_PyUnicodeBufferContainsUCS4(Py_UNICODE* buffer, Py_ssize_t length, Py_UCS4 character); /*proto*/
7767
""",
7768
# additionally handles surrogate pairs for Py_UNICODE buffers in 16bit Unicode builds
7769 7770
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character) {
7771 7772
#ifdef CYTHON_PEP393_ENABLED
    Py_ssize_t i;
7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783
    int kind;
    void* udata;
    Py_ssize_t length;
    kind = PyUnicode_KIND(unicode);
    if (likely(kind != PyUnicode_WCHAR_KIND)) {
        udata = PyUnicode_DATA(unicode);
        length = PyUnicode_GET_LENGTH(unicode);
        for (i=0; i < length; i++) {
            if (unlikely(character == PyUnicode_READ(kind, udata, i))) return 1;
        }
        return 0;
7784
    }
7785 7786 7787 7788 7789 7790
#endif
    return __Pyx_PyUnicodeBufferContainsUCS4(
        PyUnicode_AS_UNICODE(unicode),
        PyUnicode_GET_SIZE(unicode),
        character);
}
7791

7792 7793 7794
static CYTHON_INLINE int __Pyx_PyUnicodeBufferContainsUCS4(Py_UNICODE* buffer, Py_ssize_t length, Py_UCS4 character) {
    Py_UNICODE uchar;
    Py_UNICODE* pos;
7795
    #if Py_UNICODE_SIZE == 2
7796
    if (character > 65535) {
7797 7798 7799
        Py_UNICODE high_val, low_val;
        high_val = (Py_UNICODE) (0xD800 | (((character - 0x10000) >> 10) & ((1<<10)-1)));
        low_val  = (Py_UNICODE) (0xDC00 | ( (character - 0x10000)        & ((1<<10)-1)));
7800
        for (pos=buffer; pos < buffer+length-1; pos++) {
7801 7802 7803 7804 7805 7806
            if (unlikely(high_val == pos[0]) & unlikely(low_val == pos[1])) return 1;
        }
        return 0;
    }
    #endif
    uchar = (Py_UNICODE) character;
7807
    for (pos=buffer; pos < buffer+length; pos++) {
7808
        if (unlikely(uchar == pos[0])) return 1;
7809 7810 7811 7812 7813
    }
    return 0;
}
""")

7814 7815 7816 7817 7818 7819
pyunicode_equals_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) {
Stefan Behnel's avatar
Stefan Behnel committed
7820
    if (s1 == s2) {   /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */
7821 7822
        return (equals == Py_EQ);
    } else if (PyUnicode_CheckExact(s1) & PyUnicode_CheckExact(s2)) {
7823
        #ifdef CYTHON_PEP393_ENABLED
7824
        if ((PyUnicode_READY(s1) < 0) || (PyUnicode_READY(s2) < 0))
7825
            return -1;
7826 7827 7828
        if (PyUnicode_GET_LENGTH(s1) != PyUnicode_GET_LENGTH(s2)) {
            return (equals == Py_NE);
        } else if (PyUnicode_GET_LENGTH(s1) == 1) {
7829 7830 7831
            Py_UCS4 ch1 = PyUnicode_READ_CHAR(s1, 0);
            Py_UCS4 ch2 = PyUnicode_READ_CHAR(s2, 0);
            return (equals == Py_EQ) ? (ch1 == ch2) : (ch1 != ch2);
7832 7833 7834 7835 7836
"""
## currently disabled: may not be safe depending on who created the string
#        } else if (PyUnicode_MAX_CHAR_VALUE(s1) != PyUnicode_MAX_CHAR_VALUE(s2)) {
#            return (equals == Py_NE);
"""\
7837
        #else
7838 7839 7840
        if (PyUnicode_GET_SIZE(s1) != PyUnicode_GET_SIZE(s2)) {
            return (equals == Py_NE);
        } else if (PyUnicode_GET_SIZE(s1) == 1) {
7841 7842 7843
            Py_UNICODE ch1 = PyUnicode_AS_UNICODE(s1)[0];
            Py_UNICODE ch2 = PyUnicode_AS_UNICODE(s2)[0];
            return (equals == Py_EQ) ? (ch1 == ch2) : (ch1 != ch2);
7844
        #endif
7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866
        } else {
            int result = PyUnicode_Compare(s1, s2);
            if ((result == -1) && unlikely(PyErr_Occurred()))
                return -1;
            return (equals == Py_EQ) ? (result == 0) : (result != 0);
        }
    } else if ((s1 == Py_None) & PyUnicode_CheckExact(s2)) {
        return (equals == Py_NE);
    } else if ((s2 == Py_None) & PyUnicode_CheckExact(s1)) {
        return (equals == Py_NE);
    } else {
        int result;
        PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
        if (!py_result)
            return -1;
        result = __Pyx_PyObject_IsTrue(py_result);
        Py_DECREF(py_result);
        return result;
    }
}
""")

7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882
pybytes_equals_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) {
    if (s1 == s2) {   /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */
        return (equals == Py_EQ);
    } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) {
        if (PyBytes_GET_SIZE(s1) != PyBytes_GET_SIZE(s2)) {
            return (equals == Py_NE);
        } else if (PyBytes_GET_SIZE(s1) == 1) {
            if (equals == Py_EQ)
                return (PyBytes_AS_STRING(s1)[0] == PyBytes_AS_STRING(s2)[0]);
            else
                return (PyBytes_AS_STRING(s1)[0] != PyBytes_AS_STRING(s2)[0]);
7883
        } else {
Lisandro Dalcin's avatar
Lisandro Dalcin committed
7884
            int result = memcmp(PyBytes_AS_STRING(s1), PyBytes_AS_STRING(s2), (size_t)PyBytes_GET_SIZE(s1));
7885 7886
            return (equals == Py_EQ) ? (result == 0) : (result != 0);
        }
7887 7888 7889 7890
    } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) {
        return (equals == Py_NE);
    } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) {
        return (equals == Py_NE);
7891
    } else {
7892 7893 7894 7895 7896 7897 7898 7899 7900
        int result;
        PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
        if (!py_result)
            return -1;
        result = __Pyx_PyObject_IsTrue(py_result);
        Py_DECREF(py_result);
        return result;
    }
}
7901 7902
""",
requires=[Builtin.include_string_h_utility_code])
7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913

pystr_equals_utility_code = UtilityCode(
proto="""
#if PY_MAJOR_VERSION >= 3
#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals
#else
#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals
#endif
""",
requires=[pybytes_equals_utility_code, pyunicode_equals_utility_code])

William Stein's avatar
William Stein committed
7914

7915
class PrimaryCmpNode(ExprNode, CmpNode):
William Stein's avatar
William Stein committed
7916 7917 7918 7919 7920 7921 7922
    #  Non-cascaded comparison or first comparison of
    #  a cascaded sequence.
    #
    #  operator      string
    #  operand1      ExprNode
    #  operand2      ExprNode
    #  cascade       CascadedCmpNode
7923

William Stein's avatar
William Stein committed
7924 7925 7926 7927
    #  We don't use the subexprs mechanism, because
    #  things here are too complicated for it to handle.
    #  Instead, we override all the framework methods
    #  which use it.
7928

Robert Bradshaw's avatar
Robert Bradshaw committed
7929
    child_attrs = ['operand1', 'operand2', 'cascade']
7930

William Stein's avatar
William Stein committed
7931
    cascade = None
7932

Robert Bradshaw's avatar
Robert Bradshaw committed
7933 7934 7935 7936 7937 7938 7939
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

7940
    def calculate_constant_result(self):
7941
        self.calculate_cascaded_constant_result(self.operand1.constant_result)
7942

7943
    def compile_time_value(self, denv):
7944
        operand1 = self.operand1.compile_time_value(denv)
7945 7946
        return self.cascaded_compile_time_value(operand1, denv)

William Stein's avatar
William Stein committed
7947 7948 7949
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
7950 7951
        if self.is_cpp_comparison():
            self.analyse_cpp_comparison(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
7952 7953 7954
            if self.cascade:
                error(self.pos, "Cascading comparison not yet supported for cpp types.")
            return
William Stein's avatar
William Stein committed
7955
        if self.cascade:
7956 7957
            self.cascade.analyse_types(env)

7958
        if self.operator in ('in', 'not_in'):
7959 7960 7961 7962 7963 7964 7965
            if self.is_c_string_contains():
                self.is_pycmp = False
                common_type = None
                if self.cascade:
                    error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
                    return
                if self.operand2.type is unicode_type:
7966
                    env.use_utility_code(py_ucs4_in_unicode_utility_code)
7967 7968 7969 7970 7971 7972
                else:
                    if self.operand1.type is PyrexTypes.c_uchar_type:
                        self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
                    if self.operand2.type is not bytes_type:
                        self.operand2 = self.operand2.coerce_to(bytes_type, env)
                    env.use_utility_code(char_in_bytes_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
7973 7974
                self.operand2 = self.operand2.as_none_safe_node(
                    "argument of type 'NoneType' is not iterable")
7975 7976 7977 7978 7979 7980
            elif self.is_ptr_contains():
                if self.cascade:
                    error(self.pos, "Cascading comparison not yet supported for 'val in sliced pointer'.")
                self.type = PyrexTypes.c_bint_type
                # Will be transformed by IterationTransform
                return
7981
            else:
7982 7983
                if self.operand2.type is dict_type:
                    self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
7984 7985
                common_type = py_object_type
                self.is_pycmp = True
7986 7987 7988 7989
        elif self.find_special_bool_compare_function(env):
            common_type = None # if coercion needed, the method call above has already done it
            self.is_pycmp = False # result is bint
            self.is_temp = True # must check for error return
7990 7991 7992 7993
        else:
            common_type = self.find_common_type(env, self.operator, self.operand1)
            self.is_pycmp = common_type.is_pyobject

7994
        if common_type is not None and not common_type.is_error:
7995 7996 7997
            if self.operand1.type != common_type:
                self.operand1 = self.operand1.coerce_to(common_type, env)
            self.coerce_operands_to(common_type, env)
7998

William Stein's avatar
William Stein committed
7999 8000 8001
        if self.cascade:
            self.operand2 = self.operand2.coerce_to_simple(env)
            self.cascade.coerce_cascaded_operands_to_temp(env)
8002 8003 8004 8005 8006 8007 8008 8009
        if self.is_python_result():
            self.type = PyrexTypes.py_object_type
        else:
            self.type = PyrexTypes.c_bint_type
        cdr = self.cascade
        while cdr:
            cdr.type = self.type
            cdr = cdr.cascade
William Stein's avatar
William Stein committed
8010 8011
        if self.is_pycmp or self.cascade:
            self.is_temp = 1
8012

8013 8014 8015
    def analyse_cpp_comparison(self, env):
        type1 = self.operand1.type
        type2 = self.operand2.type
8016 8017
        entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
        if entry is None:
8018 8019
            error(self.pos, "Invalid types for '%s' (%s, %s)" %
                (self.operator, type1, type2))
8020 8021 8022
            self.type = PyrexTypes.error_type
            self.result_code = "<error>"
            return
8023 8024 8025 8026 8027
        func_type = entry.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        if len(func_type.args) == 1:
            self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
8028
        else:
8029 8030 8031
            self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
            self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
        self.type = func_type.return_type
8032

William Stein's avatar
William Stein committed
8033 8034 8035
    def has_python_operands(self):
        return (self.operand1.type.is_pyobject
            or self.operand2.type.is_pyobject)
8036

William Stein's avatar
William Stein committed
8037 8038 8039
    def check_const(self):
        if self.cascade:
            self.not_const()
8040 8041 8042
            return False
        else:
            return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
8043 8044

    def calculate_result_code(self):
8045 8046 8047 8048 8049 8050 8051
        if self.operand1.type.is_complex:
            if self.operator == "!=":
                negation = "!"
            else:
                negation = ""
            return "(%s%s(%s, %s))" % (
                negation,
8052 8053
                self.operand1.type.binary_op('=='),
                self.operand1.result(),
8054
                self.operand2.result())
8055
        elif self.is_c_string_contains():
8056
            if self.operand2.type is unicode_type:
8057
                method = "__Pyx_UnicodeContainsUCS4"
8058
            else:
8059
                method = "__Pyx_BytesContains"
8060 8061 8062 8063 8064 8065 8066
            if self.operator == "not_in":
                negation = "!"
            else:
                negation = ""
            return "(%s%s(%s, %s))" % (
                negation,
                method,
8067
                self.operand2.result(),
8068
                self.operand1.result())
8069 8070 8071 8072 8073
        else:
            return "(%s %s %s)" % (
                self.operand1.result(),
                self.c_operator(self.operator),
                self.operand2.result())
8074

William Stein's avatar
William Stein committed
8075 8076 8077 8078
    def generate_evaluation_code(self, code):
        self.operand1.generate_evaluation_code(code)
        self.operand2.generate_evaluation_code(code)
        if self.is_temp:
8079
            self.allocate_temp_result(code)
8080
            self.generate_operation_code(code, self.result(),
William Stein's avatar
William Stein committed
8081 8082 8083
                self.operand1, self.operator, self.operand2)
            if self.cascade:
                self.cascade.generate_evaluation_code(code,
8084
                    self.result(), self.operand2)
William Stein's avatar
William Stein committed
8085
            self.operand1.generate_disposal_code(code)
8086
            self.operand1.free_temps(code)
William Stein's avatar
William Stein committed
8087
            self.operand2.generate_disposal_code(code)
8088
            self.operand2.free_temps(code)
8089

William Stein's avatar
William Stein committed
8090 8091 8092 8093 8094
    def generate_subexpr_disposal_code(self, code):
        #  If this is called, it is a non-cascaded cmp,
        #  so only need to dispose of the two main operands.
        self.operand1.generate_disposal_code(code)
        self.operand2.generate_disposal_code(code)
8095

8096 8097 8098 8099 8100
    def free_subexpr_temps(self, code):
        #  If this is called, it is a non-cascaded cmp,
        #  so only need to dispose of the two main operands.
        self.operand1.free_temps(code)
        self.operand2.free_temps(code)
8101

8102 8103 8104 8105 8106
    def annotate(self, code):
        self.operand1.annotate(code)
        self.operand2.annotate(code)
        if self.cascade:
            self.cascade.annotate(code)
William Stein's avatar
William Stein committed
8107 8108 8109


class CascadedCmpNode(Node, CmpNode):
8110 8111 8112
    #  A CascadedCmpNode is not a complete expression node. It
    #  hangs off the side of another comparison node, shares
    #  its left operand with that node, and shares its result
William Stein's avatar
William Stein committed
8113 8114 8115 8116 8117 8118
    #  with the PrimaryCmpNode at the head of the chain.
    #
    #  operator      string
    #  operand2      ExprNode
    #  cascade       CascadedCmpNode

Robert Bradshaw's avatar
Robert Bradshaw committed
8119 8120
    child_attrs = ['operand2', 'cascade']

William Stein's avatar
William Stein committed
8121
    cascade = None
8122 8123
    constant_result = constant_value_not_set # FIXME: where to calculate this?

Robert Bradshaw's avatar
Robert Bradshaw committed
8124 8125 8126 8127 8128 8129 8130
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

8131 8132 8133 8134
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

8135
    def analyse_types(self, env):
William Stein's avatar
William Stein committed
8136 8137
        self.operand2.analyse_types(env)
        if self.cascade:
8138
            self.cascade.analyse_types(env)
8139

William Stein's avatar
William Stein committed
8140 8141
    def has_python_operands(self):
        return self.operand2.type.is_pyobject
8142

William Stein's avatar
William Stein committed
8143 8144
    def coerce_operands_to_pyobjects(self, env):
        self.operand2 = self.operand2.coerce_to_pyobject(env)
8145 8146
        if self.operand2.type is dict_type and self.operator in ('in', 'not_in'):
            self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
William Stein's avatar
William Stein committed
8147 8148 8149 8150 8151 8152 8153 8154
        if self.cascade:
            self.cascade.coerce_operands_to_pyobjects(env)

    def coerce_cascaded_operands_to_temp(self, env):
        if self.cascade:
            #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
            self.operand2 = self.operand2.coerce_to_simple(env)
            self.cascade.coerce_cascaded_operands_to_temp(env)
8155

William Stein's avatar
William Stein committed
8156
    def generate_evaluation_code(self, code, result, operand1):
8157 8158
        if self.type.is_pyobject:
            code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
8159
            code.put_decref(result, self.type)
8160 8161
        else:
            code.putln("if (%s) {" % result)
William Stein's avatar
William Stein committed
8162
        self.operand2.generate_evaluation_code(code)
8163
        self.generate_operation_code(code, result,
William Stein's avatar
William Stein committed
8164 8165 8166 8167 8168 8169
            operand1, self.operator, self.operand2)
        if self.cascade:
            self.cascade.generate_evaluation_code(
                code, result, self.operand2)
        # Cascaded cmp result is always temp
        self.operand2.generate_disposal_code(code)
8170
        self.operand2.free_temps(code)
William Stein's avatar
William Stein committed
8171 8172
        code.putln("}")

8173 8174 8175 8176 8177
    def annotate(self, code):
        self.operand2.annotate(code)
        if self.cascade:
            self.cascade.annotate(code)

William Stein's avatar
William Stein committed
8178 8179

binop_node_classes = {
8180 8181
    "or":       BoolBinopNode,
    "and":      BoolBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
8182 8183 8184
    "|":        IntBinopNode,
    "^":        IntBinopNode,
    "&":        IntBinopNode,
8185 8186
    "<<":       IntBinopNode,
    ">>":       IntBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
8187 8188 8189
    "+":        AddNode,
    "-":        SubNode,
    "*":        MulNode,
8190 8191
    "/":        DivNode,
    "//":       DivNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
8192
    "%":        ModNode,
8193
    "**":       PowNode
William Stein's avatar
William Stein committed
8194 8195
}

8196
def binop_node(pos, operator, operand1, operand2, inplace=False):
8197
    # Construct binop node of appropriate class for
William Stein's avatar
William Stein committed
8198
    # given operator.
8199 8200 8201
    return binop_node_classes[operator](pos,
        operator = operator,
        operand1 = operand1,
8202 8203
        operand2 = operand2,
        inplace = inplace)
William Stein's avatar
William Stein committed
8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215

#-------------------------------------------------------------------
#
#  Coercion nodes
#
#  Coercion nodes are special in that they are created during
#  the analyse_types phase of parse tree processing.
#  Their __init__ methods consequently incorporate some aspects
#  of that phase.
#
#-------------------------------------------------------------------

8216
class CoercionNode(ExprNode):
William Stein's avatar
William Stein committed
8217 8218 8219
    #  Abstract base class for coercion nodes.
    #
    #  arg       ExprNode       node being coerced
8220

William Stein's avatar
William Stein committed
8221
    subexprs = ['arg']
8222
    constant_result = not_a_constant
8223

William Stein's avatar
William Stein committed
8224 8225 8226 8227
    def __init__(self, arg):
        self.pos = arg.pos
        self.arg = arg
        if debug_coercion:
Stefan Behnel's avatar
Stefan Behnel committed
8228
            print("%s Coercing %s" % (self, self.arg))
8229 8230

    def calculate_constant_result(self):
8231 8232
        # constant folding can break type coercion, so this is disabled
        pass
8233

8234 8235 8236 8237 8238
    def annotate(self, code):
        self.arg.annotate(code)
        if self.arg.type != self.type:
            file, line, col = self.pos
            code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
William Stein's avatar
William Stein committed
8239

8240
class CoerceToMemViewSliceNode(CoercionNode):
8241 8242

    def __init__(self, arg, dst_type, env):
8243 8244
        assert dst_type.is_memoryviewslice
        assert not arg.type.is_memoryviewslice
8245 8246
        CoercionNode.__init__(self, arg)
        self.type = dst_type
8247
        self.is_temp = 1
8248 8249
        self.env = env
        self.use_managed_ref = True
8250
        self.arg = arg
8251 8252

    def generate_result_code(self, code):
8253 8254 8255 8256 8257
        self.type.create_from_py_utility_code(self.env)
        code.putln("%s = %s(%s);" % (self.result(),
                                     self.type.from_py_function,
                                     self.arg.py_result()))

8258 8259 8260
        error_cond = self.type.error_condition(self.result())
        code.putln(code.error_goto_if(error_cond, self.pos))

William Stein's avatar
William Stein committed
8261 8262 8263

class CastNode(CoercionNode):
    #  Wrap a node in a C type cast.
8264

William Stein's avatar
William Stein committed
8265 8266 8267
    def __init__(self, arg, new_type):
        CoercionNode.__init__(self, arg)
        self.type = new_type
Stefan Behnel's avatar
Stefan Behnel committed
8268 8269 8270

    def may_be_none(self):
        return self.arg.may_be_none()
8271

William Stein's avatar
William Stein committed
8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283
    def calculate_result_code(self):
        return self.arg.result_as(self.type)

    def generate_result_code(self, code):
        self.arg.generate_result_code(code)


class PyTypeTestNode(CoercionNode):
    #  This node is used to check that a generic Python
    #  object is an instance of a particular extension type.
    #  This node borrows the result of its argument node.

8284
    def __init__(self, arg, dst_type, env, notnone=False):
William Stein's avatar
William Stein committed
8285 8286
        #  The arg is know to be a Python object, and
        #  the dst_type is known to be an extension type.
Robert Bradshaw's avatar
Robert Bradshaw committed
8287
        assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
William Stein's avatar
William Stein committed
8288 8289 8290
        CoercionNode.__init__(self, arg)
        self.type = dst_type
        self.result_ctype = arg.ctype()
8291
        self.notnone = notnone
8292

8293
    nogil_check = Node.gil_error
8294
    gil_message = "Python type test"
8295

8296 8297
    def analyse_types(self, env):
        pass
Stefan Behnel's avatar
Stefan Behnel committed
8298 8299 8300 8301 8302

    def may_be_none(self):
        if self.notnone:
            return False
        return self.arg.may_be_none()
8303

8304 8305 8306
    def is_simple(self):
        return self.arg.is_simple()

William Stein's avatar
William Stein committed
8307 8308
    def result_in_temp(self):
        return self.arg.result_in_temp()
8309

William Stein's avatar
William Stein committed
8310 8311
    def is_ephemeral(self):
        return self.arg.is_ephemeral()
8312 8313 8314 8315 8316

    def calculate_constant_result(self):
        # FIXME
        pass

William Stein's avatar
William Stein committed
8317
    def calculate_result_code(self):
8318
        return self.arg.result()
8319

William Stein's avatar
William Stein committed
8320 8321
    def generate_result_code(self, code):
        if self.type.typeobj_is_available():
8322
            if not self.type.is_builtin_type:
8323
                code.globalstate.use_utility_code(type_test_utility_code)
William Stein's avatar
William Stein committed
8324
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
8325
                "if (!(%s)) %s" % (
8326
                    self.type.type_test_code(self.arg.py_result(), self.notnone),
William Stein's avatar
William Stein committed
8327 8328 8329 8330
                    code.error_goto(self.pos)))
        else:
            error(self.pos, "Cannot test type of extern C class "
                "without type object name specification")
8331

William Stein's avatar
William Stein committed
8332 8333
    def generate_post_assignment_code(self, code):
        self.arg.generate_post_assignment_code(code)
8334 8335 8336

    def free_temps(self, code):
        self.arg.free_temps(code)
8337 8338 8339 8340 8341 8342 8343


class NoneCheckNode(CoercionNode):
    # This node is used to check that a Python object is not None and
    # raises an appropriate exception (as specified by the creating
    # transform).

8344 8345
    def __init__(self, arg, exception_type_cname, exception_message,
                 exception_format_args):
8346 8347 8348 8349 8350
        CoercionNode.__init__(self, arg)
        self.type = arg.type
        self.result_ctype = arg.ctype()
        self.exception_type_cname = exception_type_cname
        self.exception_message = exception_message
8351
        self.exception_format_args = tuple(exception_format_args or ())
8352 8353

    def analyse_types(self, env):
8354
        pass
8355

8356 8357 8358
    def may_be_none(self):
        return False

8359 8360 8361
    def is_simple(self):
        return self.arg.is_simple()

8362 8363 8364 8365 8366
    def result_in_temp(self):
        return self.arg.result_in_temp()

    def calculate_result_code(self):
        return self.arg.result()
8367

8368 8369
    def generate_result_code(self, code):
        code.putln(
8370
            "if (unlikely(%s == Py_None)) {" % self.arg.py_result())
8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384
        escape = StringEncoding.escape_byte_string
        if self.exception_format_args:
            code.putln('PyErr_Format(%s, "%s", %s); %s ' % (
                self.exception_type_cname,
                StringEncoding.escape_byte_string(
                    self.exception_message.encode('UTF-8')),
                ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8'))
                            for arg in self.exception_format_args ]),
                code.error_goto(self.pos)))
        else:
            code.putln('PyErr_SetString(%s, "%s"); %s ' % (
                self.exception_type_cname,
                escape(self.exception_message.encode('UTF-8')),
                code.error_goto(self.pos)))
8385 8386 8387 8388 8389 8390 8391 8392
        code.putln("}")

    def generate_post_assignment_code(self, code):
        self.arg.generate_post_assignment_code(code)

    def free_temps(self, code):
        self.arg.free_temps(code)

8393

William Stein's avatar
William Stein committed
8394 8395 8396
class CoerceToPyTypeNode(CoercionNode):
    #  This node is used to convert a C data type
    #  to a Python object.
8397

8398
    type = py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
8399
    is_temp = 1
William Stein's avatar
William Stein committed
8400

8401
    def __init__(self, arg, env, type=py_object_type):
8402
        if not arg.type.create_to_py_utility_code(env):
8403 8404 8405 8406 8407 8408 8409
            error(arg.pos, "Cannot convert '%s' to Python object" % arg.type)
        elif arg.type.is_complex:
            # special case: complex coercion is so complex that it
            # uses a macro ("__pyx_PyComplex_FromComplex()"), for
            # which the argument must be simple
            arg = arg.coerce_to_simple(env)
        CoercionNode.__init__(self, arg)
8410 8411 8412 8413
        if type is py_object_type:
            # be specific about some known types
            if arg.type.is_string:
                self.type = bytes_type
Stefan Behnel's avatar
Stefan Behnel committed
8414
            elif arg.type.is_unicode_char:
8415 8416 8417 8418 8419 8420
                self.type = unicode_type
            elif arg.type.is_complex:
                self.type = Builtin.complex_type
        else:
            # FIXME: check that the target type and the resulting type are compatible
            pass
8421

8422 8423 8424 8425
        if arg.type.is_memoryviewslice:
            # Register utility codes at this point
            arg.type.get_to_py_function(env, arg)

8426 8427
        self.env = env

8428
    gil_message = "Converting to Python object"
8429

8430 8431 8432 8433
    def may_be_none(self):
        # FIXME: is this always safe?
        return False

8434
    def coerce_to_boolean(self, env):
8435 8436 8437 8438 8439 8440
        arg_type = self.arg.type
        if (arg_type == PyrexTypes.c_bint_type or
            (arg_type.is_pyobject and arg_type.name == 'bool')):
            return self.arg.coerce_to_temp(env)
        else:
            return CoerceToBooleanNode(self, env)
8441

8442 8443 8444 8445 8446 8447
    def coerce_to_integer(self, env):
        # If not already some C integer type, coerce to longint.
        if self.arg.type.is_int:
            return self.arg
        else:
            return self.arg.coerce_to(PyrexTypes.c_long_type, env)
8448

8449 8450 8451 8452
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
8453
    def generate_result_code(self, code):
8454
        if self.arg.type.is_memoryviewslice:
8455
            funccall = self.arg.type.get_to_py_function(self.env, self.arg)
8456 8457 8458 8459 8460
        else:
            funccall = "%s(%s)" % (self.arg.type.to_py_function,
                                   self.arg.result())

        code.putln('%s = %s; %s' % (
8461
            self.result(),
8462
            funccall,
8463
            code.error_goto_if_null(self.result(), self.pos)))
8464

8465
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
8466 8467


8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507
class CoerceIntToBytesNode(CoerceToPyTypeNode):
    #  This node is used to convert a C int type to a Python bytes
    #  object.

    is_temp = 1

    def __init__(self, arg, env):
        arg = arg.coerce_to_simple(env)
        CoercionNode.__init__(self, arg)
        self.type = Builtin.bytes_type

    def generate_result_code(self, code):
        arg = self.arg
        arg_result = arg.result()
        if arg.type not in (PyrexTypes.c_char_type,
                            PyrexTypes.c_uchar_type,
                            PyrexTypes.c_schar_type):
            if arg.type.signed:
                code.putln("if ((%s < 0) || (%s > 255)) {" % (
                    arg_result, arg_result))
            else:
                code.putln("if (%s > 255) {" % arg_result)
            code.putln('PyErr_Format(PyExc_OverflowError, '
                       '"value too large to pack into a byte"); %s' % (
                           code.error_goto(self.pos)))
            code.putln('}')
        temp = None
        if arg.type is not PyrexTypes.c_char_type:
            temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False)
            code.putln("%s = (char)%s;" % (temp, arg_result))
            arg_result = temp
        code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % (
            self.result(),
            arg_result,
            code.error_goto_if_null(self.result(), self.pos)))
        if temp is not None:
            code.funcstate.release_temp(temp)
        code.put_gotref(self.py_result())


William Stein's avatar
William Stein committed
8508 8509 8510 8511 8512 8513 8514 8515
class CoerceFromPyTypeNode(CoercionNode):
    #  This node is used to convert a Python object
    #  to a C data type.

    def __init__(self, result_type, arg, env):
        CoercionNode.__init__(self, arg)
        self.type = result_type
        self.is_temp = 1
8516
        if not result_type.create_from_py_utility_code(env):
William Stein's avatar
William Stein committed
8517
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
8518
                  "Cannot convert Python object to '%s'" % result_type)
William Stein's avatar
William Stein committed
8519 8520
        if self.type.is_string and self.arg.is_ephemeral():
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
8521
                  "Obtaining char * from temporary Python value")
8522

8523 8524 8525 8526
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
8527 8528
    def generate_result_code(self, code):
        function = self.type.from_py_function
8529 8530 8531 8532
        operand = self.arg.py_result()
        rhs = "%s(%s)" % (function, operand)
        if self.type.is_enum:
            rhs = typecast(self.type, c_long_type, rhs)
Robert Bradshaw's avatar
Robert Bradshaw committed
8533
        code.putln('%s = %s; %s' % (
8534
            self.result(),
8535
            rhs,
8536
            code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
8537
        if self.type.is_pyobject:
8538
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
8539

8540 8541 8542
    def nogil_check(self, env):
        error(self.pos, "Coercion from Python not allowed without the GIL")

William Stein's avatar
William Stein committed
8543 8544 8545 8546

class CoerceToBooleanNode(CoercionNode):
    #  This node is used when a result needs to be used
    #  in a boolean context.
8547

8548
    type = PyrexTypes.c_bint_type
8549 8550 8551 8552

    _special_builtins = {
        Builtin.list_type    : 'PyList_GET_SIZE',
        Builtin.tuple_type   : 'PyTuple_GET_SIZE',
8553
        Builtin.bytes_type   : 'PyBytes_GET_SIZE',
8554 8555 8556
        Builtin.unicode_type : 'PyUnicode_GET_SIZE',
        }

William Stein's avatar
William Stein committed
8557 8558 8559 8560
    def __init__(self, arg, env):
        CoercionNode.__init__(self, arg)
        if arg.type.is_pyobject:
            self.is_temp = 1
8561

8562
    def nogil_check(self, env):
8563
        if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
8564
            self.gil_error()
8565

8566
    gil_message = "Truth-testing Python object"
8567

William Stein's avatar
William Stein committed
8568 8569 8570
    def check_const(self):
        if self.is_temp:
            self.not_const()
8571 8572
            return False
        return self.arg.check_const()
8573

William Stein's avatar
William Stein committed
8574
    def calculate_result_code(self):
8575
        return "(%s != 0)" % self.arg.result()
William Stein's avatar
William Stein committed
8576 8577

    def generate_result_code(self, code):
8578 8579 8580 8581
        if not self.is_temp:
            return
        test_func = self._special_builtins.get(self.arg.type)
        if test_func is not None:
Stefan Behnel's avatar
Stefan Behnel committed
8582
            code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
8583 8584 8585 8586 8587
                       self.result(),
                       self.arg.py_result(),
                       test_func,
                       self.arg.py_result()))
        else:
William Stein's avatar
William Stein committed
8588
            code.putln(
8589
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
8590 8591
                    self.result(),
                    self.arg.py_result(),
8592
                    code.error_goto_if_neg(self.result(), self.pos)))
William Stein's avatar
William Stein committed
8593

8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604
class CoerceToComplexNode(CoercionNode):

    def __init__(self, arg, dst_type, env):
        if arg.type.is_complex:
            arg = arg.coerce_to_simple(env)
        self.type = dst_type
        CoercionNode.__init__(self, arg)
        dst_type.create_declaration_utility_code(env)

    def calculate_result_code(self):
        if self.arg.type.is_complex:
8605 8606
            real_part = "__Pyx_CREAL(%s)" % self.arg.result()
            imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
8607 8608 8609 8610 8611 8612 8613
        else:
            real_part = self.arg.result()
            imag_part = "0"
        return "%s(%s, %s)" % (
                self.type.from_parts,
                real_part,
                imag_part)
8614

8615 8616
    def generate_result_code(self, code):
        pass
William Stein's avatar
William Stein committed
8617 8618 8619 8620 8621 8622 8623 8624 8625

class CoerceToTempNode(CoercionNode):
    #  This node is used to force the result of another node
    #  to be stored in a temporary. It is only used if the
    #  argument node's result is not already in a temporary.

    def __init__(self, arg, env):
        CoercionNode.__init__(self, arg)
        self.type = self.arg.type
8626
        self.constant_result = self.arg.constant_result
William Stein's avatar
William Stein committed
8627 8628 8629
        self.is_temp = 1
        if self.type.is_pyobject:
            self.result_ctype = py_object_type
8630 8631 8632

    gil_message = "Creating temporary Python reference"

8633 8634 8635
    def analyse_types(self, env):
        # The arg is always already analysed
        pass
8636

8637 8638
    def coerce_to_boolean(self, env):
        self.arg = self.arg.coerce_to_boolean(env)
8639 8640
        if self.arg.is_simple():
            return self.arg
8641 8642 8643
        self.type = self.arg.type
        self.result_ctype = self.type
        return self
8644

William Stein's avatar
William Stein committed
8645 8646 8647 8648
    def generate_result_code(self, code):
        #self.arg.generate_evaluation_code(code) # Already done
        # by generic generate_subexpr_evaluation_code!
        code.putln("%s = %s;" % (
8649
            self.result(), self.arg.result_as(self.ctype())))
8650
        if self.type.is_pyobject and self.use_managed_ref:
8651
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
8652 8653 8654 8655 8656 8657 8658


class CloneNode(CoercionNode):
    #  This node is employed when the result of another node needs
    #  to be used multiple times. The argument node's result must
    #  be in a temporary. This node "borrows" the result from the
    #  argument node, and does not generate any evaluation or
8659
    #  disposal code for it. The original owner of the argument
William Stein's avatar
William Stein committed
8660
    #  node is responsible for doing those things.
8661

William Stein's avatar
William Stein committed
8662
    subexprs = [] # Arg is not considered a subexpr
8663
    nogil_check = None
8664

William Stein's avatar
William Stein committed
8665 8666
    def __init__(self, arg):
        CoercionNode.__init__(self, arg)
8667 8668 8669 8670 8671
        if hasattr(arg, 'type'):
            self.type = arg.type
            self.result_ctype = arg.result_ctype
        if hasattr(arg, 'entry'):
            self.entry = arg.entry
8672

8673
    def result(self):
8674
        return self.arg.result()
8675

8676 8677 8678
    def may_be_none(self):
        return self.arg.may_be_none()

Robert Bradshaw's avatar
Robert Bradshaw committed
8679 8680
    def type_dependencies(self, env):
        return self.arg.type_dependencies(env)
8681

8682 8683
    def infer_type(self, env):
        return self.arg.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
8684

Robert Bradshaw's avatar
Robert Bradshaw committed
8685 8686 8687 8688
    def analyse_types(self, env):
        self.type = self.arg.type
        self.result_ctype = self.arg.result_ctype
        self.is_temp = 1
8689 8690
        if hasattr(self.arg, 'entry'):
            self.entry = self.arg.entry
8691

8692 8693 8694
    def is_simple(self):
        return True # result is always in a temp (or a name)

William Stein's avatar
William Stein committed
8695 8696 8697 8698 8699
    def generate_evaluation_code(self, code):
        pass

    def generate_result_code(self, code):
        pass
8700

8701
    def generate_disposal_code(self, code):
8702
        pass
8703

8704 8705
    def free_temps(self, code):
        pass
8706

8707

Stefan Behnel's avatar
Stefan Behnel committed
8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719
class CMethodSelfCloneNode(CloneNode):
    # Special CloneNode for the self argument of builtin C methods
    # that accepts subtypes of the builtin type.  This is safe only
    # for 'final' subtypes, as subtypes of the declared type may
    # override the C method.

    def coerce_to(self, dst_type, env):
        if dst_type.is_builtin_type and self.type.subtype_of(dst_type):
            return self
        return CloneNode.coerce_to(self, dst_type, env)


8720 8721
class ModuleRefNode(ExprNode):
    # Simple returns the module object
8722

8723 8724 8725
    type = py_object_type
    is_temp = False
    subexprs = []
8726

8727 8728 8729
    def analyse_types(self, env):
        pass

8730 8731 8732
    def may_be_none(self):
        return False

8733 8734 8735 8736 8737 8738 8739 8740
    def calculate_result_code(self):
        return Naming.module_cname

    def generate_result_code(self, code):
        pass

class DocstringRefNode(ExprNode):
    # Extracts the docstring of the body element
8741

8742 8743 8744
    subexprs = ['body']
    type = py_object_type
    is_temp = True
8745

8746 8747 8748 8749 8750 8751 8752 8753 8754
    def __init__(self, pos, body):
        ExprNode.__init__(self, pos)
        assert body.type.is_pyobject
        self.body = body

    def analyse_types(self, env):
        pass

    def generate_result_code(self, code):
8755 8756 8757
        code.putln('%s = __Pyx_GetAttrString(%s, "__doc__"); %s' % (
            self.result(), self.body.result(),
            code.error_goto_if_null(self.result(), self.pos)))
8758 8759 8760 8761
        code.put_gotref(self.result())



William Stein's avatar
William Stein committed
8762 8763 8764 8765 8766 8767
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

8768 8769
get_name_interned_utility_code = UtilityCode(
proto = """
8770
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
8771 8772
""",
impl = """
William Stein's avatar
William Stein committed
8773 8774 8775
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
    PyObject *result;
    result = PyObject_GetAttr(dict, name);
8776 8777 8778 8779 8780 8781 8782 8783 8784
    if (!result) {
        if (dict != %(BUILTINS)s) {
            PyErr_Clear();
            result = PyObject_GetAttr(%(BUILTINS)s, name);
        }
        if (!result) {
            PyErr_SetObject(PyExc_NameError, name);
        }
    }
William Stein's avatar
William Stein committed
8785 8786
    return result;
}
8787
""" % {'BUILTINS' : Naming.builtins_cname})
William Stein's avatar
William Stein committed
8788 8789 8790

#------------------------------------------------------------------------------------

8791 8792
import_utility_code = UtilityCode(
proto = """
Haoyu Bai's avatar
Haoyu Bai committed
8793
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
8794 8795
""",
impl = """
Haoyu Bai's avatar
Haoyu Bai committed
8796
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
8797
    PyObject *py_import = 0;
William Stein's avatar
William Stein committed
8798 8799 8800 8801 8802
    PyObject *empty_list = 0;
    PyObject *module = 0;
    PyObject *global_dict = 0;
    PyObject *empty_dict = 0;
    PyObject *list;
8803 8804
    py_import = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
    if (!py_import)
William Stein's avatar
William Stein committed
8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819
        goto bad;
    if (from_list)
        list = from_list;
    else {
        empty_list = PyList_New(0);
        if (!empty_list)
            goto bad;
        list = empty_list;
    }
    global_dict = PyModule_GetDict(%(GLOBALS)s);
    if (!global_dict)
        goto bad;
    empty_dict = PyDict_New();
    if (!empty_dict)
        goto bad;
Haoyu Bai's avatar
Haoyu Bai committed
8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833
    #if PY_VERSION_HEX >= 0x02050000
    {
        PyObject *py_level = PyInt_FromLong(level);
        if (!py_level)
            goto bad;
        module = PyObject_CallFunctionObjArgs(py_import,
            name, global_dict, empty_dict, list, py_level, NULL);
        Py_DECREF(py_level);
    }
    #else
    if (level>0) {
        PyErr_SetString(PyExc_RuntimeError, "Relative import is not supported for Python <=2.4.");
        goto bad;
    }
8834
    module = PyObject_CallFunctionObjArgs(py_import,
8835
        name, global_dict, empty_dict, list, NULL);
Haoyu Bai's avatar
Haoyu Bai committed
8836
    #endif
William Stein's avatar
William Stein committed
8837 8838
bad:
    Py_XDECREF(empty_list);
8839
    Py_XDECREF(py_import);
William Stein's avatar
William Stein committed
8840 8841 8842 8843 8844 8845
    Py_XDECREF(empty_dict);
    return module;
}
""" % {
    "BUILTINS": Naming.builtins_cname,
    "GLOBALS":  Naming.module_cname,
8846
})
William Stein's avatar
William Stein committed
8847 8848 8849

#------------------------------------------------------------------------------------

8850 8851
get_exception_utility_code = UtilityCode(
proto = """
8852
static PyObject *__Pyx_GetExcValue(void); /*proto*/
8853 8854
""",
impl = """
William Stein's avatar
William Stein committed
8855 8856
static PyObject *__Pyx_GetExcValue(void) {
    PyObject *type = 0, *value = 0, *tb = 0;
8857
    PyObject *tmp_type, *tmp_value, *tmp_tb;
William Stein's avatar
William Stein committed
8858 8859 8860 8861 8862 8863 8864 8865 8866 8867
    PyObject *result = 0;
    PyThreadState *tstate = PyThreadState_Get();
    PyErr_Fetch(&type, &value, &tb);
    PyErr_NormalizeException(&type, &value, &tb);
    if (PyErr_Occurred())
        goto bad;
    if (!value) {
        value = Py_None;
        Py_INCREF(value);
    }
8868 8869 8870
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
William Stein's avatar
William Stein committed
8871 8872 8873
    tstate->exc_type = type;
    tstate->exc_value = value;
    tstate->exc_traceback = tb;
8874 8875 8876 8877 8878
    /* Make sure tstate is in a consistent state when we XDECREF
    these objects (XDECREF may run arbitrary code). */
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
William Stein's avatar
William Stein committed
8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889
    result = value;
    Py_XINCREF(result);
    type = 0;
    value = 0;
    tb = 0;
bad:
    Py_XDECREF(type);
    Py_XDECREF(value);
    Py_XDECREF(tb);
    return result;
}
8890
""")
William Stein's avatar
William Stein committed
8891 8892 8893

#------------------------------------------------------------------------------------

8894 8895
type_test_utility_code = UtilityCode(
proto = """
8896
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
8897 8898
""",
impl = """
8899
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
8900
    if (unlikely(!type)) {
William Stein's avatar
William Stein committed
8901 8902 8903
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
8904
    if (likely(PyObject_TypeCheck(obj, type)))
William Stein's avatar
William Stein committed
8905
        return 1;
8906 8907
    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
                 Py_TYPE(obj)->tp_name, type->tp_name);
William Stein's avatar
William Stein committed
8908 8909
    return 0;
}
8910
""")
William Stein's avatar
William Stein committed
8911 8912 8913

#------------------------------------------------------------------------------------

8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924
find_py2_metaclass_utility_code = UtilityCode(
proto = '''
static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases); /*proto*/
''',
impl = '''
static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases) {
    PyObject *metaclass;
    /* Default metaclass */
#if PY_MAJOR_VERSION < 3
    if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
        PyObject *base = PyTuple_GET_ITEM(bases, 0);
8925
        metaclass = PyObject_GetAttrString(base, (char *)"__class__");
8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945
        if (!metaclass) {
            PyErr_Clear();
            metaclass = (PyObject*) Py_TYPE(base);
        }
    } else {
        metaclass = (PyObject *) &PyClass_Type;
    }
#else
    if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
        PyObject *base = PyTuple_GET_ITEM(bases, 0);
        metaclass = (PyObject*) Py_TYPE(base);
    } else {
        metaclass = (PyObject *) &PyType_Type;
    }
#endif
    Py_INCREF(metaclass);
    return metaclass;
}
''')

8946 8947
create_class_utility_code = UtilityCode(
proto = """
8948
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
8949 8950 8951 8952 8953
                                   PyObject *modname); /*proto*/
""",
impl = """
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
                                   PyObject *modname) {
8954 8955
    PyObject *result;
    PyObject *metaclass;
8956 8957 8958 8959 8960 8961

    if (PyDict_SetItemString(dict, "__module__", modname) < 0)
        return NULL;

    /* Python2 __metaclass__ */
    metaclass = PyDict_GetItemString(dict, "__metaclass__");
8962 8963 8964 8965
    if (metaclass) {
        Py_INCREF(metaclass);
    } else {
        metaclass = __Pyx_FindPy2Metaclass(bases);
8966 8967 8968 8969 8970
    }
    result = PyObject_CallFunctionObjArgs(metaclass, name, bases, dict, NULL);
    Py_DECREF(metaclass);
    return result;
}
8971 8972
""",
requires = [find_py2_metaclass_utility_code])
8973 8974 8975 8976 8977

#------------------------------------------------------------------------------------

create_py3class_utility_code = UtilityCode(
proto = """
Stefan Behnel's avatar
Stefan Behnel committed
8978 8979 8980
static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw); /*proto*/
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw, PyObject *modname, PyObject *doc); /*proto*/
static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw); /*proto*/
8981 8982
""",
impl = """
Stefan Behnel's avatar
Stefan Behnel committed
8983
PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw) {
8984
    PyObject *metaclass = PyDict_GetItemString(mkw, "metaclass");
8985 8986 8987 8988 8989 8990 8991 8992
    if (metaclass) {
        Py_INCREF(metaclass);
        if (PyDict_DelItemString(mkw, "metaclass") < 0) {
            Py_DECREF(metaclass);
            return NULL;
        }
        return metaclass;
    }
8993
    return __Pyx_FindPy2Metaclass(bases);
8994 8995
}

Stefan Behnel's avatar
Stefan Behnel committed
8996 8997
PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw,
                                    PyObject *modname, PyObject *doc) {
8998 8999 9000
    PyObject *prep;
    PyObject *pargs;
    PyObject *ns;
9001
    PyObject *str;
9002

9003
    prep = PyObject_GetAttrString(metaclass, (char *)"__prepare__");
Stefan Behnel's avatar
Stefan Behnel committed
9004
    if (!prep) {
9005
        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
9006
            return NULL;
9007
        PyErr_Clear();
9008
        return PyDict_New();
9009
    }
Stefan Behnel's avatar
Stefan Behnel committed
9010 9011
    pargs = PyTuple_New(2);
    if (!pargs) {
9012
        Py_DECREF(prep);
9013
        return NULL;
9014
    }
9015

Stefan Behnel's avatar
Stefan Behnel committed
9016 9017 9018 9019
    Py_INCREF(name);
    Py_INCREF(bases);
    PyTuple_SET_ITEM(pargs, 0, name);
    PyTuple_SET_ITEM(pargs, 1, bases);
9020

Stefan Behnel's avatar
Stefan Behnel committed
9021
    ns = PyObject_Call(prep, pargs, mkw);
9022

9023
    Py_DECREF(prep);
9024 9025
    Py_DECREF(pargs);

9026
    if (ns == NULL)
9027 9028 9029 9030
        return NULL;

    /* Required here to emulate assignment order */
    /* XXX: use consts here */
Stefan Behnel's avatar
Stefan Behnel committed
9031 9032 9033
    #if PY_MAJOR_VERSION >= 3
    str = PyUnicode_FromString("__module__");
    #else
9034
    str = PyString_FromString("__module__");
Stefan Behnel's avatar
Stefan Behnel committed
9035
    #endif
9036
    if (!str) {
9037
        Py_DECREF(ns);
9038
        return NULL;
9039
    }
Vitja Makarov's avatar
Vitja Makarov committed
9040

9041 9042 9043
    if (PyObject_SetItem(ns, str, modname) < 0) {
        Py_DECREF(ns);
        Py_DECREF(str);
9044
        return NULL;
9045 9046 9047
    }
    Py_DECREF(str);
    if (doc) {
Stefan Behnel's avatar
Stefan Behnel committed
9048 9049 9050
        #if PY_MAJOR_VERSION >= 3
        str = PyUnicode_FromString("__doc__");
        #else
9051
        str = PyString_FromString("__doc__");
Stefan Behnel's avatar
Stefan Behnel committed
9052
        #endif
9053 9054
        if (!str) {
            Py_DECREF(ns);
9055
            return NULL;
Vitja Makarov's avatar
Vitja Makarov committed
9056
        }
9057 9058 9059 9060
        if (PyObject_SetItem(ns, str, doc) < 0) {
            Py_DECREF(ns);
            Py_DECREF(str);
            return NULL;
Stefan Behnel's avatar
Stefan Behnel committed
9061
        }
9062
        Py_DECREF(str);
Vitja Makarov's avatar
Vitja Makarov committed
9063
    }
9064 9065 9066
    return ns;
}

Stefan Behnel's avatar
Stefan Behnel committed
9067
PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw) {
9068
    PyObject *result;
9069
    PyObject *margs = PyTuple_New(3);
9070 9071
    if (!margs)
        return NULL;
9072 9073 9074 9075 9076 9077
    Py_INCREF(name);
    Py_INCREF(bases);
    Py_INCREF(dict);
    PyTuple_SET_ITEM(margs, 0, name);
    PyTuple_SET_ITEM(margs, 1, bases);
    PyTuple_SET_ITEM(margs, 2, dict);
Stefan Behnel's avatar
Stefan Behnel committed
9078
    result = PyObject_Call(metaclass, margs, mkw);
9079
    Py_DECREF(margs);
William Stein's avatar
William Stein committed
9080 9081
    return result;
}
9082 9083
""",
requires = [find_py2_metaclass_utility_code])
William Stein's avatar
William Stein committed
9084 9085

#------------------------------------------------------------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
9086

9087 9088
cpp_exception_utility_code = UtilityCode(
proto = """
9089 9090
#ifndef __Pyx_CppExn2PyErr
static void __Pyx_CppExn2PyErr() {
9091 9092
  // Catch a handful of different errors here and turn them into the
  // equivalent Python errors.
Robert Bradshaw's avatar
Robert Bradshaw committed
9093 9094 9095 9096 9097
  try {
    if (PyErr_Occurred())
      ; // let the latest Python exn pass through and ignore the current one
    else
      throw;
9098 9099
  } catch (const std::bad_alloc& exn) {
    PyErr_SetString(PyExc_MemoryError, exn.what());
9100 9101
  } catch (const std::bad_cast& exn) {
    PyErr_SetString(PyExc_TypeError, exn.what());
9102 9103 9104 9105
  } catch (const std::domain_error& exn) {
    PyErr_SetString(PyExc_ValueError, exn.what());
  } catch (const std::invalid_argument& exn) {
    PyErr_SetString(PyExc_ValueError, exn.what());
9106 9107 9108 9109
  } catch (const std::ios_base::failure& exn) {
    // Unfortunately, in standard C++ we have no way of distinguishing EOF
    // from other errors here; be careful with the exception mask
    PyErr_SetString(PyExc_IOError, exn.what());
Robert Bradshaw's avatar
Robert Bradshaw committed
9110
  } catch (const std::out_of_range& exn) {
9111
    // Change out_of_range to IndexError
Robert Bradshaw's avatar
Robert Bradshaw committed
9112
    PyErr_SetString(PyExc_IndexError, exn.what());
9113 9114 9115 9116 9117 9118
  } catch (const std::overflow_error& exn) {
    PyErr_SetString(PyExc_OverflowError, exn.what());
  } catch (const std::range_error& exn) {
    PyErr_SetString(PyExc_ArithmeticError, exn.what());
  } catch (const std::underflow_error& exn) {
    PyErr_SetString(PyExc_ArithmeticError, exn.what());
Robert Bradshaw's avatar
Robert Bradshaw committed
9119 9120 9121 9122 9123 9124 9125 9126
  } catch (const std::exception& exn) {
    PyErr_SetString(PyExc_RuntimeError, exn.what());
  }
  catch (...)
  {
    PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
  }
}
9127
#endif
9128 9129 9130
""",
impl = ""
)
Robert Bradshaw's avatar
Robert Bradshaw committed
9131

9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150
pyerr_occurred_withgil_utility_code= UtilityCode(
proto = """
static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
""",
impl = """
static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
  int err;
  #ifdef WITH_THREAD
  PyGILState_STATE _save = PyGILState_Ensure();
  #endif
  err = !!PyErr_Occurred();
  #ifdef WITH_THREAD
  PyGILState_Release(_save);
  #endif
  return err;
}
"""
)

Robert Bradshaw's avatar
Robert Bradshaw committed
9151
#------------------------------------------------------------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
9152

9153 9154 9155 9156 9157 9158 9159 9160 9161 9162
raise_noneattr_error_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
""",
impl = '''
static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
}
''')

9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182
raise_noneindex_error_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void);
""",
impl = '''
static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void) {
    PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
}
''')

raise_none_iter_error_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
""",
impl = '''
static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
}
''')

9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202
raise_unbound_local_error_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);
""",
impl = """
static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) {
    PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname);
}
""")

raise_closure_name_error_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);
""",
impl = """
static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
    PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname);
}
""")

9203 9204 9205 9206
#------------------------------------------------------------------------------------

getitem_dict_utility_code = UtilityCode(
proto = """
9207
#if PY_MAJOR_VERSION >= 3
9208
static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
9209
    PyObject *value;
9210
    if (unlikely(d == Py_None)) {
9211 9212 9213
        __Pyx_RaiseNoneIndexingError();
        return NULL;
    }
9214 9215 9216
    value = PyDict_GetItemWithError(d, key);
    if (unlikely(!value)) {
        if (!PyErr_Occurred())
9217
            PyErr_SetObject(PyExc_KeyError, key);
9218
        return NULL;
9219
    }
9220 9221
    Py_INCREF(value);
    return value;
9222
}
9223 9224 9225
#else
    #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
#endif
9226
""",
9227 9228 9229
requires = [raise_noneindex_error_utility_code])

#------------------------------------------------------------------------------------
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9230

9231 9232 9233 9234
getitem_int_pyunicode_utility_code = UtilityCode(
proto = '''
#define __Pyx_GetItemInt_Unicode(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                               __Pyx_GetItemInt_Unicode_Fast(o, i) : \\
Stefan Behnel's avatar
Stefan Behnel committed
9235
                                               __Pyx_GetItemInt_Unicode_Generic(o, to_py_func(i)))
9236

9237
static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i) {
9238 9239 9240 9241 9242
    const Py_ssize_t length = __Pyx_PyUnicode_GET_LENGTH(ustring);
    if (likely((0 <= i) & (i < length))) {
        return __Pyx_PyUnicode_READ_CHAR(ustring, i);
    } else if ((-length <= i) & (i < 0)) {
        return __Pyx_PyUnicode_READ_CHAR(ustring, i + length);
9243 9244
    } else {
        PyErr_SetString(PyExc_IndexError, "string index out of range");
9245
        return (Py_UCS4)-1;
9246 9247 9248
    }
}

9249 9250
static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Generic(PyObject* ustring, PyObject* j) {
    Py_UCS4 uchar;
9251
    PyObject *uchar_string;
9252
    if (!j) return (Py_UCS4)-1;
9253
    uchar_string = PyObject_GetItem(ustring, j);
9254
    Py_DECREF(j);
9255
    if (!uchar_string) return (Py_UCS4)-1;
9256
    uchar = __Pyx_PyUnicode_READ_CHAR(uchar_string, 0);
9257
    Py_DECREF(uchar_string);
9258 9259
    return uchar;
}
9260
''')
9261

9262 9263
getitem_int_utility_code = UtilityCode(
proto = """
9264

9265
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
9266
    PyObject *r;
9267
    if (!j) return NULL;
9268 9269 9270 9271
    r = PyObject_GetItem(o, j);
    Py_DECREF(j);
    return r;
}
9272

9273 9274
""" + ''.join([
"""
9275 9276
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
9277 9278
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

9279
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
9280 9281 9282 9283 9284 9285
    if (likely(o != Py_None)) {
        if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
            PyObject *r = Py%(type)s_GET_ITEM(o, i);
            Py_INCREF(r);
            return r;
        }
9286 9287
        else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
            PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
9288 9289 9290
            Py_INCREF(r);
            return r;
        }
9291
    }
9292
    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
9293
}
9294 9295
""" % {'type' : type_name} for type_name in ('List', 'Tuple')
]) + """
9296

9297 9298
#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_Fast(o, i) : \\
9299 9300
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

9301
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
9302 9303 9304 9305 9306 9307 9308
    if (PyList_CheckExact(o)) {
        Py_ssize_t n = (likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
        if (likely((n >= 0) & (n < PyList_GET_SIZE(o)))) {
            PyObject *r = PyList_GET_ITEM(o, n);
            Py_INCREF(r);
            return r;
        }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9309
    }
9310 9311 9312 9313 9314 9315 9316
    else if (PyTuple_CheckExact(o)) {
        Py_ssize_t n = (likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
        if (likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) {
            PyObject *r = PyTuple_GET_ITEM(o, n);
            Py_INCREF(r);
            return r;
        }
9317
    }
9318 9319 9320 9321 9322
    else if (likely(i >= 0)) {
        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
        if (likely(m && m->sq_item)) {
            return m->sq_item(o, i);
        }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9323
    }
9324
    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9325 9326
}
""",
9327 9328
impl = """
""")
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9329

9330 9331


Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9332 9333
#------------------------------------------------------------------------------------

9334 9335
setitem_int_utility_code = UtilityCode(
proto = """
9336 9337
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_SetItemInt_Fast(o, i, v) : \\
9338 9339
                                                    __Pyx_SetItemInt_Generic(o, to_py_func(i), v))

9340
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9341
    int r;
9342 9343 9344 9345 9346 9347
    if (!j) return -1;
    r = PyObject_SetItem(o, j, v);
    Py_DECREF(j);
    return r;
}

9348
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
9349 9350 9351
    if (PyList_CheckExact(o)) {
        Py_ssize_t n = (likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
        if (likely((n >= 0) & (n < PyList_GET_SIZE(o)))) {
9352
            PyObject* old = PyList_GET_ITEM(o, n);
9353
            Py_INCREF(v);
9354
            PyList_SET_ITEM(o, n, v);
9355 9356 9357
            Py_DECREF(old);
            return 1;
        }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9358
    }
9359 9360 9361 9362 9363
    else if (likely(i >= 0)) {
        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
        if (likely(m && m->sq_ass_item)) {
            return m->sq_ass_item(o, i, v);
        }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9364
    }
9365
    return __Pyx_SetItemInt_Generic(o, PyInt_FromSsize_t(i), v);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
9366 9367
}
""",
9368 9369 9370
impl = """
""")

9371 9372
#------------------------------------------------------------------------------------

9373 9374
delitem_int_utility_code = UtilityCode(
proto = """
9375 9376
#define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_DelItemInt_Fast(o, i) : \\
9377 9378
                                                    __Pyx_DelItem_Generic(o, to_py_func(i)))

9379
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
9380
    int r;
9381 9382 9383 9384 9385 9386
    if (!j) return -1;
    r = PyObject_DelItem(o, j);
    Py_DECREF(j);
    return r;
}

9387
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
9388 9389 9390 9391 9392
    if (likely(i >= 0)) {
        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
        if (likely(m && m->sq_ass_item)) {
            return m->sq_ass_item(o, i, (PyObject *)NULL);
        }
9393
    }
9394
    return __Pyx_DelItem_Generic(o, PyInt_FromSsize_t(i));
9395 9396 9397 9398 9399 9400 9401
}
""",
impl = """
""")

#------------------------------------------------------------------------------------

9402 9403
raise_too_many_values_to_unpack = UtilityCode(
proto = """
9404
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
9405 9406
""",
impl = '''
9407 9408
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
    PyErr_Format(PyExc_ValueError,
9409
                 "too many values to unpack (expected %"PY_FORMAT_SIZE_T"d)", expected);
9410 9411 9412 9413 9414
}
''')

raise_need_more_values_to_unpack = UtilityCode(
proto = """
9415
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
9416 9417
""",
impl = '''
9418
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
9419
    PyErr_Format(PyExc_ValueError,
9420 9421
                 "need more than %"PY_FORMAT_SIZE_T"d value%s to unpack",
                 index, (index == 1) ? "" : "s");
9422 9423 9424 9425 9426
}
''')

#------------------------------------------------------------------------------------

9427 9428 9429
tuple_unpacking_error_code = UtilityCode(
proto = """
static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
9430
""",
9431 9432 9433 9434 9435 9436 9437
impl = """
static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
    if (t == Py_None) {
      __Pyx_RaiseNoneNotIterableError();
    } else if (PyTuple_GET_SIZE(t) < index) {
      __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
    } else {
9438
      __Pyx_RaiseTooManyValuesError(index);
9439 9440
    }
}
9441
""",
9442 9443 9444 9445 9446
requires = [raise_none_iter_error_utility_code,
            raise_need_more_values_to_unpack,
            raise_too_many_values_to_unpack]
)

9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460
unpacking_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
""",
impl = """
static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
    PyObject *item;
    if (!(item = PyIter_Next(iter))) {
        if (!PyErr_Occurred()) {
            __Pyx_RaiseNeedMoreValuesError(index);
        }
    }
    return item;
}
9461 9462 9463
""",
requires = [raise_need_more_values_to_unpack]
)
9464

9465 9466 9467 9468 9469 9470 9471 9472
iternext_unpacking_end_utility_code = UtilityCode(
proto = """
static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); /*proto*/
""",
impl = """
static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
    if (unlikely(retval)) {
        Py_DECREF(retval);
9473
        __Pyx_RaiseTooManyValuesError(expected);
9474
        return -1;
9475 9476 9477 9478 9479 9480 9481
    } else if (PyErr_Occurred()) {
        if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) {
            PyErr_Clear();
            return 0;
        } else {
            return -1;
        }
9482
    }
9483
    return 0;
9484 9485
}
""",
9486
requires = [raise_too_many_values_to_unpack]
9487
)
Robert Bradshaw's avatar
Robert Bradshaw committed
9488

9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500
#------------------------------------------------------------------------------------

# CPython supports calling functions with non-dict kwargs by
# converting them to a dict first

kwargs_call_utility_code = UtilityCode(
proto = """
static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject*, PyObject*, PyObject*); /*proto*/
""",
impl = """
static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs) {
    PyObject* result;
9501
    if (likely(PyDict_Check(kwargs))) {
9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512
        return PyEval_CallObjectWithKeywords(callable, args, kwargs);
    } else {
        PyObject* real_dict;
        real_dict = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, kwargs, NULL);
        if (unlikely(!real_dict))
            return NULL;
        result = PyEval_CallObjectWithKeywords(callable, args, real_dict);
        Py_DECREF(real_dict);
        return result; /* may be NULL */
    }
}
9513
""",
9514 9515
)

Robert Bradshaw's avatar
Robert Bradshaw committed
9516 9517 9518 9519 9520

#------------------------------------------------------------------------------------

int_pow_utility_code = UtilityCode(
proto="""
9521
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
9522 9523
""",
impl="""
9524
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
Robert Bradshaw's avatar
Robert Bradshaw committed
9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545
    %(type)s t = b;
    switch (e) {
        case 3:
            t *= b;
        case 2:
            t *= b;
        case 1:
            return t;
        case 0:
            return 1;
    }
    if (unlikely(e<0)) return 0;
    t = 1;
    while (likely(e)) {
        t *= (b * (e&1)) | ((~e)&1);    /* 1 or b */
        b *= b;
        e >>= 1;
    }
    return t;
}
""")
9546 9547 9548

# ------------------------------ Division ------------------------------------

9549 9550
div_int_utility_code = UtilityCode(
proto="""
9551
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
9552 9553
""",
impl="""
9554
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
9555 9556 9557 9558 9559
    %(type)s q = a / b;
    %(type)s r = a - q*b;
    q -= ((r != 0) & ((r ^ b) < 0));
    return q;
}
9560 9561
""")

9562
mod_int_utility_code = UtilityCode(
9563
proto="""
9564
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
9565 9566
""",
impl="""
9567
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
9568 9569 9570
    %(type)s r = a %% b;
    r += ((r != 0) & ((r ^ b) < 0)) * b;
    return r;
9571 9572 9573
}
""")

9574
mod_float_utility_code = UtilityCode(
9575
proto="""
9576
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
9577 9578
""",
impl="""
9579
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
9580 9581 9582
    %(type)s r = fmod%(math_h_modifier)s(a, b);
    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
    return r;
9583 9584
}
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
9585

9586
cdivision_warning_utility_code = UtilityCode(
Robert Bradshaw's avatar
Robert Bradshaw committed
9587
proto="""
9588
static int __Pyx_cdivision_warning(const char *, int); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
9589 9590
""",
impl="""
9591
static int __Pyx_cdivision_warning(const char *filename, int lineno) {
9592
    return PyErr_WarnExplicit(PyExc_RuntimeWarning,
9593
                              "division with oppositely signed operands, C and Python semantics differ",
9594 9595
                              filename,
                              lineno,
9596
                              __Pyx_MODULE_NAME,
9597
                              NULL);
Robert Bradshaw's avatar
Robert Bradshaw committed
9598
}
9599
""")
9600 9601 9602 9603

# from intobject.c
division_overflow_test_code = UtilityCode(
proto="""
Vitja Makarov's avatar
Vitja Makarov committed
9604 9605
#define UNARY_NEG_WOULD_OVERFLOW(x)    \
        (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
9606
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
9607 9608 9609 9610


binding_cfunc_utility_code = UtilityCode(
proto="""
9611 9612
#define __Pyx_CyFunction_USED 1
#include <structmember.h>
Robert Bradshaw's avatar
Robert Bradshaw committed
9613 9614 9615

typedef struct {
    PyCFunctionObject func;
9616
    PyObject *func_dict;
9617
    PyObject *func_weakreflist;
9618
    PyObject *func_name;
9619
    PyObject *func_doc;
9620
    PyObject *func_code;
9621
} __pyx_CyFunctionObject;
Robert Bradshaw's avatar
Robert Bradshaw committed
9622

9623
static PyTypeObject *__pyx_CyFunctionType = 0;
Robert Bradshaw's avatar
Robert Bradshaw committed
9624

9625
static PyObject *__Pyx_CyFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module, PyObject* code);
Robert Bradshaw's avatar
Robert Bradshaw committed
9626

9627
static int __Pyx_CyFunction_init(void);
Robert Bradshaw's avatar
Robert Bradshaw committed
9628 9629
""" % Naming.__dict__,
impl="""
9630
static PyObject *
9631
__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
9632
{
9633
    if (op->func_doc == NULL && op->func.m_ml->ml_doc) {
9634
#if PY_MAJOR_VERSION >= 3
9635
        op->func_doc = PyUnicode_FromString(op->func.m_ml->ml_doc);
9636
#else
9637
        op->func_doc = PyString_FromString(op->func.m_ml->ml_doc);
9638
#endif
9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650
    }
    if (op->func_doc == 0) {
        Py_INCREF(Py_None);
        return Py_None;
    }
    Py_INCREF(op->func_doc);
    return op->func_doc;
}

static int
__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value)
{
9651 9652
    PyObject *tmp = op->func_doc;
    if (value == NULL)
9653
        op->func_doc = Py_None; /* Mark as deleted */
9654
    else
9655
        op->func_doc = value;
9656 9657
    Py_INCREF(op->func_doc);
    Py_XDECREF(tmp);
9658
    return 0;
9659 9660 9661
}

static PyObject *
9662
__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op)
9663
{
9664
    if (op->func_name == NULL) {
9665
#if PY_MAJOR_VERSION >= 3
9666
        op->func_name = PyUnicode_InternFromString(op->func.m_ml->ml_name);
9667
#else
9668
        op->func_name = PyString_InternFromString(op->func.m_ml->ml_name);
9669
#endif
9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693
    }
    Py_INCREF(op->func_name);
    return op->func_name;
}

static int
__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value)
{
    PyObject *tmp;

#if PY_MAJOR_VERSION >= 3
    if (value == NULL || !PyUnicode_Check(value)) {
#else
    if (value == NULL || !PyString_Check(value)) {
#endif
        PyErr_SetString(PyExc_TypeError,
                        "__name__ must be set to a string object");
        return -1;
    }
    tmp = op->func_name;
    Py_INCREF(value);
    op->func_name = value;
    Py_XDECREF(tmp);
    return 0;
9694 9695 9696
}

static PyObject *
9697
__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure)
9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740
{
    PyObject *self;

    self = m->func.m_self;
    if (self == NULL)
        self = Py_None;
    Py_INCREF(self);
    return self;
}

static PyObject *
__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op)
{
    if (op->func_dict == NULL) {
        op->func_dict = PyDict_New();
        if (op->func_dict == NULL)
            return NULL;
    }
    Py_INCREF(op->func_dict);
    return op->func_dict;
}

static int
__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
{
    PyObject *tmp;

    if (value == NULL) {
        PyErr_SetString(PyExc_TypeError,
               "function's dictionary may not be deleted");
        return -1;
    }
    if (!PyDict_Check(value)) {
        PyErr_SetString(PyExc_TypeError,
               "setting function's dictionary to a non-dict");
        return -1;
    }
    tmp = op->func_dict;
    Py_INCREF(value);
    op->func_dict = value;
    Py_XDECREF(tmp);
    return 0;
}
9741 9742 9743 9744 9745 9746 9747
""" + (
# TODO: we implicitly use the global module to get func_globals.  This
# will need to be passed into __Pyx_CyFunction_NewEx() if we share
# this type accross modules.  We currently avoid doing this to reduce
# the overhead of creating a function object, and to avoid keeping a
# reference to the module dict as long as we don't need to.
"""
9748
static PyObject *
9749
__Pyx_CyFunction_get_globals(CYTHON_UNUSED __pyx_CyFunctionObject *op)
9750
{
9751 9752 9753
    PyObject* dict = PyModule_GetDict(%(module_cname)s);
    Py_XINCREF(dict);
    return dict;
9754
}
9755 9756
""" % Naming.__dict__ ) +
"""
9757
static PyObject *
9758
__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op)
9759 9760 9761 9762 9763
{
    Py_INCREF(Py_None);
    return Py_None;
}

9764 9765 9766 9767 9768 9769 9770 9771
static PyObject *
__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op)
{
    PyObject* result = (op->func_code) ? op->func_code : Py_None;
    Py_INCREF(result);
    return result;
}

9772
static PyGetSetDef __pyx_CyFunction_getsets[] = {
9773 9774 9775 9776 9777 9778 9779
    {(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
    {(char *) "__doc__",  (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
    {(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
    {(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
    {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0},
    {(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
    {(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
9780 9781 9782 9783
    {(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
    {(char *) "__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
    {(char *) "func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
    {(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
9784 9785
    {(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
    {(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
9786 9787 9788
    {0, 0, 0, 0, 0}
};

9789 9790 9791
#ifndef PY_WRITE_RESTRICTED /* < Py2.5 */
#define PY_WRITE_RESTRICTED WRITE_RESTRICTED
#endif
Robert Bradshaw's avatar
Robert Bradshaw committed
9792

Vitja Makarov's avatar
Vitja Makarov committed
9793
static PyMemberDef __pyx_CyFunction_members[] = {
9794 9795
    {(char *) "__module__", T_OBJECT, offsetof(__pyx_CyFunctionObject, func.m_module), PY_WRITE_RESTRICTED, 0},
    {0, 0, 0,  0, 0}
Vitja Makarov's avatar
Vitja Makarov committed
9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808
};

static PyObject *
__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args)
{
#if PY_MAJOR_VERSION >= 3
    return PyUnicode_FromString(m->func.m_ml->ml_name);
#else
    return PyString_FromString(m->func.m_ml->ml_name);
#endif
}

static PyMethodDef __pyx_CyFunction_methods[] = {
9809
    {__Pyx_NAMESTR("__reduce__"), (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0},
Vitja Makarov's avatar
Vitja Makarov committed
9810 9811 9812
    {0, 0, 0, 0}
};

9813

9814
static PyObject *__Pyx_CyFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module, PyObject* code) {
9815
    __pyx_CyFunctionObject *op = PyObject_GC_New(__pyx_CyFunctionObject, __pyx_CyFunctionType);
Robert Bradshaw's avatar
Robert Bradshaw committed
9816 9817
    if (op == NULL)
        return NULL;
9818
    op->func_weakreflist = NULL;
Vitja Makarov's avatar
Vitja Makarov committed
9819 9820 9821 9822 9823
    op->func.m_ml = ml;
    Py_XINCREF(self);
    op->func.m_self = self;
    Py_XINCREF(module);
    op->func.m_module = module;
9824
    op->func_dict = NULL;
9825
    op->func_name = NULL;
9826
    op->func_doc = NULL;
9827 9828
    Py_XINCREF(code);
    op->func_code = code;
Vitja Makarov's avatar
Vitja Makarov committed
9829 9830
    PyObject_GC_Track(op);
    return (PyObject *)op;
Robert Bradshaw's avatar
Robert Bradshaw committed
9831 9832
}

9833 9834
static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
{
Vitja Makarov's avatar
Vitja Makarov committed
9835
    PyObject_GC_UnTrack(m);
9836 9837
    if (m->func_weakreflist != NULL)
        PyObject_ClearWeakRefs((PyObject *) m);
Vitja Makarov's avatar
Vitja Makarov committed
9838 9839
    Py_XDECREF(m->func.m_self);
    Py_XDECREF(m->func.m_module);
9840
    Py_XDECREF(m->func_dict);
9841
    Py_XDECREF(m->func_name);
9842
    Py_XDECREF(m->func_doc);
9843
    Py_XDECREF(m->func_code);
Robert Bradshaw's avatar
Robert Bradshaw committed
9844 9845 9846
    PyObject_GC_Del(m);
}

9847 9848 9849 9850 9851
static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg)
{
    Py_VISIT(m->func.m_self);
    Py_VISIT(m->func.m_module);
    Py_VISIT(m->func_dict);
9852 9853
    Py_VISIT(m->func_name);
    Py_VISIT(m->func_doc);
9854
    Py_VISIT(m->func_code);
9855 9856 9857 9858 9859
    return 0;
}

static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
Vitja Makarov's avatar
Vitja Makarov committed
9860
    if (obj == Py_None)
9861
        obj = NULL;
Vitja Makarov's avatar
Vitja Makarov committed
9862
    return PyMethod_New(func, obj, type);
Robert Bradshaw's avatar
Robert Bradshaw committed
9863 9864
}

9865 9866 9867
static PyObject*
__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
{
9868 9869
    PyObject *func_name = __Pyx_CyFunction_get_name(op);

9870
#if PY_MAJOR_VERSION >= 3
9871
    return PyUnicode_FromFormat("<cyfunction %U at %p>",
9872
                               func_name, op);
9873
#else
9874
    return PyString_FromFormat("<cyfunction %s at %p>",
9875
                               PyString_AsString(func_name), op);
9876 9877 9878
#endif
}

9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892
static PyTypeObject __pyx_CyFunctionType_type = {
    PyVarObject_HEAD_INIT(0, 0)
    __Pyx_NAMESTR("cython_function_or_method"), /*tp_name*/
    sizeof(__pyx_CyFunctionObject),   /*tp_basicsize*/
    0,                                  /*tp_itemsize*/
    (destructor) __Pyx_CyFunction_dealloc, /*tp_dealloc*/
    0,                                  /*tp_print*/
    0,                                  /*tp_getattr*/
    0,                                  /*tp_setattr*/
#if PY_MAJOR_VERSION < 3
    0,                                  /*tp_compare*/
#else
    0,                                  /*reserved*/
#endif
9893
    (reprfunc) __Pyx_CyFunction_repr,   /*tp_repr*/
9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907
    0,                                  /*tp_as_number*/
    0,                                  /*tp_as_sequence*/
    0,                                  /*tp_as_mapping*/
    0,                                  /*tp_hash*/
    PyCFunction_Call,                   /*tp_call*/
    0,                                  /*tp_str*/
    0,                                  /*tp_getattro*/
    0,                                  /*tp_setattro*/
    0,                                  /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags*/
    0,                                  /*tp_doc*/
    (traverseproc) __Pyx_CyFunction_traverse,   /*tp_traverse*/
    0,                                  /*tp_clear*/
    0,                                  /*tp_richcompare*/
9908
    offsetof(__pyx_CyFunctionObject, func_weakreflist), /* tp_weaklistoffse */
9909 9910
    0,                                  /*tp_iter*/
    0,                                  /*tp_iternext*/
Vitja Makarov's avatar
Vitja Makarov committed
9911 9912
    __pyx_CyFunction_methods,           /*tp_methods*/
    __pyx_CyFunction_members,           /*tp_members*/
9913
    __pyx_CyFunction_getsets,           /*tp_getset*/
Vitja Makarov's avatar
Vitja Makarov committed
9914
    0,                                  /*tp_base*/
9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938
    0,                                  /*tp_dict*/
    __Pyx_CyFunction_descr_get,         /*tp_descr_get*/
    0,                                  /*tp_descr_set*/
    offsetof(__pyx_CyFunctionObject, func_dict),/*tp_dictoffset*/
    0,                                  /*tp_init*/
    0,                                  /*tp_alloc*/
    0,                                  /*tp_new*/
    0,                                  /*tp_free*/
    0,                                  /*tp_is_gc*/
    0,                                  /*tp_bases*/
    0,                                  /*tp_mro*/
    0,                                  /*tp_cache*/
    0,                                  /*tp_subclasses*/
    0,                                  /*tp_weaklist*/
    0,                                  /*tp_del*/
#if PY_VERSION_HEX >= 0x02060000
    0,                                  /*tp_version_tag*/
#endif
};


static int __Pyx_CyFunction_init(void)
{
    if (PyType_Ready(&__pyx_CyFunctionType_type) < 0)
Robert Bradshaw's avatar
Robert Bradshaw committed
9939
        return -1;
9940
    __pyx_CyFunctionType = &__pyx_CyFunctionType_type;
Robert Bradshaw's avatar
Robert Bradshaw committed
9941 9942
    return 0;
}
9943
""")
9944 9945 9946

generator_utility_code = UtilityCode(
proto="""
9947 9948 9949 9950
static PyObject *__Pyx_Generator_Next(PyObject *self);
static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value);
static PyObject *__Pyx_Generator_Close(PyObject *self);
static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args, CYTHON_UNUSED PyObject *kwds);
9951

9952
typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
9953 9954
""",
impl="""
9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965
static CYTHON_INLINE void __Pyx_Generator_ExceptionClear(struct __pyx_Generator_object *self)
{
    Py_XDECREF(self->exc_type);
    Py_XDECREF(self->exc_value);
    Py_XDECREF(self->exc_traceback);

    self->exc_type = NULL;
    self->exc_value = NULL;
    self->exc_traceback = NULL;
}

9966
static CYTHON_INLINE PyObject *__Pyx_Generator_SendEx(struct __pyx_Generator_object *self, PyObject *value)
9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984
{
    PyObject *retval;

    if (self->is_running) {
        PyErr_SetString(PyExc_ValueError,
                        "generator already executing");
        return NULL;
    }

    if (self->resume_label == 0) {
        if (value && value != Py_None) {
            PyErr_SetString(PyExc_TypeError,
                            "can't send non-None value to a "
                            "just-started generator");
            return NULL;
        }
    }

9985 9986 9987 9988 9989
    if (self->resume_label == -1) {
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }

9990 9991 9992 9993 9994 9995

    if (value)
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
    else
        __Pyx_Generator_ExceptionClear(self);

9996
    self->is_running = 1;
9997
    retval = self->body((PyObject *) self, value);
9998 9999
    self->is_running = 0;

10000 10001 10002 10003 10004
    if (retval)
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
    else
        __Pyx_Generator_ExceptionClear(self);

10005 10006 10007
    return retval;
}

10008
static PyObject *__Pyx_Generator_Next(PyObject *self)
10009
{
10010
    return __Pyx_Generator_SendEx((struct __pyx_Generator_object *) self, Py_None);
10011 10012
}

10013
static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value)
10014
{
10015
    return __Pyx_Generator_SendEx((struct __pyx_Generator_object *) self, value);
10016
}
Vitja Makarov's avatar
Vitja Makarov committed
10017

10018
static PyObject *__Pyx_Generator_Close(PyObject *self)
Vitja Makarov's avatar
Vitja Makarov committed
10019
{
10020
    struct __pyx_Generator_object *generator = (struct __pyx_Generator_object *) self;
Vitja Makarov's avatar
Vitja Makarov committed
10021
    PyObject *retval;
10022 10023 10024
#if PY_VERSION_HEX < 0x02050000
    PyErr_SetNone(PyExc_StopIteration);
#else
Vitja Makarov's avatar
Vitja Makarov committed
10025
    PyErr_SetNone(PyExc_GeneratorExit);
10026
#endif
10027
    retval = __Pyx_Generator_SendEx(generator, NULL);
Vitja Makarov's avatar
Vitja Makarov committed
10028 10029 10030 10031 10032 10033
    if (retval) {
        Py_DECREF(retval);
        PyErr_SetString(PyExc_RuntimeError,
                        "generator ignored GeneratorExit");
        return NULL;
    }
10034 10035 10036
#if PY_VERSION_HEX < 0x02050000
    if (PyErr_ExceptionMatches(PyExc_StopIteration))
#else
Vitja Makarov's avatar
Vitja Makarov committed
10037 10038
    if (PyErr_ExceptionMatches(PyExc_StopIteration)
        || PyErr_ExceptionMatches(PyExc_GeneratorExit))
10039
#endif
Vitja Makarov's avatar
Vitja Makarov committed
10040 10041 10042 10043 10044 10045 10046
    {
        PyErr_Clear();          /* ignore these errors */
        Py_INCREF(Py_None);
        return Py_None;
    }
    return NULL;
}
10047

10048
static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args, CYTHON_UNUSED PyObject *kwds)
10049
{
10050
    struct __pyx_Generator_object *generator = (struct __pyx_Generator_object *) self;
10051 10052 10053 10054
    PyObject *typ;
    PyObject *tb = NULL;
    PyObject *val = NULL;

10055
    if (!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))
10056
        return NULL;
10057
    __Pyx_Raise(typ, val, tb, NULL);
10058
    return __Pyx_Generator_SendEx(generator, NULL);
10059
}
Stefan Behnel's avatar
Stefan Behnel committed
10060 10061
""",
proto_block='utility_code_proto_before_types',
10062
requires=[Nodes.raise_utility_code, Nodes.swap_exception_utility_code],
Stefan Behnel's avatar
Stefan Behnel committed
10063
)