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

5 6 7 8 9 10 11 12 13 14
import cython
from cython import set
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)

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

17
from Errors import error, warning, warn_once, InternalError, CompileError
18
from Errors import hold_errors, release_errors, held_errors, report_error
19
from Code import UtilityCode
20
import StringEncoding
William Stein's avatar
William Stein committed
21
import Naming
Robert Bradshaw's avatar
Robert Bradshaw committed
22
import Nodes
William Stein's avatar
William Stein committed
23 24
from Nodes import Node
import PyrexTypes
25 26
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
     unspecified_type
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 73 74
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
    #  is_sequence_constructor  
    #               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.
William Stein's avatar
William Stein committed
80 81
    
    result_ctype = None
82
    type = None
83 84
    temp_code = None
    old_temp = None # error checker for multiple frees etc.
85
    use_managed_ref = True # can be set by optimisation transforms
William Stein's avatar
William Stein committed
86 87 88 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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

    #  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.
    #  
    #  The framework makes use of a number of abstract methods. 
    #  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
    #        the LHS of an assignment or argument of a del 
    #        statement. Similar responsibilities to analyse_types.
    #
140 141 142 143
    #      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
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
    #
    #      check_const
    #        - Check that this node and its subnodes form a
    #          legal constant expression. If so, do nothing,
    #          otherwise call not_const. 
    #
    #        The default implementation of check_const 
    #        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
    #        assumes that the expression is not a constant 
    #        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
172
    #        is provided which uses the following abstract methods:
William Stein's avatar
William Stein committed
173 174 175 176 177 178
    #
    #          generate_result_code
    #            - Generate any C statements necessary to calculate
    #              the result of this node from the results of its
    #              sub-expressions.
    #
179 180 181 182 183
    #          calculate_result_code
    #            - Should return a C code fragment evaluating to the 
    #              result. This is only called when the result is not 
    #              a temporary.
    #
William Stein's avatar
William Stein committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    #      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.
    #
    #
    
    is_sequence_constructor = 0
    is_attribute = 0
    
    saved_subexpr_nodes = None
    is_temp = 0
205
    is_target = 0
206
    is_starred = 0
William Stein's avatar
William Stein committed
207

208 209
    constant_result = constant_value_not_set

210 211 212 213
    try:
        _get_child_attrs = operator.attrgetter('subexprs')
    except AttributeError:
        # Python 2.3
214
        def __get_child_attrs(self):
215
            return self.subexprs
216
        _get_child_attrs = __get_child_attrs
217
    child_attrs = property(fget=_get_child_attrs)
218
        
William Stein's avatar
William Stein committed
219 220 221 222
    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
223
                (self.__class__.__name__, method_name))
William Stein's avatar
William Stein committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
                
    def is_lvalue(self):
        return 0
    
    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.
239 240 241
        nodes = []
        for name in self.subexprs:
            item = getattr(self, name)
Stefan Behnel's avatar
Stefan Behnel committed
242 243
            if item is not None:
                if type(item) is list:
244
                    nodes.extend(item)
Stefan Behnel's avatar
Stefan Behnel committed
245 246
                else:
                    nodes.append(item)
247
        return nodes
248 249
        
    def result(self):
250 251 252
        if self.is_temp:
            return self.temp_code
        else:
253
            return self.calculate_result_code()
William Stein's avatar
William Stein committed
254 255 256
    
    def result_as(self, type = None):
        #  Return the result code cast to the specified C type.
257
        return typecast(type, self.ctype(), self.result())
William Stein's avatar
William Stein committed
258 259 260 261 262 263 264 265 266
    
    def py_result(self):
        #  Return the result code cast to PyObject *.
        return self.result_as(py_object_type)
    
    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
267

268
    def get_constant_c_result_code(self):
269
        # Return the constant value of this node as a result code
270 271 272 273 274 275 276
        # 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.
277 278
        return None

279
    def calculate_constant_result(self):
280 281 282 283 284
        # 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.
285 286 287 288 289 290
        #
        # 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

291 292 293 294
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

295 296 297 298 299 300 301 302
    def compile_time_value(self, denv):
        #  Return value of compile-time expression, or report error.
        error(self.pos, "Invalid compile-time expression")
    
    def compile_time_value_error(self, e):
        error(self.pos, "Error in compile-time expression: %s: %s" % (
            e.__class__.__name__, e))
    
William Stein's avatar
William Stein committed
303 304 305 306 307 308 309 310 311 312 313 314 315
    # ------------- Declaration Analysis ----------------
    
    def analyse_target_declaration(self, env):
        error(self.pos, "Cannot assign to or delete this")
    
    # ------------- Expression Analysis ----------------
    
    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)
316
        return self.check_const()
William Stein's avatar
William Stein committed
317 318 319 320 321 322 323
    
    def analyse_expressions(self, env):
        #  Convenience routine performing both the Type
        #  Analysis and Temp Allocation phases for a whole 
        #  expression.
        self.analyse_types(env)
    
324
    def analyse_target_expression(self, env, rhs):
William Stein's avatar
William Stein committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        #  Convenience routine performing both the Type
        #  Analysis and Temp Allocation phases for the LHS of
        #  an assignment.
        self.analyse_target_types(env)
    
    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
    
    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
345 346
        return self.coerce_to_boolean(env).coerce_to_simple(env)

347 348
    # --------------- Type Inference -----------------
    
Robert Bradshaw's avatar
Robert Bradshaw committed
349
    def type_dependencies(self, env):
350 351 352 353
        # 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
354
        return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
355 356 357 358 359 360 361 362 363 364 365 366 367
    
    def infer_type(self, env):
        # Attempt to deduce the type of self. 
        # Differs from analyse_types as it avoids unnecessary 
        # 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")
    
William Stein's avatar
William Stein committed
368 369 370 371 372 373
    # --------------- Type Analysis ------------------
    
    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
374 375 376 377 378
        
    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
William Stein's avatar
William Stein committed
379 380 381 382 383 384 385 386 387 388 389
    
    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
    
    def analyse_types(self, env):
        self.not_implemented("analyse_types")
    
    def analyse_target_types(self, env):
        self.analyse_types(env)
390

391
    def nogil_check(self, env):
392 393 394 395
        # By default, any expression based on Python objects is
        # prevented in nogil environments.  Subtypes must override
        # this if they can work without the GIL.
        if self.type.is_pyobject:
396
            self.gil_error()
397

398 399 400 401
    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
402 403
    def check_const(self):
        self.not_const()
404
        return False
William Stein's avatar
William Stein committed
405 406 407 408 409 410
    
    def not_const(self):
        error(self.pos, "Not allowed in a constant expression")
    
    def check_const_addr(self):
        self.addr_not_const()
411
        return False
William Stein's avatar
William Stein committed
412 413 414
    
    def addr_not_const(self):
        error(self.pos, "Address is not constant")
415

William Stein's avatar
William Stein committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
    # ----------------- Result Allocation -----------------
    
    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
            
    def target_code(self):
        #  Return code fragment for use as LHS of a C assignment.
        return self.calculate_result_code()
    
    def calculate_result_code(self):
        self.not_implemented("calculate_result_code")
    
Robert Bradshaw's avatar
Robert Bradshaw committed
432 433 434
#    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
435

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

    def release_temp_result(self, code):
        if not self.temp_code:
            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
460 461 462 463 464 465
    # ---------------- Code Generation -----------------
    
    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():
466
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
467 468
    
    def generate_evaluation_code(self, code):
469
        code.mark_pos(self.pos)
470
        
William Stein's avatar
William Stein committed
471 472 473 474
        #  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)
475 476 477 478

        if self.is_temp:
            self.allocate_temp_result(code)

William Stein's avatar
William Stein committed
479 480
        self.generate_result_code(code)
        if self.is_temp:
481 482
            # 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
483
            self.generate_subexpr_disposal_code(code)
484
            self.free_subexpr_temps(code)
485

William Stein's avatar
William Stein committed
486 487 488 489 490 491 492
    def generate_subexpr_evaluation_code(self, code):
        for node in self.subexpr_nodes():
            node.generate_evaluation_code(code)
    
    def generate_result_code(self, code):
        self.not_implemented("generate_result_code")
    
493 494 495 496
    def generate_disposal_code(self, code):
        if self.is_temp:
            if self.type.is_pyobject:
                code.put_decref_clear(self.result(), self.ctype())
William Stein's avatar
William Stein committed
497
        else:
498
            # Already done if self.is_temp
499
            self.generate_subexpr_disposal_code(code)
500

William Stein's avatar
William Stein committed
501 502 503 504 505 506 507 508 509
    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)
    
    def generate_post_assignment_code(self, code):
        if self.is_temp:
            if self.type.is_pyobject:
510
                code.putln("%s = 0;" % self.result())
William Stein's avatar
William Stein committed
511 512
        else:
            self.generate_subexpr_disposal_code(code)
513

William Stein's avatar
William Stein committed
514 515 516 517 518 519 520 521 522 523 524
    def generate_assignment_code(self, rhs, code):
        #  Stub method for nodes which are not legal as
        #  the LHS of an assignment. An error will have 
        #  been reported earlier.
        pass
    
    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
525 526

    def free_temps(self, code):
527 528 529 530
        if self.is_temp:
            if not self.type.is_void:
                self.release_temp_result(code)
        else:
531
            self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
532
    
533 534 535 536
    def free_subexpr_temps(self, code):
        for sub in self.subexpr_nodes():
            sub.free_temps(code)

537 538 539
    def generate_function_definitions(self, env, code):
        pass

540 541 542 543 544 545
    # ---------------- Annotation ---------------------
    
    def annotate(self, code):
        for node in self.subexpr_nodes():
            node.annotate(code)
    
William Stein's avatar
William Stein committed
546 547 548 549 550 551 552 553 554 555
    # ----------------- Coercion ----------------------
    
    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.
556 557 558 559 560 561 562 563
        #
        #   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
564 565 566 567
        src = self
        src_type = self.type
        src_is_py_type = src_type.is_pyobject
        dst_is_py_type = dst_type.is_pyobject
568

569 570 571
        if self.check_for_coercion_error(dst_type):
            return self

572 573 574
        if dst_type.is_reference:
            dst_type = dst_type.ref_base_type
        
William Stein's avatar
William Stein committed
575 576
        if dst_type.is_pyobject:
            if not src.type.is_pyobject:
577 578 579 580
                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
581
            if not src.type.subtype_of(dst_type):
582 583
                if not isinstance(src, NoneNode):
                    src = PyTypeTestNode(src, dst_type, env)
William Stein's avatar
William Stein committed
584 585
        elif src.type.is_pyobject:
            src = CoerceFromPyTypeNode(dst_type, src, env)
586
        elif (dst_type.is_complex 
587 588
              and src_type != dst_type
              and dst_type.assignable_from(src_type)):
589
            src = CoerceToComplexNode(src, dst_type, env)
William Stein's avatar
William Stein committed
590
        else: # neither src nor dst are py types
591
            # Added the string comparison, since for c types that
592
            # is enough, but Cython gets confused when the types are
593
            # in different pxi files.
594
            if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
595
                self.fail_assignment(dst_type)
William Stein's avatar
William Stein committed
596 597
        return src

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    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
613 614 615 616 617 618
    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.
619 620 621 622 623 624 625

        # 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
626 627 628 629
        type = self.type
        if type.is_pyobject or type.is_ptr or type.is_float:
            return CoerceToBooleanNode(self, env)
        else:
630
            if not (type.is_int or type.is_enum or type.is_error):
William Stein's avatar
William Stein committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
                error(self.pos, 
                    "Type '%s' not acceptable as a boolean" % type)
            return self
    
    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)
    
    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)
    
    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)
    
    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()
662 663

    def may_be_none(self):
664 665 666 667 668
        if not self.type.is_pyobject:
            return False
        if self.constant_result not in (not_a_constant, constant_value_not_set):
            return self.constant_result is not None
        return True
669

670
    def as_cython_attribute(self):
671
        return None
William Stein's avatar
William Stein committed
672

673
    def as_none_safe_node(self, message, error="PyExc_TypeError"):
674 675 676 677 678 679 680 681
        # 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():
            return NoneCheckNode(self, error, message)
        else:
            return self


William Stein's avatar
William Stein committed
682
class AtomicExprNode(ExprNode):
683 684 685 686 687 688
    #  Abstract base class for expression nodes which have
    #  no sub-expressions.
    
    subexprs = []

    # Override to optimize -- we know we have no children
689 690 691 692
    def generate_subexpr_evaluation_code(self, code):
        pass
    def generate_subexpr_disposal_code(self, code):
        pass
693

694
class PyConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
695 696
    #  Abstract base class for constant Python values.
    
697
    is_literal = 1
698
    type = py_object_type
699
    
William Stein's avatar
William Stein committed
700 701
    def is_simple(self):
        return 1
702 703 704 705

    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
706
    def analyse_types(self, env):
707
        pass
William Stein's avatar
William Stein committed
708 709 710 711 712 713 714 715 716 717 718 719
    
    def calculate_result_code(self):
        return self.value

    def generate_result_code(self, code):
        pass


class NoneNode(PyConstNode):
    #  The constant value None
    
    value = "Py_None"
720 721

    constant_result = None
722 723
    
    nogil_check = None
724

725 726
    def compile_time_value(self, denv):
        return None
727 728 729 730 731

    def may_be_none(self):
        return True


William Stein's avatar
William Stein committed
732 733 734 735 736
class EllipsisNode(PyConstNode):
    #  '...' in a subscript list.
    
    value = "Py_Ellipsis"

737 738
    constant_result = Ellipsis

739 740 741
    def compile_time_value(self, denv):
        return Ellipsis

William Stein's avatar
William Stein committed
742

743
class ConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
744 745 746 747 748
    # Abstract base type for literal constant nodes.
    #
    # value     string      C code fragment
    
    is_literal = 1
749
    nogil_check = None
750

William Stein's avatar
William Stein committed
751 752
    def is_simple(self):
        return 1
753 754 755 756

    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
757 758 759 760
    def analyse_types(self, env):
        pass # Types are held in class variables
    
    def check_const(self):
761
        return True
William Stein's avatar
William Stein committed
762
    
763
    def get_constant_c_result_code(self):
764 765
        return self.calculate_result_code()

William Stein's avatar
William Stein committed
766 767 768 769 770 771 772
    def calculate_result_code(self):
        return str(self.value)

    def generate_result_code(self, code):
        pass


773 774 775
class BoolNode(ConstNode):
    type = PyrexTypes.c_bint_type
    #  The constant value True or False
776 777 778 779

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

780 781 782 783
    def compile_time_value(self, denv):
        return self.value
    
    def calculate_result_code(self):
784
        return str(int(self.value))
785

786

William Stein's avatar
William Stein committed
787 788
class NullNode(ConstNode):
    type = PyrexTypes.c_null_ptr_type
789
    value = "NULL"
790
    constant_result = 0
William Stein's avatar
William Stein committed
791

792
    def get_constant_c_result_code(self):
793 794
        return self.value

William Stein's avatar
William Stein committed
795 796 797

class CharNode(ConstNode):
    type = PyrexTypes.c_char_type
798 799 800

    def calculate_constant_result(self):
        self.constant_result = ord(self.value)
William Stein's avatar
William Stein committed
801
    
802
    def compile_time_value(self, denv):
803
        return ord(self.value)
804
    
William Stein's avatar
William Stein committed
805
    def calculate_result_code(self):
806
        return "'%s'" % StringEncoding.escape_char(self.value)
William Stein's avatar
William Stein committed
807 808 809


class IntNode(ConstNode):
810 811 812

    # unsigned     "" or "U"
    # longness     "" or "L" or "LL"
813
    # is_c_literal   True/False/None   creator considers this a C integer literal
814 815 816

    unsigned = ""
    longness = ""
817
    is_c_literal = None # unknown
818 819 820

    def __init__(self, pos, **kwds):
        ExprNode.__init__(self, pos, **kwds)
Robert Bradshaw's avatar
Robert Bradshaw committed
821
        if 'type' not in kwds:
822 823 824 825 826 827 828 829
            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
830 831 832 833
        # 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 \
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
               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
850

851
    def coerce_to(self, dst_type, env):
852
        if self.type is dst_type:
853
            return self
854
        elif dst_type.is_float:
855 856 857 858 859 860 861
            if self.constant_result is not not_a_constant:
                float_value = float(self.constant_result)
                return FloatNode(self.pos, value=repr(float_value), type=dst_type,
                                 constant_result=float_value)
            else:
                return FloatNode(self.pos, value=self.value, type=dst_type,
                                 constant_result=not_a_constant)
862
        if dst_type.is_numeric and not dst_type.is_complex:
863
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
864 865
                           type = dst_type, is_c_literal = True,
                           unsigned=self.unsigned, longness=self.longness)
866
            return node
867 868
        elif dst_type.is_pyobject:
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
869 870
                           type = PyrexTypes.py_object_type, is_c_literal = False,
                           unsigned=self.unsigned, longness=self.longness)
871
        else:
872 873
            # FIXME: not setting the type here to keep it working with
            # complex numbers. Should they be special cased?
874 875
            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
                           unsigned=self.unsigned, longness=self.longness)
876 877 878
        # 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.
879 880
        return ConstNode.coerce_to(node, dst_type, env)

881
    def coerce_to_boolean(self, env):
882 883 884 885
        return IntNode(
            self.pos, value=self.value,
            type = PyrexTypes.c_bint_type,
            unsigned=self.unsigned, longness=self.longness)
886

887
    def generate_evaluation_code(self, code):
888
        if self.type.is_pyobject:
889
            # pre-allocate a Python version of the number
890 891
            plain_integer_string = self.value_as_c_integer_string(plain_digits=True)
            self.result_code = code.get_py_num(plain_integer_string, self.longness)
892
        else:
893
            self.result_code = self.get_constant_c_result_code()
894
    
895
    def get_constant_c_result_code(self):
896 897 898
        return self.value_as_c_integer_string() + self.unsigned + self.longness

    def value_as_c_integer_string(self, plain_digits=False):
899 900 901 902
        value = self.value
        if isinstance(value, basestring) and len(value) > 2:
            # must convert C-incompatible Py3 oct/bin notations
            if value[1] in 'oO':
903 904 905 906
                if plain_digits:
                    value = int(value[2:], 8)
                else:
                    value = value[0] + value[2:] # '0o123' => '0123'
907 908
            elif value[1] in 'bB':
                value = int(value[2:], 2)
909 910 911
            elif plain_digits and value[1] in 'xX':
                value = int(value[2:], 16)
        return str(value)
912 913 914

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

916
    def calculate_constant_result(self):
917
        self.constant_result = Utils.str_to_number(self.value)
918

919
    def compile_time_value(self, denv):
920
        return Utils.str_to_number(self.value)
921 922


William Stein's avatar
William Stein committed
923 924 925
class FloatNode(ConstNode):
    type = PyrexTypes.c_double_type

926
    def calculate_constant_result(self):
927
        self.constant_result = float(self.value)
928

929 930
    def compile_time_value(self, denv):
        return float(self.value)
Stefan Behnel's avatar
Stefan Behnel committed
931 932
    
    def calculate_result_code(self):
933 934 935 936
        strval = self.value
        assert isinstance(strval, (str, unicode))
        cmpval = repr(float(strval))
        if cmpval == 'nan':
937
            return "(Py_HUGE_VAL * 0)"
938
        elif cmpval == 'inf':
939
            return "Py_HUGE_VAL"
940
        elif cmpval == '-inf':
941
            return "(-Py_HUGE_VAL)"
Stefan Behnel's avatar
Stefan Behnel committed
942 943
        else:
            return strval
944

William Stein's avatar
William Stein committed
945

946
class BytesNode(ConstNode):
947 948 949 950
    # A char* or bytes literal
    #
    # value      BytesLiteral

William Stein's avatar
William Stein committed
951
    type = PyrexTypes.c_char_ptr_type
952 953

    def compile_time_value(self, denv):
954
        return self.value
955

956
    def analyse_as_type(self, env):
957 958 959
        type = PyrexTypes.parse_basic_type(self.value)
        if type is not None:    
            return type
960 961 962 963 964 965 966
        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
967

968 969 970
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

971 972 973 974 975
    def coerce_to_boolean(self, env):
        # This is special because we start off as a C char*.  Testing
        # that for truth directly would yield the wrong result.
        return BoolNode(self.pos, value=bool(self.value))

William Stein's avatar
William Stein committed
976
    def coerce_to(self, dst_type, env):
977
        if dst_type.is_int:
978
            if not self.can_coerce_to_char_literal():
979 980 981 982
                error(self.pos, "Only single-character string literals can be coerced into ints.")
                return self
            if dst_type is PyrexTypes.c_py_unicode_type:
                error(self.pos, "Bytes literals cannot coerce to Py_UNICODE, use a unicode literal instead.")
983
                return self
984 985
            return CharNode(self.pos, value=self.value)

986 987 988 989 990 991 992 993
        node = BytesNode(self.pos, value=self.value)
        if dst_type == PyrexTypes.c_char_ptr_type:
            node.type = PyrexTypes.c_char_ptr_type
            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)

994 995
        if not self.type.is_pyobject:
            if dst_type in (py_object_type, Builtin.bytes_type):
996
                node.type = Builtin.bytes_type
997
            elif dst_type.is_pyobject:
998 999 1000 1001
                self.fail_assignment(dst_type)
                return self
        elif dst_type.is_pyobject and dst_type is not py_object_type:
            self.check_for_coercion_error(dst_type, fail=True)
1002
            return node
1003

William Stein's avatar
William Stein committed
1004 1005 1006 1007 1008 1009
        # 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)

    def as_py_string_node(self, env):
1010
        # Return a new BytesNode with the same value as this node
William Stein's avatar
William Stein committed
1011
        # but whose type is a Python type instead of a C type.
1012
        return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
1013 1014

    def generate_evaluation_code(self, code):
William Stein's avatar
William Stein committed
1015
        if self.type.is_pyobject:
1016
            self.result_code = code.get_py_string_const(self.value)
William Stein's avatar
William Stein committed
1017
        else:
1018
            self.result_code = code.get_string_const(self.value)
1019

1020
    def get_constant_c_result_code(self):
1021
        return None # FIXME
1022 1023 1024
    
    def calculate_result_code(self):
        return self.result_code
William Stein's avatar
William Stein committed
1025 1026


1027
class UnicodeNode(PyConstNode):
1028 1029
    # A Python unicode object
    #
1030 1031
    # value        EncodedString
    # bytes_value  BytesLiteral    the literal parsed as bytes string ('-3' unicode literals only)
Robert Bradshaw's avatar
Robert Bradshaw committed
1032

1033
    bytes_value = None
1034
    type = unicode_type
1035

1036
    def coerce_to(self, dst_type, env):
1037 1038
        if dst_type is self.type:
            pass
1039 1040 1041 1042 1043 1044
        elif dst_type is PyrexTypes.c_py_unicode_type:
            if not self.can_coerce_to_char_literal():
                error(self.pos, "Only single-character Unicode string literals can be coerced into Py_UNICODE.")
                return self
            int_value = ord(self.value)
            return IntNode(self.pos, value=int_value, constant_result=int_value)
1045
        elif not dst_type.is_pyobject:
1046 1047 1048
            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)
1049
            error(self.pos, "Unicode literals do not support coercion to C types other than Py_UNICODE.")
1050 1051 1052 1053
        elif dst_type is not py_object_type:
            if not self.check_for_coercion_error(dst_type):
                self.fail_assignment(dst_type)
        return self
1054

1055 1056 1057
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
    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

1075
    def generate_evaluation_code(self, code):
1076
        self.result_code = code.get_py_string_const(self.value)
1077 1078 1079

    def calculate_result_code(self):
        return self.result_code
1080 1081 1082
        
    def compile_time_value(self, env):
        return self.value
1083 1084


1085 1086 1087 1088
class StringNode(PyConstNode):
    # A Python str object, i.e. a byte string in Python 2.x and a
    # unicode string in Python 3.x
    #
1089 1090
    # value          BytesLiteral (or EncodedString with ASCII content)
    # unicode_value  EncodedString or None
1091
    # is_identifier  boolean
1092

1093
    type = str_type
1094
    is_identifier = None
1095
    unicode_value = None
1096

1097
    def coerce_to(self, dst_type, env):
1098
        if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
1099 1100 1101 1102 1103
#            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)
1104
            self.check_for_coercion_error(dst_type, fail=True)
1105 1106

        # this will be a unicode string in Py3, so make sure we can decode it
1107
        if self.value.encoding and isinstance(self.value, StringEncoding.BytesLiteral):
1108
            try:
1109 1110 1111 1112 1113
                self.value.decode(self.value.encoding)
            except UnicodeDecodeError:
                error(self.pos, ("Decoding unprefixed string literal from '%s' failed. Consider using"
                                 "a byte string or unicode string explicitly, "
                                 "or adjust the source code encoding.") % self.value.encoding)
1114

1115
        return self
1116

1117 1118
    def can_coerce_to_char_literal(self):
        return not self.is_identifier and len(self.value) == 1
1119

1120
    def generate_evaluation_code(self, code):
1121 1122
        self.result_code = code.get_py_string_const(
            self.value, identifier=self.is_identifier, is_str=True)
1123

1124
    def get_constant_c_result_code(self):
1125 1126
        return None

1127
    def calculate_result_code(self):
1128
        return self.result_code
1129 1130 1131
        
    def compile_time_value(self, env):
        return self.value
1132 1133


1134 1135 1136 1137
class IdentifierStringNode(StringNode):
    # A special str value that represents an identifier (bytes in Py2,
    # unicode in Py3).
    is_identifier = True
1138 1139


1140
class LongNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1141 1142 1143
    #  Python long integer literal
    #
    #  value   string
1144

1145 1146
    type = py_object_type

1147
    def calculate_constant_result(self):
1148
        self.constant_result = Utils.str_to_number(self.value)
William Stein's avatar
William Stein committed
1149
    
1150
    def compile_time_value(self, denv):
1151
        return Utils.str_to_number(self.value)
1152
    
William Stein's avatar
William Stein committed
1153 1154
    def analyse_types(self, env):
        self.is_temp = 1
1155

1156 1157 1158
    def may_be_none(self):
        return False

1159 1160
    gil_message = "Constructing Python long int"

1161
    def generate_result_code(self, code):
William Stein's avatar
William Stein committed
1162
        code.putln(
1163
            '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1164
                self.result(),
William Stein's avatar
William Stein committed
1165
                self.value,
1166
                code.error_goto_if_null(self.result(), self.pos)))
1167
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1168 1169


1170
class ImagNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1171 1172 1173
    #  Imaginary number literal
    #
    #  value   float    imaginary part
1174 1175
    
    type = PyrexTypes.c_double_complex_type
1176 1177 1178

    def calculate_constant_result(self):
        self.constant_result = complex(0.0, self.value)
William Stein's avatar
William Stein committed
1179
    
1180 1181 1182
    def compile_time_value(self, denv):
        return complex(0.0, self.value)
    
William Stein's avatar
William Stein committed
1183
    def analyse_types(self, env):
1184 1185
        self.type.create_declaration_utility_code(env)

1186 1187 1188
    def may_be_none(self):
        return False

1189
    def coerce_to(self, dst_type, env):
1190 1191 1192
        if self.type is dst_type:
            return self
        node = ImagNode(self.pos, value=self.value)
1193
        if dst_type.is_pyobject:
1194 1195
            node.is_temp = 1
            node.type = PyrexTypes.py_object_type
1196 1197 1198
        # 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.
1199
        return AtomicExprNode.coerce_to(node, dst_type, env)
1200 1201 1202

    gil_message = "Constructing complex number"

1203 1204 1205 1206 1207 1208
    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))

1209
    def generate_result_code(self, code):
1210 1211 1212 1213 1214 1215 1216
        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())
1217
        
William Stein's avatar
William Stein committed
1218

Danilo Freitas's avatar
Danilo Freitas committed
1219
class NewExprNode(AtomicExprNode):
1220 1221 1222

    # C++ new statement
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1223 1224 1225
    # cppclass              node                 c++ class to create
    
    type = None
Danilo Freitas's avatar
Danilo Freitas committed
1226
    
1227
    def infer_type(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1228 1229
        type = self.cppclass.analyse_as_type(env)
        if type is None or not type.is_cpp_class:
Danilo Freitas's avatar
Danilo Freitas committed
1230
            error(self.pos, "new operator can only be applied to a C++ class")
Robert Bradshaw's avatar
Robert Bradshaw committed
1231
            self.type = error_type
Danilo Freitas's avatar
Danilo Freitas committed
1232
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
1233
        self.cpp_check(env)
1234
        constructor = type.scope.lookup(u'<init>')
Danilo Freitas's avatar
Danilo Freitas committed
1235
        if constructor is None:
1236 1237
            return_type = PyrexTypes.CFuncType(type, [])
            return_type = PyrexTypes.CPtrType(return_type)
1238 1239
            type.scope.declare_cfunction(u'<init>', return_type, self.pos)
            constructor = type.scope.lookup(u'<init>')
1240
        self.class_type = type
DaniloFreitas's avatar
DaniloFreitas committed
1241
        self.entry = constructor
Robert Bradshaw's avatar
Robert Bradshaw committed
1242
        self.type = constructor.type
1243 1244 1245
        return self.type
    
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1246 1247
        if self.type is None:
            self.infer_type(env)
1248 1249 1250 1251

    def may_be_none(self):
        return False

Danilo Freitas's avatar
Danilo Freitas committed
1252 1253
    def generate_result_code(self, code):
        pass
Danilo Freitas's avatar
Danilo Freitas committed
1254
   
Danilo Freitas's avatar
Danilo Freitas committed
1255
    def calculate_result_code(self):
1256
        return "new " + self.class_type.declaration_code("")
Danilo Freitas's avatar
Danilo Freitas committed
1257

William Stein's avatar
William Stein committed
1258

1259
class NameNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1260 1261 1262 1263
    #  Reference to a local or global variable name.
    #
    #  name            string    Python name of the variable
    #  entry           Entry     Symbol table entry
1264
    #  type_entry      Entry     For extension type names, the original type entry
William Stein's avatar
William Stein committed
1265
    
1266 1267
    is_name = True
    is_cython_module = False
Robert Bradshaw's avatar
Robert Bradshaw committed
1268
    cython_attribute = None
1269
    lhs_of_first_assignment = False
1270
    is_used_as_rvalue = 0
1271
    entry = None
1272
    type_entry = None
1273 1274 1275 1276 1277

    def create_analysed_rvalue(pos, env, entry):
        node = NameNode(pos)
        node.analyse_types(env, entry=entry)
        return node
Robert Bradshaw's avatar
Robert Bradshaw committed
1278
        
1279
    def as_cython_attribute(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
1280
        return self.cython_attribute
1281 1282
    
    create_analysed_rvalue = staticmethod(create_analysed_rvalue)
William Stein's avatar
William Stein committed
1283
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
    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 ()
    
    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
1297 1298 1299
        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
1300
            # is used for the pointer to the type they represent.
Robert Bradshaw's avatar
Robert Bradshaw committed
1301
            return type_type
Robert Bradshaw's avatar
Robert Bradshaw committed
1302 1303
        else:
            return self.entry.type
1304
    
1305 1306 1307 1308
    def compile_time_value(self, denv):
        try:
            return denv.lookup(self.name)
        except KeyError:
Stefan Behnel's avatar
Stefan Behnel committed
1309
            error(self.pos, "Compile-time name '%s' not defined" % self.name)
1310 1311 1312 1313 1314

    def get_constant_c_result_code(self):
        if not self.entry or self.entry.type.is_pyobject:
            return None
        return self.entry.cname
1315 1316 1317 1318 1319 1320 1321 1322
    
    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
1323
            if entry and entry.is_cfunction:
1324 1325
                var_entry = entry.as_variable
                if var_entry:
1326 1327
                    if var_entry.is_builtin and Options.cache_builtins:
                        var_entry = env.declare_builtin(var_entry.name, self.pos)
1328 1329 1330 1331
                    node = NameNode(self.pos, name = self.name)
                    node.entry = var_entry
                    node.analyse_rvalue_entry(env)
                    return node
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1332
        return super(NameNode, self).coerce_to(dst_type, env)
1333
    
William Stein's avatar
William Stein committed
1334 1335 1336
    def analyse_as_module(self, env):
        # Try to interpret this as a reference to a cimported module.
        # Returns the module scope, or None.
1337 1338 1339
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1340 1341 1342
        if entry and entry.as_module:
            return entry.as_module
        return None
1343 1344
        
    def analyse_as_type(self, env):
1345 1346 1347 1348
        if self.cython_attribute:
            type = PyrexTypes.parse_basic_type(self.cython_attribute)
        else:
            type = PyrexTypes.parse_basic_type(self.name)
1349 1350
        if type:
            return type
1351 1352 1353 1354 1355 1356 1357
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
        if entry and entry.is_type:
            return entry.type
        else:
            return None
William Stein's avatar
William Stein committed
1358 1359 1360 1361
    
    def analyse_as_extension_type(self, env):
        # Try to interpret this as a reference to an extension type.
        # Returns the extension type, or None.
1362 1363 1364
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1365
        if entry and entry.is_type and entry.type.is_extension_type:
1366 1367 1368
            return entry.type
        else:
            return None
William Stein's avatar
William Stein committed
1369 1370
    
    def analyse_target_declaration(self, env):
1371 1372
        if not self.entry:
            self.entry = env.lookup_here(self.name)
William Stein's avatar
William Stein committed
1373
        if not self.entry:
1374 1375
            if env.directives['warn.undeclared']:
                warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1376
            if env.directives['infer_types'] != False:
1377 1378 1379 1380
                type = unspecified_type
            else:
                type = py_object_type
            self.entry = env.declare_var(self.name, type, self.pos)
Craig Citro's avatar
Craig Citro committed
1381
        env.control_flow.set_state(self.pos, (self.name, 'initialized'), True)
Robert Bradshaw's avatar
Robert Bradshaw committed
1382
        env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1383 1384
        if self.entry.is_declared_generic:
            self.result_ctype = py_object_type
William Stein's avatar
William Stein committed
1385
    
1386 1387 1388
    def analyse_types(self, env):
        if self.entry is None:
            self.entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1389 1390
        if not self.entry:
            self.entry = env.declare_builtin(self.name, self.pos)
1391 1392 1393
        if not self.entry:
            self.type = PyrexTypes.error_type
            return
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1394 1395 1396 1397 1398 1399 1400 1401
        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)
1402 1403 1404
        self.analyse_rvalue_entry(env)
        
    def analyse_target_types(self, env):
William Stein's avatar
William Stein committed
1405
        self.analyse_entry(env)
1406 1407 1408 1409
        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
1410
        self.entry.used = 1
1411
        if self.entry.type.is_buffer:
1412 1413 1414
            import Buffer
            Buffer.used_buffer_aux_vars(self.entry)
                
1415 1416 1417 1418
    def analyse_rvalue_entry(self, env):
        #print "NameNode.analyse_rvalue_entry:", self.name ###
        #print "Entry:", self.entry.__dict__ ###
        self.analyse_entry(env)
1419 1420
        entry = self.entry
        if entry.is_declared_generic:
William Stein's avatar
William Stein committed
1421
            self.result_ctype = py_object_type
1422
        if entry.is_pyglobal or entry.is_builtin:
1423 1424 1425 1426
            if Options.cache_builtins and entry.is_builtin:
                self.is_temp = 0
            else:
                self.is_temp = 1
1427
                env.use_utility_code(get_name_interned_utility_code)
1428 1429
            self.is_used_as_rvalue = 1

1430
    def nogil_check(self, env):
1431 1432 1433 1434
        if self.is_used_as_rvalue:
            entry = self.entry
            if entry.is_builtin:
                # if not Options.cache_builtins: # cached builtins are ok
1435
                self.gil_error()
1436
            elif entry.is_pyglobal:
1437
                self.gil_error()
1438 1439 1440

    gil_message = "Accessing Python global or builtin"

1441 1442
    def analyse_entry(self, env):
        #print "NameNode.analyse_entry:", self.name ###
William Stein's avatar
William Stein committed
1443
        self.check_identifier_kind()
1444 1445 1446 1447
        entry = self.entry
        type = entry.type
        self.type = type

William Stein's avatar
William Stein committed
1448
    def check_identifier_kind(self):
1449 1450 1451
        # 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
1452
        entry = self.entry
1453 1454
        if entry.is_type and entry.type.is_extension_type:
            self.type_entry = entry
William Stein's avatar
William Stein committed
1455
        if not (entry.is_const or entry.is_variable 
Danilo Freitas's avatar
Danilo Freitas committed
1456 1457
            or entry.is_builtin or entry.is_cfunction
            or entry.is_cpp_class):
William Stein's avatar
William Stein committed
1458 1459 1460 1461
                if self.entry.as_variable:
                    self.entry = self.entry.as_variable
                else:
                    error(self.pos, 
1462 1463
                          "'%s' is not a constant, variable or function identifier" % self.name)

William Stein's avatar
William Stein committed
1464 1465 1466 1467 1468 1469 1470 1471 1472
    def is_simple(self):
        #  If it's not a C variable, it'll be in a temp.
        return 1
    
    def calculate_target_results(self, env):
        pass
    
    def check_const(self):
        entry = self.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
1473
        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
1474
            self.not_const()
1475 1476
            return False
        return True
William Stein's avatar
William Stein committed
1477 1478 1479
    
    def check_const_addr(self):
        entry = self.entry
1480
        if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
William Stein's avatar
William Stein committed
1481
            self.addr_not_const()
1482 1483
            return False
        return True
William Stein's avatar
William Stein committed
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493

    def is_lvalue(self):
        return self.entry.is_variable and \
            not self.entry.type.is_array and \
            not self.entry.is_readonly
    
    def is_ephemeral(self):
        #  Name nodes are never ephemeral, even if the
        #  result is in a temporary.
        return 0
Stefan Behnel's avatar
Stefan Behnel committed
1494
    
William Stein's avatar
William Stein committed
1495
    def calculate_result_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
1496 1497
        entry = self.entry
        if not entry:
William Stein's avatar
William Stein committed
1498
            return "<error>" # There was an error earlier
Stefan Behnel's avatar
Stefan Behnel committed
1499
        return entry.cname
William Stein's avatar
William Stein committed
1500 1501
    
    def generate_result_code(self, code):
1502
        assert hasattr(self, 'entry')
William Stein's avatar
William Stein committed
1503 1504 1505
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1506 1507
        if entry.is_builtin and Options.cache_builtins:
            return # Lookup already cached
Stefan Behnel's avatar
Stefan Behnel committed
1508
        elif entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1509 1510 1511 1512 1513 1514 1515
            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
            code.putln(
Stefan Behnel's avatar
Stefan Behnel committed
1516
                '%s = PyObject_GetItem(%s, %s); %s' % (
Vitja Makarov's avatar
Vitja Makarov committed
1517 1518 1519 1520 1521 1522
                self.result(),
                namespace,
                interned_cname,
                code.error_goto_if_null(self.result(), self.pos)))
            code.put_gotref(self.py_result())
            
1523
        elif entry.is_pyglobal or entry.is_builtin:
1524 1525
            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
1526 1527 1528
            if entry.is_builtin:
                namespace = Naming.builtins_cname
            else: # entry.is_pyglobal
1529
                namespace = entry.scope.namespace_cname
1530
            code.globalstate.use_utility_code(get_name_interned_utility_code)
1531 1532
            code.putln(
                '%s = __Pyx_GetName(%s, %s); %s' % (
1533
                self.result(),
1534
                namespace, 
1535
                interned_cname,
1536
                code.error_goto_if_null(self.result(), self.pos)))
1537
            code.put_gotref(self.py_result())
1538
            
1539 1540
        elif entry.is_local and False:
            # control flow not good enough yet
Craig Citro's avatar
Craig Citro committed
1541
            assigned = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
1542 1543
            if assigned is False:
                error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1544
            elif not Options.init_local_none and assigned is None:
1545 1546
                code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
                           (entry.cname, entry.name, code.error_goto(self.pos)))
Craig Citro's avatar
Craig Citro committed
1547
                entry.scope.control_flow.set_state(self.pos, (entry.name, 'initialized'), True)
William Stein's avatar
William Stein committed
1548 1549

    def generate_assignment_code(self, rhs, code):
1550
        #print "NameNode.generate_assignment_code:", self.name ###
William Stein's avatar
William Stein committed
1551 1552 1553
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1554 1555 1556 1557

        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")
1558
        
1559 1560
        # 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
1561
        if entry.is_pyglobal:
1562 1563
            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
            interned_cname = code.intern_identifier(self.entry.name)
1564
            namespace = self.entry.scope.namespace_cname
1565
            if entry.is_member:
Stefan Behnel's avatar
Stefan Behnel committed
1566
                # if the entry is a member we have to cheat: SetAttr does not work
1567
                # on types, so we create a descriptor which is then added to tp_dict
1568 1569 1570
                code.put_error_if_neg(self.pos,
                    'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
                        namespace,
1571
                        interned_cname,
1572
                        rhs.py_result()))
1573 1574
                rhs.generate_disposal_code(code)
                rhs.free_temps(code)
1575
                # in Py2.6+, we need to invalidate the method cache
1576
                code.putln("PyType_Modified(%s);" %
Vitja Makarov's avatar
Vitja Makarov committed
1577
                            entry.scope.parent_type.typeptr_cname)
Stefan Behnel's avatar
Stefan Behnel committed
1578
            elif entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1579
                code.put_error_if_neg(self.pos,
Stefan Behnel's avatar
Stefan Behnel committed
1580
                    'PyObject_SetItem(%s, %s, %s)' % (
Vitja Makarov's avatar
Vitja Makarov committed
1581 1582 1583 1584 1585 1586
                        namespace,
                        interned_cname,
                        rhs.py_result()))
                rhs.generate_disposal_code(code)
                rhs.free_temps(code)
            else:
1587 1588 1589
                code.put_error_if_neg(self.pos,
                    'PyObject_SetAttr(%s, %s, %s)' % (
                        namespace,
1590
                        interned_cname,
1591
                        rhs.py_result()))
1592
                if debug_disposal_code:
Stefan Behnel's avatar
Stefan Behnel committed
1593 1594
                    print("NameNode.generate_assignment_code:")
                    print("...generating disposal code for %s" % rhs)
1595
                rhs.generate_disposal_code(code)
1596
                rhs.free_temps(code)
William Stein's avatar
William Stein committed
1597
        else:
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
            if self.type.is_buffer:
                # 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)

1608
            if self.type.is_pyobject:
William Stein's avatar
William Stein committed
1609 1610 1611 1612
                #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() ###
1613 1614 1615 1616
                if self.use_managed_ref:
                    rhs.make_owned_reference(code)
                    if entry.is_cglobal:
                        code.put_gotref(self.py_result())
1617 1618 1619 1620 1621 1622 1623 1624
                    if not self.lhs_of_first_assignment:
                        if entry.is_local and not Options.init_local_none:
                            initialized = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
                            if initialized is True:
                                code.put_decref(self.result(), self.ctype())
                            elif initialized is None:
                                code.put_xdecref(self.result(), self.ctype())
                        else:
1625
                            code.put_decref(self.result(), self.ctype())
1626
                    if entry.is_cglobal:
1627
                        code.put_giveref(rhs.py_result())
1628 1629 1630

            code.putln('%s = %s;' % (self.result(),
                                     rhs.result_as(self.ctype())))
William Stein's avatar
William Stein committed
1631
            if debug_disposal_code:
Stefan Behnel's avatar
Stefan Behnel committed
1632 1633
                print("NameNode.generate_assignment_code:")
                print("...generating post-assignment code for %s" % rhs)
William Stein's avatar
William Stein committed
1634
            rhs.generate_post_assignment_code(code)
1635
            rhs.free_temps(code)
1636 1637

    def generate_acquire_buffer(self, rhs, code):
1638 1639 1640
        # 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.
1641 1642 1643 1644 1645 1646 1647
        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())))

1648 1649 1650
        buffer_aux = self.entry.buffer_aux
        bufstruct = buffer_aux.buffer_info_var.cname
        import Buffer
1651
        Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1652
                                    is_initialized=not self.lhs_of_first_assignment,
1653
                                    pos=self.pos, code=code)
1654 1655 1656 1657
        
        if not pretty_rhs:
            code.putln("%s = 0;" % rhstmp)
            code.funcstate.release_temp(rhstmp)
William Stein's avatar
William Stein committed
1658 1659 1660 1661 1662 1663 1664
    
    def generate_deletion_code(self, code):
        if self.entry is None:
            return # There was an error earlier
        if not self.entry.is_pyglobal:
            error(self.pos, "Deletion of local or C global name not supported")
            return
Stefan Behnel's avatar
Stefan Behnel committed
1665
        if self.entry.is_pyclass_attr:
Vitja Makarov's avatar
Vitja Makarov committed
1666 1667
            namespace = self.entry.scope.namespace_cname
            code.put_error_if_neg(self.pos,
Stefan Behnel's avatar
Stefan Behnel committed
1668
                'PyMapping_DelItemString(%s, "%s")' % (
Vitja Makarov's avatar
Vitja Makarov committed
1669 1670 1671 1672 1673 1674 1675
                    namespace,
                    self.entry.name))
        else:
            code.put_error_if_neg(self.pos, 
                '__Pyx_DelAttrString(%s, "%s")' % (
                    Naming.module_cname,
                    self.entry.name))
1676 1677 1678 1679 1680 1681 1682 1683
                
    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)))
William Stein's avatar
William Stein committed
1684
            
1685
class BackquoteNode(ExprNode):
William Stein's avatar
William Stein committed
1686 1687 1688 1689
    #  `expr`
    #
    #  arg    ExprNode
    
1690 1691
    type = py_object_type
    
William Stein's avatar
William Stein committed
1692 1693 1694 1695 1696 1697
    subexprs = ['arg']
    
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
        self.is_temp = 1
1698 1699 1700

    gil_message = "Backquote expression"

1701 1702 1703
    def calculate_constant_result(self):
        self.constant_result = repr(self.arg.constant_result)

William Stein's avatar
William Stein committed
1704 1705
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1706
            "%s = PyObject_Repr(%s); %s" % (
1707
                self.result(),
William Stein's avatar
William Stein committed
1708
                self.arg.py_result(),
1709
                code.error_goto_if_null(self.result(), self.pos)))
1710
        code.put_gotref(self.py_result())
1711
        
William Stein's avatar
William Stein committed
1712 1713


1714
class ImportNode(ExprNode):
William Stein's avatar
William Stein committed
1715 1716 1717 1718
    #  Used as part of import statement implementation.
    #  Implements result = 
    #    __import__(module_name, globals(), None, name_list)
    #
1719 1720
    #  module_name   StringNode            dotted name of module
    #  name_list     ListNode or None      list of names to be imported
William Stein's avatar
William Stein committed
1721
    
1722
    type = py_object_type
William Stein's avatar
William Stein committed
1723 1724
    
    subexprs = ['module_name', 'name_list']
1725
    
William Stein's avatar
William Stein committed
1726 1727 1728 1729 1730
    def analyse_types(self, env):
        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)
1731
            self.name_list.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
1732 1733
        self.is_temp = 1
        env.use_utility_code(import_utility_code)
1734 1735 1736

    gil_message = "Python import"

William Stein's avatar
William Stein committed
1737 1738 1739 1740 1741 1742
    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(
Robert Bradshaw's avatar
Robert Bradshaw committed
1743
            "%s = __Pyx_Import(%s, %s); %s" % (
1744
                self.result(),
William Stein's avatar
William Stein committed
1745 1746
                self.module_name.py_result(),
                name_list_code,
1747
                code.error_goto_if_null(self.result(), self.pos)))
1748
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1749 1750


1751
class IteratorNode(ExprNode):
William Stein's avatar
William Stein committed
1752
    #  Used as part of for statement implementation.
1753 1754 1755 1756
    #
    #  allocate_counter_temp/release_counter_temp needs to be called
    #  by parent (ForInStatNode)
    #
William Stein's avatar
William Stein committed
1757 1758 1759 1760
    #  Implements result = iter(sequence)
    #
    #  sequence   ExprNode
    
1761 1762
    type = py_object_type
    
William Stein's avatar
William Stein committed
1763 1764 1765 1766
    subexprs = ['sequence']
    
    def analyse_types(self, env):
        self.sequence.analyse_types(env)
1767 1768
        if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \
                not self.sequence.type.is_string:
1769
            # C array iteration will be transformed later on
1770
            self.type = self.sequence.type
1771 1772
        else:
            self.sequence = self.sequence.coerce_to_pyobject(env)
1773 1774 1775
            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
1776
        self.is_temp = 1
1777 1778 1779

    gil_message = "Iterating over Python object"

1780 1781 1782 1783 1784 1785 1786
    def allocate_counter_temp(self, code):
        self.counter_cname = code.funcstate.allocate_temp(
            PyrexTypes.c_py_ssize_t_type, manage_ref=False)

    def release_counter_temp(self, code):
        code.funcstate.release_temp(self.counter_cname)

William Stein's avatar
William Stein committed
1787
    def generate_result_code(self, code):
1788 1789
        if self.sequence.type.is_array or self.sequence.type.is_ptr:
            raise InternalError("for in carray slice not transformed")
1790
        is_builtin_sequence = self.sequence.type is list_type or \
1791
                              self.sequence.type is tuple_type
1792 1793
        may_be_a_sequence = not self.sequence.type.is_builtin_type
        if may_be_a_sequence:
1794 1795 1796 1797
            code.putln(
                "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
                    self.sequence.py_result(),
                    self.sequence.py_result()))
1798
        if is_builtin_sequence or may_be_a_sequence:
1799 1800 1801 1802 1803 1804
            code.putln(
                "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
                    self.counter_cname,
                    self.result(),
                    self.sequence.py_result(),
                    self.result()))
1805 1806 1807
        if not is_builtin_sequence:
            if may_be_a_sequence:
                code.putln("} else {")
1808
            code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1809
                    self.counter_cname,
1810 1811 1812
                    self.result(),
                    self.sequence.py_result(),
                    code.error_goto_if_null(self.result(), self.pos)))
1813
            code.put_gotref(self.py_result())
1814 1815
            if may_be_a_sequence:
                code.putln("}")
William Stein's avatar
William Stein committed
1816 1817


1818
class NextNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1819 1820 1821 1822 1823 1824 1825
    #  Used as part of for statement implementation.
    #  Implements result = iterator.next()
    #  Created during analyse_types phase.
    #  The iterator is not owned by this node.
    #
    #  iterator   ExprNode
    
1826 1827
    type = py_object_type
    
William Stein's avatar
William Stein committed
1828 1829 1830
    def __init__(self, iterator, env):
        self.pos = iterator.pos
        self.iterator = iterator
1831 1832
        if iterator.type.is_ptr or iterator.type.is_array:
            self.type = iterator.type.base_type
William Stein's avatar
William Stein committed
1833 1834 1835
        self.is_temp = 1
    
    def generate_result_code(self, code):
1836 1837
        sequence_type = self.iterator.sequence.type
        if sequence_type is list_type:
1838
            type_checks = [(list_type, "List")]
1839
        elif sequence_type is tuple_type:
1840
            type_checks = [(tuple_type, "Tuple")]
1841
        elif not sequence_type.is_builtin_type:
1842
            type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1843 1844
        else:
            type_checks = []
1845 1846 1847 1848 1849 1850

        for py_type, prefix in type_checks:
            if len(type_checks) > 1:
                code.putln(
                    "if (likely(Py%s_CheckExact(%s))) {" % (
                        prefix, self.iterator.py_result()))
1851 1852
            code.putln(
                "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1853
                    self.iterator.counter_cname,
1854
                    prefix,
1855 1856
                    self.iterator.py_result()))
            code.putln(
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1857
                "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1858
                    self.result(),
1859
                    prefix,
1860
                    self.iterator.py_result(),
1861
                    self.iterator.counter_cname,
1862
                    self.result(),
1863
                    self.iterator.counter_cname))
1864 1865 1866 1867
            if len(type_checks) > 1:
                code.put("} else ")
        if len(type_checks) == 1:
            return
1868
        code.putln("{")
William Stein's avatar
William Stein committed
1869 1870
        code.putln(
            "%s = PyIter_Next(%s);" % (
1871
                self.result(),
William Stein's avatar
William Stein committed
1872 1873 1874
                self.iterator.py_result()))
        code.putln(
            "if (!%s) {" %
1875
                self.result())
1876
        code.putln(code.error_goto_if_PyErr(self.pos))
Robert Bradshaw's avatar
Robert Bradshaw committed
1877 1878
        code.putln("break;")
        code.putln("}")
1879
        code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
1880
        code.putln("}")
1881

William Stein's avatar
William Stein committed
1882

1883
class ExcValueNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1884 1885 1886 1887
    #  Node created during analyse_types phase
    #  of an ExceptClauseNode to fetch the current
    #  exception value.
    
1888 1889
    type = py_object_type
    
1890
    def __init__(self, pos, env):
William Stein's avatar
William Stein committed
1891
        ExprNode.__init__(self, pos)
1892 1893

    def set_var(self, var):
1894
        self.var = var
William Stein's avatar
William Stein committed
1895
    
1896 1897 1898
    def calculate_result_code(self):
        return self.var

William Stein's avatar
William Stein committed
1899
    def generate_result_code(self, code):
1900
        pass
William Stein's avatar
William Stein committed
1901

1902 1903 1904
    def analyse_types(self, env):
        pass

William Stein's avatar
William Stein committed
1905

1906
class TempNode(ExprNode):
1907 1908 1909 1910 1911 1912 1913
    # 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.
1914 1915

    subexprs = []
William Stein's avatar
William Stein committed
1916 1917 1918 1919 1920 1921 1922
    
    def __init__(self, pos, type, env):
        ExprNode.__init__(self, pos)
        self.type = type
        if type.is_pyobject:
            self.result_ctype = py_object_type
        self.is_temp = 1
1923 1924 1925
        
    def analyse_types(self, env):
        return self.type
William Stein's avatar
William Stein committed
1926 1927 1928 1929
    
    def generate_result_code(self, code):
        pass

1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
    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
    
    def release_temp_result(self, code):
        pass
William Stein's avatar
William Stein committed
1950 1951 1952 1953 1954 1955 1956

class PyTempNode(TempNode):
    #  TempNode holding a Python value.
    
    def __init__(self, pos, env):
        TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)

1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975
class RawCNameExprNode(ExprNode):
    subexprs = []
    
    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
1976 1977 1978 1979 1980 1981 1982

#-------------------------------------------------------------------
#
#  Trailer nodes
#
#-------------------------------------------------------------------

1983
class IndexNode(ExprNode):
William Stein's avatar
William Stein committed
1984 1985 1986 1987
    #  Sequence indexing.
    #
    #  base     ExprNode
    #  index    ExprNode
1988 1989 1990 1991 1992 1993
    #  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.
William Stein's avatar
William Stein committed
1994
    
1995 1996 1997 1998 1999 2000
    subexprs = ['base', 'index', 'indices']
    indices = None

    def __init__(self, pos, index, *args, **kw):
        ExprNode.__init__(self, pos, index=index, *args, **kw)
        self._index = index
2001 2002 2003 2004 2005

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

2006 2007 2008 2009 2010 2011 2012 2013
    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)
    
William Stein's avatar
William Stein committed
2014 2015 2016 2017 2018
    def is_ephemeral(self):
        return self.base.is_ephemeral()
    
    def analyse_target_declaration(self, env):
        pass
2019 2020 2021 2022
        
    def analyse_as_type(self, env):
        base_type = self.base.analyse_as_type(env)
        if base_type and not base_type.is_pyobject:
2023
            if base_type.is_cpp_class:
2024
                if isinstance(self.index, TupleNode):
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035
                    template_values = self.index.args
                else:
                    template_values = [self.index]
                import Nodes
                type_node = Nodes.TemplatedTypeNode(
                    pos = self.pos, 
                    positional_args = template_values, 
                    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)))
2036
        return None
William Stein's avatar
William Stein committed
2037
    
Robert Bradshaw's avatar
Robert Bradshaw committed
2038 2039
    def type_dependencies(self, env):
        return self.base.type_dependencies(env)
2040 2041
    
    def infer_type(self, env):
2042 2043 2044 2045
        base_type = self.base.infer_type(env)
        if isinstance(self.index, SliceNode):
            # slicing!
            if base_type.is_string:
2046
                # sliced C strings must coerce to Python 
2047
                return bytes_type
2048 2049 2050
            elif base_type in (unicode_type, bytes_type, str_type, list_type, tuple_type):
                # slicing these returns the same type
                return base_type
2051
            else:
2052 2053 2054
                # TODO: Handle buffers (hopefully without too much redundancy).
                return py_object_type

2055 2056
        index_type = self.index.infer_type(env)
        if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)):
2057 2058 2059 2060 2061 2062 2063 2064 2065 2066
            # indexing!
            if base_type is unicode_type:
                # Py_UNICODE will automatically coerce to a unicode string
                # if required, so this is safe. We only infer Py_UNICODE
                # when the index is a C integer type. Otherwise, we may
                # 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.
                return PyrexTypes.c_py_unicode_type
2067 2068 2069 2070 2071 2072
            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
2073 2074
            elif base_type.is_ptr or base_type.is_array:
                return base_type.base_type
2075

2076
        # may be slicing or indexing, we don't know
2077 2078
        if base_type is unicode_type:
            # this type always returns its own type on Python indexing/slicing
2079
            return base_type
2080 2081 2082 2083
        else:
            # TODO: Handle buffers (hopefully without too much redundancy).
            return py_object_type
    
William Stein's avatar
William Stein committed
2084
    def analyse_types(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2085 2086 2087 2088
        self.analyse_base_and_index_types(env, getting = 1)
    
    def analyse_target_types(self, env):
        self.analyse_base_and_index_types(env, setting = 1)
2089

Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2090
    def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
2091 2092 2093
        # Note: This might be cleaned up by having IndexNode
        # parsed in a saner way and only construct the tuple if
        # needed.
2094 2095 2096 2097

        # 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.
2098 2099
        self.is_buffer_access = False

William Stein's avatar
William Stein committed
2100
        self.base.analyse_types(env)
2101 2102 2103 2104 2105 2106
        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
        
2107
        is_slice = isinstance(self.index, SliceNode)
2108
        # Potentially overflowing index value.
2109
        if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
2110
            self.index = self.index.coerce_to_pyobject(env)
2111

2112
        # Handle the case where base is a literal char* (and we expect a string, not an int)
2113
        if isinstance(self.base, BytesNode) or is_slice:
Robert Bradshaw's avatar
Robert Bradshaw committed
2114
            if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array):
2115
                self.base = self.base.coerce_to_pyobject(env)
2116 2117 2118

        skip_child_analysis = False
        buffer_access = False
2119
        if self.base.type.is_buffer:
2120 2121
            if self.indices:
                indices = self.indices
2122
            else:
2123 2124 2125 2126
                if isinstance(self.index, TupleNode):
                    indices = self.index.args
                else:
                    indices = [self.index]
2127
            if len(indices) == self.base.type.ndim:
2128 2129 2130 2131 2132 2133
                buffer_access = True
                skip_child_analysis = True
                for x in indices:
                    x.analyse_types(env)
                    if not x.type.is_int:
                        buffer_access = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2134 2135
            if buffer_access:
                assert hasattr(self.base, "entry") # Must be a NameNode-like node
2136

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

2140 2141
        if buffer_access:
            self.indices = indices
2142
            self.index = None
2143 2144
            self.type = self.base.type.dtype
            self.is_buffer_access = True
2145
            self.buffer_type = self.base.entry.type
2146 2147

            if getting and self.type.is_pyobject:
2148
                self.is_temp = True
2149 2150 2151 2152 2153
            if setting:
                if not self.base.entry.type.writable:
                    error(self.pos, "Writing to readonly buffer")
                else:
                    self.base.entry.buffer_aux.writable_needed = True
2154
        else:
2155
            base_type = self.base.type
2156 2157 2158 2159
            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)
2160
            self.original_index_type = self.index.type
2161 2162 2163 2164 2165 2166 2167 2168 2169
            if base_type is PyrexTypes.c_py_unicode_type:
                # we infer Py_UNICODE for unicode strings in some
                # 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
2170
            if base_type.is_pyobject:
2171
                if self.index.type.is_int:
2172
                    if (not setting
2173
                        and (base_type in (list_type, tuple_type, unicode_type))
2174 2175 2176 2177 2178
                        and (not self.index.type.signed or isinstance(self.index, IntNode) and int(self.index.value) >= 0)
                        and not env.directives['boundscheck']):
                        self.is_temp = 0
                    else:
                        self.is_temp = 1
2179 2180 2181
                    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)
2182
                    self.is_temp = 1
2183
                if self.index.type.is_int and base_type is unicode_type:
2184
                    # Py_UNICODE will automatically coerce to a unicode string
2185
                    # if required, so this is fast and safe
2186
                    self.type = PyrexTypes.c_py_unicode_type
2187 2188
                elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type):
                    self.type = base_type
2189 2190
                else:
                    self.type = py_object_type
William Stein's avatar
William Stein committed
2191
            else:
2192 2193
                if base_type.is_ptr or base_type.is_array:
                    self.type = base_type.base_type
2194 2195 2196
                    if is_slice:
                        self.type = base_type
                    elif self.index.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
2197 2198
                        self.index = self.index.coerce_to(
                            PyrexTypes.c_py_ssize_t_type, env)
2199
                    elif not self.index.type.is_int:
Robert Bradshaw's avatar
Robert Bradshaw committed
2200 2201 2202
                        error(self.pos,
                            "Invalid index type '%s'" %
                                self.index.type)
2203
                elif base_type.is_cpp_class:
2204
                    function = env.lookup_operator("[]", [self.base, self.index])
Robert Bradshaw's avatar
Robert Bradshaw committed
2205
                    if function is None:
2206
                        error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
2207 2208 2209 2210 2211 2212 2213 2214 2215
                        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
2216
                        error(self.pos, "Can't set non-reference result '%s'" % self.type)
2217 2218 2219
                else:
                    error(self.pos,
                        "Attempting to index non-array type '%s'" %
2220
                            base_type)
2221
                    self.type = PyrexTypes.error_type
Stefan Behnel's avatar
Stefan Behnel committed
2222

2223 2224
    gil_message = "Indexing Python object"

2225 2226
    def nogil_check(self, env):
        if self.is_buffer_access:
2227 2228 2229 2230 2231 2232
            if env.directives['boundscheck']:
                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
2233
        super(IndexNode, self).nogil_check(env)
2234 2235


William Stein's avatar
William Stein committed
2236
    def check_const_addr(self):
2237
        return self.base.check_const_addr() and self.index.check_const()
William Stein's avatar
William Stein committed
2238 2239 2240
    
    def is_lvalue(self):
        return 1
Dag Sverre Seljebotn's avatar
merge  
Dag Sverre Seljebotn committed
2241

William Stein's avatar
William Stein committed
2242
    def calculate_result_code(self):
2243
        if self.is_buffer_access:
2244
            return "(*%s)" % self.buffer_ptr_code
2245 2246 2247 2248
        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())
2249 2250
        elif self.base.type is unicode_type and self.type is PyrexTypes.c_py_unicode_type:
            return "PyUnicode_AS_UNICODE(%s)[%s]" % (self.base.result(), self.index.result())
2251 2252
        elif (self.type.is_ptr or self.type.is_array) and self.type == self.base.type:
            error(self.pos, "Invalid use of pointer slice")
2253 2254
        else:
            return "(%s[%s])" % (
2255
                self.base.result(), self.index.result())
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2256
            
2257
    def extra_index_params(self):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2258 2259
        if self.index.type.is_int:
            if self.original_index_type.signed:
2260
                size_adjustment = ""
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2261
            else:
2262 2263
                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
2264 2265
        else:
            return ""
2266 2267 2268

    def generate_subexpr_evaluation_code(self, code):
        self.base.generate_evaluation_code(code)
2269
        if not self.indices:
2270 2271
            self.index.generate_evaluation_code(code)
        else:
2272 2273
            for i in self.indices:
                i.generate_evaluation_code(code)
2274
        
2275 2276
    def generate_subexpr_disposal_code(self, code):
        self.base.generate_disposal_code(code)
2277
        if not self.indices:
2278 2279
            self.index.generate_disposal_code(code)
        else:
2280 2281
            for i in self.indices:
                i.generate_disposal_code(code)
2282

2283 2284 2285 2286 2287 2288 2289 2290
    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
2291
    def generate_result_code(self, code):
2292
        if self.is_buffer_access:
2293 2294
            if code.globalstate.directives['nonecheck']:
                self.put_nonecheck(code)
2295 2296 2297 2298
            self.buffer_ptr_code = self.buffer_lookup_code(code)
            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
2299
                code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310
        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)
2311
                else:
2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328
                    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())
            elif self.type is PyrexTypes.c_py_unicode_type and self.base.type is unicode_type:
2329 2330 2331
                assert self.index.type.is_int
                index_code = self.index.result()
                function = "__Pyx_GetItemInt_Unicode"
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
                code.globalstate.use_utility_code(getitem_int_pyunicode_utility_code)
                code.putln(
                    "%s = %s(%s, %s%s); if (unlikely(%s == (Py_UNICODE)-1)) %s;" % (
                        self.result(),
                        function,
                        self.base.py_result(),
                        index_code,
                        self.extra_index_params(),
                        self.result(),
                        code.error_goto(self.pos)))
2342
            
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2343 2344 2345
    def generate_setitem_code(self, value_code, code):
        if self.index.type.is_int:
            function = "__Pyx_SetItemInt"
2346
            index_code = self.index.result()
2347
            code.globalstate.use_utility_code(setitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2348 2349
        else:
            index_code = self.index.py_result()
2350 2351
            if self.base.type is dict_type:
                function = "PyDict_SetItem"
Craig Citro's avatar
Craig Citro committed
2352
            # It would seem that we could specialized lists/tuples, but that
2353 2354 2355 2356 2357 2358
            # 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). 
2359 2360
            else:
                function = "PyObject_SetItem"
2361
        code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2362 2363
            "if (%s(%s, %s, %s%s) < 0) %s" % (
                function,
2364
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2365 2366
                index_code,
                value_code,
2367
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2368
                code.error_goto(self.pos)))
2369 2370 2371

    def generate_buffer_setitem_code(self, rhs, code, op=""):
        # Used from generate_assignment_code and InPlaceAssignmentNode
2372 2373
        if code.globalstate.directives['nonecheck']:
            self.put_nonecheck(code)
2374 2375 2376 2377
        ptrexpr = self.buffer_lookup_code(code)
        if self.buffer_type.dtype.is_pyobject:
            # Must manage refcounts. Decref what is already there
            # and incref what we put in.
2378
            ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2379
            rhs_code = rhs.result()
2380
            code.putln("%s = %s;" % (ptr, ptrexpr))
2381
            code.put_gotref("*%s" % ptr)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2382
            code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2383 2384 2385
                ptr, rhs_code
                ))
            code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2386
            code.put_giveref("*%s" % ptr)
2387 2388 2389
            code.funcstate.release_temp(ptr)
        else: 
            # Simple case
2390
            code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2391

William Stein's avatar
William Stein committed
2392 2393
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2394
        if self.is_buffer_access:
2395
            self.generate_buffer_setitem_code(rhs, code)
2396
        elif self.type.is_pyobject:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2397
            self.generate_setitem_code(rhs.py_result(), code)
William Stein's avatar
William Stein committed
2398 2399 2400
        else:
            code.putln(
                "%s = %s;" % (
2401
                    self.result(), rhs.result()))
2402
        self.generate_subexpr_disposal_code(code)
2403
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2404
        rhs.generate_disposal_code(code)
2405
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2406 2407 2408
    
    def generate_deletion_code(self, code):
        self.generate_subexpr_evaluation_code(code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2409 2410
        #if self.type.is_pyobject:
        if self.index.type.is_int:
2411
            function = "__Pyx_DelItemInt"
2412
            index_code = self.index.result()
2413
            code.globalstate.use_utility_code(delitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2414 2415
        else:
            index_code = self.index.py_result()
2416 2417 2418 2419
            if self.base.type is dict_type:
                function = "PyDict_DelItem"
            else:
                function = "PyObject_DelItem"
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2420
        code.putln(
2421
            "if (%s(%s, %s%s) < 0) %s" % (
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2422
                function,
William Stein's avatar
William Stein committed
2423
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2424
                index_code,
2425
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2426
                code.error_goto(self.pos)))
William Stein's avatar
William Stein committed
2427
        self.generate_subexpr_disposal_code(code)
2428
        self.free_subexpr_temps(code)
2429

2430
    def buffer_lookup_code(self, code):
2431
        # Assign indices to temps
2432
        index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2433
        for temp, index in zip(index_temps, self.indices):
2434
            code.putln("%s = %s;" % (temp, index.result()))
2435 2436
        # Generate buffer access code using these temps
        import Buffer
2437 2438
        # The above could happen because child_attrs is wrong somewhere so that
        # options are not propagated.
2439 2440 2441
        return Buffer.put_buffer_lookup_code(entry=self.base.entry,
                                             index_signeds=[i.type.signed for i in self.indices],
                                             index_cnames=index_temps,
2442
                                             directives=code.globalstate.directives,
2443
                                             pos=self.pos, code=code)
William Stein's avatar
William Stein committed
2444

2445 2446 2447 2448 2449 2450 2451
    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("}")

2452
class SliceIndexNode(ExprNode):
William Stein's avatar
William Stein committed
2453 2454 2455 2456 2457 2458 2459
    #  2-element slice indexing
    #
    #  base      ExprNode
    #  start     ExprNode or None
    #  stop      ExprNode or None
    
    subexprs = ['base', 'start', 'stop']
2460

2461 2462 2463 2464 2465 2466 2467 2468 2469
    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
        return py_object_type

2470 2471 2472 2473
    def calculate_constant_result(self):
        self.constant_result = self.base.constant_result[
            self.start.constant_result : self.stop.constant_result]

2474 2475
    def compile_time_value(self, denv):
        base = self.base.compile_time_value(denv)
2476 2477 2478 2479 2480 2481 2482 2483
        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)
2484 2485 2486 2487 2488
        try:
            return base[start:stop]
        except Exception, e:
            self.compile_time_value_error(e)
    
William Stein's avatar
William Stein committed
2489 2490
    def analyse_target_declaration(self, env):
        pass
2491 2492 2493 2494
    
    def analyse_target_types(self, env):
        self.analyse_types(env)
        # when assigning, we must accept any Python type
2495 2496
        if self.type.is_pyobject:
            self.type = py_object_type
William Stein's avatar
William Stein committed
2497 2498 2499 2500 2501 2502 2503

    def analyse_types(self, env):
        self.base.analyse_types(env)
        if self.start:
            self.start.analyse_types(env)
        if self.stop:
            self.stop.analyse_types(env)
2504 2505 2506
        base_type = self.base.type
        if base_type.is_string:
            self.type = bytes_type
2507 2508 2509
        elif base_type.is_ptr:
            self.type = base_type
        elif base_type.is_array:
2510 2511 2512
            # we need a ptr type here instead of an array type, as
            # array types can result in invalid type casts in the C
            # code
2513
            self.type = PyrexTypes.CPtrType(base_type.base_type)
2514 2515 2516
        else:
            self.base = self.base.coerce_to_pyobject(env)
            self.type = py_object_type
2517 2518 2519
        if base_type.is_builtin_type:
            # slicing builtin types returns something of the same type
            self.type = base_type
2520
        c_int = PyrexTypes.c_py_ssize_t_type
William Stein's avatar
William Stein committed
2521 2522 2523 2524 2525
        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
2526

2527
    nogil_check = Node.gil_error
2528 2529
    gil_message = "Slicing Python object"

William Stein's avatar
William Stein committed
2530
    def generate_result_code(self, code):
2531 2532 2533 2534
        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
2535 2536 2537
        if self.base.type.is_string:
            if self.stop is None:
                code.putln(
2538
                    "%s = PyBytes_FromString(%s + %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2539 2540 2541 2542 2543 2544
                        self.result(),
                        self.base.result(),
                        self.start_code(),
                        code.error_goto_if_null(self.result(), self.pos)))
            else:
                code.putln(
2545
                    "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2546 2547 2548 2549 2550 2551 2552 2553
                        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(
2554
                "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2555 2556 2557 2558 2559
                    self.result(),
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
                    code.error_goto_if_null(self.result(), self.pos)))
2560
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2561 2562 2563
    
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2564 2565
        if self.type.is_pyobject:
            code.put_error_if_neg(self.pos, 
2566
                "__Pyx_PySequence_SetSlice(%s, %s, %s, %s)" % (
2567 2568 2569
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
Lisandro Dalcin's avatar
Lisandro Dalcin committed
2570
                    rhs.py_result()))
2571 2572 2573 2574 2575 2576 2577 2578
        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
2579 2580
            if rhs.type.is_array:
                array_length = rhs.type.size
2581
                self.generate_slice_guard_code(code, array_length)
Stefan Behnel's avatar
Stefan Behnel committed
2582
            else:
Stefan Behnel's avatar
Stefan Behnel committed
2583 2584
                error(self.pos,
                      "Slice assignments from pointers are not yet supported.")
Stefan Behnel's avatar
Stefan Behnel committed
2585 2586
                # FIXME: fix the array size according to start/stop
                array_length = self.base.type.size
2587 2588 2589 2590
            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
2591
        self.generate_subexpr_disposal_code(code)
2592
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2593
        rhs.generate_disposal_code(code)
2594
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2595 2596

    def generate_deletion_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2597
        if not self.base.type.is_pyobject:
2598 2599 2600
            error(self.pos,
                  "Deleting slices is only supported for Python types, not '%s'." % self.type)
            return
William Stein's avatar
William Stein committed
2601
        self.generate_subexpr_evaluation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2602
        code.put_error_if_neg(self.pos,
2603
            "__Pyx_PySequence_DelSlice(%s, %s, %s)" % (
William Stein's avatar
William Stein committed
2604 2605
                self.base.py_result(),
                self.start_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
2606
                self.stop_code()))
William Stein's avatar
William Stein committed
2607
        self.generate_subexpr_disposal_code(code)
2608 2609 2610 2611 2612 2613 2614 2615 2616 2617

    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
2618
                if stop < 0:
2619
                    slice_size = self.base.type.size + stop
Stefan Behnel's avatar
Stefan Behnel committed
2620 2621
                else:
                    slice_size = stop
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651
                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))
2652
            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));' % (
2653 2654 2655
                        target_size, check))
            code.putln(code.error_goto(self.pos))
            code.putln("}")
William Stein's avatar
William Stein committed
2656 2657 2658
    
    def start_code(self):
        if self.start:
2659
            return self.start.result()
William Stein's avatar
William Stein committed
2660 2661 2662 2663 2664
        else:
            return "0"
    
    def stop_code(self):
        if self.stop:
2665
            return self.stop.result()
2666 2667
        elif self.base.type.is_array:
            return self.base.type.size
William Stein's avatar
William Stein committed
2668
        else:
2669
            return "PY_SSIZE_T_MAX"
William Stein's avatar
William Stein committed
2670 2671
    
    def calculate_result_code(self):
2672
        # self.result() is not used, but this method must exist
William Stein's avatar
William Stein committed
2673 2674 2675
        return "<unused>"
    

2676
class SliceNode(ExprNode):
William Stein's avatar
William Stein committed
2677 2678 2679 2680 2681
    #  start:stop:step in subscript list
    #
    #  start     ExprNode
    #  stop      ExprNode
    #  step      ExprNode
2682 2683 2684
    
    type = py_object_type
    is_temp = 1
2685 2686 2687 2688 2689 2690 2691

    def calculate_constant_result(self):
        self.constant_result = self.base.constant_result[
            self.start.constant_result : \
                self.stop.constant_result : \
                self.step.constant_result]

2692 2693
    def compile_time_value(self, denv):
        start = self.start.compile_time_value(denv)
2694 2695 2696 2697 2698 2699 2700 2701
        if self.stop is None:
            stop = None
        else:
            stop = self.stop.compile_time_value(denv)
        if self.step is None:
            step = None
        else:
            step = self.step.compile_time_value(denv)
2702 2703 2704 2705 2706
        try:
            return slice(start, stop, step)
        except Exception, e:
            self.compile_time_value_error(e)

William Stein's avatar
William Stein committed
2707 2708 2709 2710 2711 2712 2713 2714 2715
    subexprs = ['start', 'stop', 'step']
    
    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)
2716 2717 2718

    gil_message = "Constructing Python slice object"

William Stein's avatar
William Stein committed
2719 2720
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2721
            "%s = PySlice_New(%s, %s, %s); %s" % (
2722
                self.result(),
William Stein's avatar
William Stein committed
2723 2724 2725
                self.start.py_result(), 
                self.stop.py_result(), 
                self.step.py_result(),
2726
                code.error_goto_if_null(self.result(), self.pos)))
2727
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2728

2729

2730
class CallNode(ExprNode):
2731

Stefan Behnel's avatar
Stefan Behnel committed
2732 2733 2734 2735 2736 2737 2738 2739
    # allow overriding the default 'may_be_none' behaviour
    may_return_none = None

    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
2740 2741 2742 2743 2744 2745
    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):
2746
                items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
Robert Bradshaw's avatar
Robert Bradshaw committed
2747 2748 2749 2750 2751 2752 2753
            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
2754 2755 2756 2757 2758 2759 2760 2761 2762
        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
2763 2764 2765
    
    def is_lvalue(self):
        return self.type.is_reference
2766

2767
    def nogil_check(self, env):
2768 2769
        func_type = self.function_type()
        if func_type.is_pyobject:
2770
            self.gil_error()
2771
        elif not getattr(func_type, 'nogil', False):
2772
            self.gil_error()
2773 2774 2775

    gil_message = "Calling gil-requiring function"

2776 2777

class SimpleCallNode(CallNode):
William Stein's avatar
William Stein committed
2778 2779 2780 2781 2782 2783 2784
    #  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
2785
    #  wrapper_call   bool                 used internally
2786
    #  has_optional_args   bool            used internally
2787
    #  nogil          bool                 used internally
William Stein's avatar
William Stein committed
2788 2789 2790 2791 2792 2793
    
    subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
    
    self = None
    coerced_self = None
    arg_tuple = None
2794
    wrapper_call = False
2795
    has_optional_args = False
2796
    nogil = False
2797
    analysed = False
William Stein's avatar
William Stein committed
2798
    
2799 2800 2801 2802 2803 2804 2805
    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)
2806
            
Robert Bradshaw's avatar
Robert Bradshaw committed
2807
    def type_dependencies(self, env):
2808 2809
        # TODO: Update when Danilo's C++ code merged in to handle the
        # the case of function overloading.
Robert Bradshaw's avatar
Robert Bradshaw committed
2810
        return self.function.type_dependencies(env)
2811 2812
    
    def infer_type(self, env):
2813 2814
        function = self.function
        func_type = function.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
2815 2816
        if isinstance(self.function, NewExprNode):
            return PyrexTypes.CPtrType(self.function.class_type)
2817 2818 2819 2820
        if func_type.is_ptr:
            func_type = func_type.base_type
        if func_type.is_cfunction:
            return func_type.return_type
2821 2822 2823 2824 2825 2826
        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:
2827 2828 2829
                    if function.entry.name == 'float':
                        return PyrexTypes.c_double_type
                    elif function.entry.name in Builtin.types_that_construct_their_instance:
2830 2831 2832
                        return result_type
        return py_object_type

2833
    def analyse_as_type(self, env):
2834
        attr = self.function.as_cython_attribute()
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
        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
2847

William Stein's avatar
William Stein committed
2848
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2849 2850
        if self.analyse_as_type_constructor(env):
            return
2851 2852 2853
        if self.analysed:
            return
        self.analysed = True
William Stein's avatar
William Stein committed
2854 2855 2856 2857 2858 2859 2860 2861 2862 2863
        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:
2864 2865
            self.arg_tuple = TupleNode(self.pos, args = self.args)
            self.arg_tuple.analyse_types(env)
William Stein's avatar
William Stein committed
2866
            self.args = None
2867 2868 2869
            if func_type is Builtin.type_type and function.is_name and \
                   function.entry and \
                   function.entry.is_builtin and \
2870 2871 2872 2873 2874 2875 2876 2877 2878
                   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
2879
                self.may_return_none = False
2880
            elif function.is_name and function.type_entry:
2881 2882 2883 2884 2885
                # 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
2886
                self.may_return_none = False
2887 2888
            else:
                self.type = py_object_type
William Stein's avatar
William Stein committed
2889 2890 2891 2892 2893 2894
            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.
2895 2896 2897
                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(
2898 2899
                        "'NoneType' object has no attribute '%s'" % self.function.entry.name,
                        'PyExc_AttributeError')
2900
                expected_type = self_arg.type
William Stein's avatar
William Stein committed
2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915
                self.coerced_self = CloneNode(self.self).coerce_to(
                    expected_type, env)
                # Insert coerced 'self' argument into argument list.
                self.args.insert(0, self.coerced_self)
            self.analyse_c_function_call(env)
    
    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
    
    def analyse_c_function_call(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2916
        if self.function.type is error_type:
2917
            self.type = error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2918
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
2919
        if self.function.type.is_cpp_class:
2920 2921
            overloaded_entry = self.function.type.scope.lookup("operator()")
            if overloaded_entry is None:
Robert Bradshaw's avatar
Robert Bradshaw committed
2922 2923 2924
                self.type = PyrexTypes.error_type
                self.result_code = "<error>"
                return
2925 2926
        elif hasattr(self.function, 'entry'):
            overloaded_entry = self.function.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
2927
        else:
2928 2929 2930 2931 2932 2933 2934 2935 2936
            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
2937 2938 2939 2940 2941 2942 2943 2944
            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
2945
        # Check no. of args
2946 2947
        max_nargs = len(func_type.args)
        expected_nargs = max_nargs - func_type.optional_arg_count
William Stein's avatar
William Stein committed
2948
        actual_nargs = len(self.args)
2949 2950 2951
        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
2952
        # Coerce arguments
2953
        for i in range(min(max_nargs, actual_nargs)):
William Stein's avatar
William Stein committed
2954 2955
            formal_type = func_type.args[i].type
            self.args[i] = self.args[i].coerce_to(formal_type, env)
2956
        for i in range(max_nargs, actual_nargs):
William Stein's avatar
William Stein committed
2957 2958 2959 2960
            if self.args[i].type.is_pyobject:
                error(self.args[i].pos, 
                    "Python object cannot be passed as a varargs parameter")
        # Calc result type and code fragment
Robert Bradshaw's avatar
Robert Bradshaw committed
2961
        if isinstance(self.function, NewExprNode):
2962
            self.type = PyrexTypes.CPtrType(self.function.class_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2963 2964
        else:
            self.type = func_type.return_type
Stefan Behnel's avatar
Stefan Behnel committed
2965 2966 2967 2968 2969 2970
        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
2971
        # Called in 'nogil' context?
2972
        self.nogil = env.nogil
2973 2974 2975 2976 2977
        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
2978 2979 2980 2981
        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
2982 2983 2984 2985 2986
    def calculate_result_code(self):
        return self.c_call_code()
    
    def c_call_code(self):
        func_type = self.function_type()
2987
        if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
William Stein's avatar
William Stein committed
2988 2989 2990
            return "<error>"
        formal_args = func_type.args
        arg_list_code = []
2991
        args = list(zip(formal_args, self.args))
2992 2993 2994 2995
        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
2996 2997
                arg_code = actual_arg.result_as(formal_arg.type)
                arg_list_code.append(arg_code)
2998
                
2999 3000 3001
        if func_type.is_overridable:
            arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
                
3002
        if func_type.optional_arg_count:
3003
            if expected_nargs == actual_nargs:
3004
                optional_args = 'NULL'
3005
            else:
3006
                optional_args = "&%s" % self.opt_arg_struct
3007
            arg_list_code.append(optional_args)
3008
            
William Stein's avatar
William Stein committed
3009
        for actual_arg in self.args[len(formal_args):]:
3010 3011
            arg_list_code.append(actual_arg.result())
        result = "%s(%s)" % (self.function.result(),
Stefan Behnel's avatar
Stefan Behnel committed
3012
            ', '.join(arg_list_code))
William Stein's avatar
William Stein committed
3013 3014 3015 3016 3017
        return result
    
    def generate_result_code(self, code):
        func_type = self.function_type()
        if func_type.is_pyobject:
3018
            arg_code = self.arg_tuple.py_result()
William Stein's avatar
William Stein committed
3019
            code.putln(
3020
                "%s = PyObject_Call(%s, %s, NULL); %s" % (
3021
                    self.result(),
William Stein's avatar
William Stein committed
3022
                    self.function.py_result(),
3023
                    arg_code,
3024
                    code.error_goto_if_null(self.result(), self.pos)))
3025
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3026
        elif func_type.is_cfunction:
3027 3028 3029
            if self.has_optional_args:
                actual_nargs = len(self.args)
                expected_nargs = len(func_type.args) - func_type.optional_arg_count
3030 3031
                self.opt_arg_struct = code.funcstate.allocate_temp(
                    func_type.op_arg_struct.base_type, manage_ref=True)
3032 3033 3034 3035
                code.putln("%s.%s = %s;" % (
                        self.opt_arg_struct,
                        Naming.pyrex_prefix + "n",
                        len(self.args) - expected_nargs))
3036
                args = list(zip(func_type.args, self.args))
3037 3038 3039
                for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
                    code.putln("%s.%s = %s;" % (
                            self.opt_arg_struct,
3040
                            func_type.opt_arg_cname(formal_arg.name),
3041
                            actual_arg.result_as(formal_arg.type)))
William Stein's avatar
William Stein committed
3042
            exc_checks = []
3043
            if self.type.is_pyobject and self.is_temp:
3044
                exc_checks.append("!%s" % self.result())
William Stein's avatar
William Stein committed
3045
            else:
3046 3047
                exc_val = func_type.exception_value
                exc_check = func_type.exception_check
William Stein's avatar
William Stein committed
3048
                if exc_val is not None:
3049
                    exc_checks.append("%s == %s" % (self.result(), exc_val))
William Stein's avatar
William Stein committed
3050
                if exc_check:
3051 3052 3053 3054
                    if self.nogil:
                        exc_checks.append("__Pyx_ErrOccurredWithGIL()")
                    else:    
                        exc_checks.append("PyErr_Occurred()")
William Stein's avatar
William Stein committed
3055 3056
            if self.is_temp or exc_checks:
                rhs = self.c_call_code()
3057 3058
                if self.result():
                    lhs = "%s = " % self.result()
William Stein's avatar
William Stein committed
3059 3060 3061
                    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
3062
                        #    "from", return_type, "to pyobject" ###
William Stein's avatar
William Stein committed
3063 3064 3065
                        rhs = typecast(py_object_type, self.type, rhs)
                else:
                    lhs = ""
Felix Wu's avatar
Felix Wu committed
3066
                if func_type.exception_check == '+':
Robert Bradshaw's avatar
Robert Bradshaw committed
3067 3068 3069
                    if func_type.exception_value is None:
                        raise_py_exception = "__Pyx_CppExn2PyErr()"
                    elif func_type.exception_value.type.is_pyobject:
3070 3071 3072
                        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
3073 3074
                    else:
                        raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
3075 3076
                    if self.nogil:
                        raise_py_exception = 'Py_BLOCK_THREADS; %s; Py_UNBLOCK_THREADS' % raise_py_exception
Felix Wu's avatar
Felix Wu committed
3077
                    code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3078
                    "try {%s%s;} catch(...) {%s; %s}" % (
Felix Wu's avatar
Felix Wu committed
3079 3080
                        lhs,
                        rhs,
Robert Bradshaw's avatar
Robert Bradshaw committed
3081
                        raise_py_exception,
Felix Wu's avatar
Felix Wu committed
3082
                        code.error_goto(self.pos)))
3083 3084 3085 3086 3087 3088
                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))
3089
                if self.type.is_pyobject and self.result():
3090
                    code.put_gotref(self.py_result())
3091 3092
            if self.has_optional_args:
                code.funcstate.release_temp(self.opt_arg_struct)
3093 3094 3095 3096


class PythonCapiFunctionNode(ExprNode):
    subexprs = []
3097
    def __init__(self, pos, py_name, cname, func_type, utility_code = None):
3098
        self.pos = pos
3099 3100
        self.name = py_name
        self.cname = cname
3101 3102 3103
        self.type = func_type
        self.utility_code = utility_code

3104 3105 3106
    def analyse_types(self, env):
        pass

3107 3108 3109 3110 3111
    def generate_result_code(self, code):
        if self.utility_code:
            code.globalstate.use_utility_code(self.utility_code)

    def calculate_result_code(self):
3112
        return self.cname
3113 3114 3115 3116

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

Stefan Behnel's avatar
Stefan Behnel committed
3117 3118 3119 3120 3121 3122
    # 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

3123
    def __init__(self, pos, function_name, func_type,
3124
                 utility_code = None, py_name=None, **kwargs):
3125 3126 3127
        self.type = func_type.return_type
        self.result_ctype = self.type
        self.function = PythonCapiFunctionNode(
3128
            pos, py_name, function_name, func_type,
3129 3130 3131 3132 3133
            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
3134

3135
class GeneralCallNode(CallNode):
William Stein's avatar
William Stein committed
3136 3137 3138 3139 3140 3141 3142 3143
    #  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
    #  starstar_arg     ExprNode or None  Dict of extra keyword args
    
3144 3145
    type = py_object_type
    
William Stein's avatar
William Stein committed
3146 3147
    subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']

3148
    nogil_check = Node.gil_error
3149

3150 3151 3152 3153 3154 3155 3156 3157 3158 3159
    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)
        starstar_arg = self.starstar_arg.compile_time_value(denv)
        try:
            keyword_args.update(starstar_arg)
            return function(*positional_args, **keyword_args)
        except Exception, e:
            self.compile_time_value_error(e)
3160 3161 3162
            
    def explicit_args_kwds(self):
        if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
3163
            raise CompileError(self.pos,
3164 3165
                'Compile-time keyword arguments must be explicit.')
        return self.positional_args.args, self.keyword_args
3166

William Stein's avatar
William Stein committed
3167
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3168 3169
        if self.analyse_as_type_constructor(env):
            return
William Stein's avatar
William Stein committed
3170 3171 3172 3173 3174 3175
        self.function.analyse_types(env)
        self.positional_args.analyse_types(env)
        if self.keyword_args:
            self.keyword_args.analyse_types(env)
        if self.starstar_arg:
            self.starstar_arg.analyse_types(env)
3176
        if not self.function.type.is_pyobject:
3177 3178
            if self.function.type.is_error:
                self.type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
3179
                return
3180
            if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
3181
                error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
3182 3183
            else:
                self.function = self.function.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
3184 3185 3186 3187 3188
        self.positional_args = \
            self.positional_args.coerce_to_pyobject(env)
        if self.starstar_arg:
            self.starstar_arg = \
                self.starstar_arg.coerce_to_pyobject(env)
Stefan Behnel's avatar
Stefan Behnel committed
3189
        function = self.function
3190 3191 3192 3193 3194
        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
3195
            self.may_return_none = False
3196 3197
        else:
            self.type = py_object_type
William Stein's avatar
William Stein committed
3198 3199 3200
        self.is_temp = 1
        
    def generate_result_code(self, code):
3201
        if self.type.is_error: return
3202
        kwargs_call_function = "PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
3203
        if self.keyword_args and self.starstar_arg:
Robert Bradshaw's avatar
Robert Bradshaw committed
3204 3205
            code.put_error_if_neg(self.pos, 
                "PyDict_Update(%s, %s)" % (
William Stein's avatar
William Stein committed
3206
                    self.keyword_args.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
3207
                    self.starstar_arg.py_result()))
William Stein's avatar
William Stein committed
3208 3209 3210 3211 3212
            keyword_code = self.keyword_args.py_result()
        elif self.keyword_args:
            keyword_code = self.keyword_args.py_result()
        elif self.starstar_arg:
            keyword_code = self.starstar_arg.py_result()
3213 3214
            if self.starstar_arg.type is not Builtin.dict_type:
                # CPython supports calling functions with non-dicts, so do we
3215 3216
                code.globalstate.use_utility_code(kwargs_call_utility_code)
                kwargs_call_function = "__Pyx_PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
3217 3218 3219
        else:
            keyword_code = None
        if not keyword_code:
3220
            call_code = "PyObject_Call(%s, %s, NULL)" % (
William Stein's avatar
William Stein committed
3221 3222 3223
                self.function.py_result(),
                self.positional_args.py_result())
        else:
3224 3225
            call_code = "%s(%s, %s, %s)" % (
                kwargs_call_function,
William Stein's avatar
William Stein committed
3226 3227 3228 3229
                self.function.py_result(),
                self.positional_args.py_result(),
                keyword_code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3230
            "%s = %s; %s" % (
3231
                self.result(),
William Stein's avatar
William Stein committed
3232
                call_code,
3233
                code.error_goto_if_null(self.result(), self.pos)))
3234
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3235 3236


3237
class AsTupleNode(ExprNode):
William Stein's avatar
William Stein committed
3238 3239 3240 3241 3242 3243
    #  Convert argument to tuple. Used for normalising
    #  the * argument of a function call.
    #
    #  arg    ExprNode
    
    subexprs = ['arg']
3244 3245 3246

    def calculate_constant_result(self):
        self.constant_result = tuple(self.base.constant_result)
William Stein's avatar
William Stein committed
3247
    
3248 3249 3250 3251 3252 3253 3254
    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
3255 3256 3257
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
3258
        self.type = tuple_type
William Stein's avatar
William Stein committed
3259
        self.is_temp = 1
3260

3261 3262 3263
    def may_be_none(self):
        return False

3264
    nogil_check = Node.gil_error
3265 3266
    gil_message = "Constructing Python tuple"

William Stein's avatar
William Stein committed
3267 3268
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3269
            "%s = PySequence_Tuple(%s); %s" % (
3270
                self.result(),
William Stein's avatar
William Stein committed
3271
                self.arg.py_result(),
3272
                code.error_goto_if_null(self.result(), self.pos)))
3273
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3274 3275
    

3276
class AttributeNode(ExprNode):
William Stein's avatar
William Stein committed
3277 3278 3279 3280
    #  obj.attribute
    #
    #  obj          ExprNode
    #  attribute    string
3281
    #  needs_none_check boolean        Used if obj is an extension type.
3282
    #                                  If set to True, it is known that the type is not None.
William Stein's avatar
William Stein committed
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296
    #
    #  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
    
    is_attribute = 1
    subexprs = ['obj']
    
    type = PyrexTypes.error_type
    entry = None
    is_called = 0
3297
    needs_none_check = True
William Stein's avatar
William Stein committed
3298

3299
    def as_cython_attribute(self):
3300 3301
        if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
            return self.attribute
3302 3303 3304
        cy = self.obj.as_cython_attribute()
        if cy:
            return "%s.%s" % (cy, self.attribute)
3305

3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
    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
                self.analyse_as_python_attribute(env) 
                return self
3317
        return ExprNode.coerce_to(self, dst_type, env)
3318 3319 3320

    def calculate_constant_result(self):
        attr = self.attribute
3321
        if attr.startswith("__") and attr.endswith("__"):
3322 3323 3324
            return
        self.constant_result = getattr(self.obj.constant_result, attr)

3325 3326
    def compile_time_value(self, denv):
        attr = self.attribute
3327
        if attr.startswith("__") and attr.endswith("__"):
Stefan Behnel's avatar
Stefan Behnel committed
3328 3329
            error(self.pos,
                  "Invalid attribute name '%s' in compile-time expression" % attr)
3330
            return None
3331
        obj = self.obj.compile_time_value(denv)
3332 3333 3334 3335
        try:
            return getattr(obj, attr)
        except Exception, e:
            self.compile_time_value_error(e)
3336
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3337 3338 3339
    def type_dependencies(self, env):
        return self.obj.type_dependencies(env)
    
3340 3341 3342 3343 3344 3345
    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:
Robert Bradshaw's avatar
Robert Bradshaw committed
3346
            self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
3347
            return self.type
3348

William Stein's avatar
William Stein committed
3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392
    def analyse_target_declaration(self, env):
        pass
    
    def analyse_target_types(self, env):
        self.analyse_types(env, target = 1)
    
    def analyse_types(self, env, target = 0):
        if self.analyse_as_cimported_attribute(env, target):
            return
        if not target and self.analyse_as_unbound_cmethod(env):
            return
        self.analyse_as_ordinary_attribute(env, target)
    
    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)
                    return 1
        return 0
    
    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
3393
                ubcm_entry.is_unbound_cmethod = 1
William Stein's avatar
William Stein committed
3394 3395 3396
                self.mutate_into_name_node(env, ubcm_entry, None)
                return 1
        return 0
3397 3398 3399 3400
        
    def analyse_as_type(self, env):
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
3401
            return module_scope.lookup_type(self.attribute)
Robert Bradshaw's avatar
Robert Bradshaw committed
3402 3403 3404 3405
        if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)):
            base_type = self.obj.analyse_as_type(env)
            if base_type and hasattr(base_type, 'scope'):
                return base_type.scope.lookup_type(self.attribute)
3406
        return None
William Stein's avatar
William Stein committed
3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
    
    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
    
    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
                
    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:
3439
            NameNode.analyse_rvalue_entry(self, env)
William Stein's avatar
William Stein committed
3440 3441 3442 3443 3444
    
    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:
3445 3446
#            error(self.pos, "C method can only be called")
            pass
3447 3448
        ## Reference to C array turns into pointer to first element.
        #while self.type.is_array:
Robert Bradshaw's avatar
Robert Bradshaw committed
3449
        #    self.type = self.type.element_ptr_type()
William Stein's avatar
William Stein committed
3450 3451 3452 3453 3454
        if self.is_py_attr:
            if not target:
                self.is_temp = 1
                self.result_ctype = py_object_type
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3455
    def analyse_attribute(self, env, obj_type = None):
William Stein's avatar
William Stein committed
3456 3457 3458
        # 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
3459 3460 3461 3462 3463 3464 3465
        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
3466
        if obj_type.is_ptr or obj_type.is_array:
William Stein's avatar
William Stein committed
3467 3468 3469 3470 3471 3472 3473 3474 3475 3476
            obj_type = obj_type.base_type
            self.op = "->"
        elif obj_type.is_extension_type:
            self.op = "->"
        else:
            self.op = "."
        if obj_type.has_attributes:
            entry = None
            if obj_type.attributes_known():
                entry = obj_type.scope.lookup_here(self.attribute)
Robert Bradshaw's avatar
Robert Bradshaw committed
3477 3478
                if entry and entry.is_member:
                    entry = None
William Stein's avatar
William Stein committed
3479 3480 3481 3482
            else:
                error(self.pos, 
                    "Cannot select attribute of incomplete type '%s'" 
                    % obj_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3483 3484
                self.type = PyrexTypes.error_type
                return
William Stein's avatar
William Stein committed
3485 3486
            self.entry = entry
            if entry:
3487 3488
                if obj_type.is_extension_type and entry.name == "__weakref__":
                    error(self.pos, "Illegal use of special attribute __weakref__")
3489 3490
                # methods need the normal attribute lookup
                # because they do not have struct entries
3491 3492 3493 3494
                if entry.is_variable or entry.is_cmethod:
                    self.type = entry.type
                    self.member = entry.cname
                    return
William Stein's avatar
William Stein committed
3495 3496 3497 3498 3499 3500 3501 3502 3503
                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
        # If we get here, the base object is not a struct/union/extension 
        # 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
3504
        self.analyse_as_python_attribute(env, obj_type)
Stefan Behnel's avatar
Stefan Behnel committed
3505

Robert Bradshaw's avatar
Robert Bradshaw committed
3506 3507 3508
    def analyse_as_python_attribute(self, env, obj_type = None):
        if obj_type is None:
            obj_type = self.obj.type
3509
        self.member = self.attribute
3510 3511
        self.type = py_object_type
        self.is_py_attr = 1
3512
        if not obj_type.is_pyobject and not obj_type.is_error:
3513
            if obj_type.can_coerce_to_pyobject(env):
3514 3515 3516 3517 3518
                self.obj = self.obj.coerce_to_pyobject(env)
            else:
                error(self.pos,
                      "Object of type '%s' has no attribute '%s'" %
                      (obj_type, self.attribute))
3519

3520
    def nogil_check(self, env):
3521
        if self.is_py_attr:
3522
            self.gil_error()
3523

3524 3525
    gil_message = "Accessing Python attribute"

William Stein's avatar
William Stein committed
3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545
    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)
    
    def is_ephemeral(self):
        if self.obj:
            return self.obj.is_ephemeral()
        else:
            return NameNode.is_ephemeral(self)
    
    def calculate_result_code(self):
        #print "AttributeNode.calculate_result_code:", self.member ###
3546
        #print "...obj node =", self.obj, "code", self.obj.result() ###
William Stein's avatar
William Stein committed
3547 3548 3549 3550 3551
        #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:
Robert Bradshaw's avatar
Robert Bradshaw committed
3552 3553 3554 3555 3556 3557
            if obj.type.is_extension_type:
                return "((struct %s *)%s%s%s)->%s" % (
                    obj.type.vtabstruct_cname, obj_code, self.op, 
                    obj.type.vtabslot_cname, self.member)
            else:
                return self.member
3558
        elif obj.type.is_complex:
3559
            return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
William Stein's avatar
William Stein committed
3560 3561 3562 3563
        else:
            return "%s%s%s" % (obj_code, self.op, self.member)
    
    def generate_result_code(self, code):
3564
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3565
        if self.is_py_attr:
3566 3567
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
3568
                    self.result(),
3569
                    self.obj.py_result(),
3570
                    interned_attr_cname,
3571
                    code.error_goto_if_null(self.result(), self.pos)))
3572
            code.put_gotref(self.py_result())
3573 3574 3575
        else:
            # result_code contains what is needed, but we may need to insert
            # a check and raise an exception
3576 3577 3578 3579
            if (self.obj.type.is_extension_type
                  and self.needs_none_check
                  and code.globalstate.directives['nonecheck']):
                self.put_nonecheck(code)
William Stein's avatar
William Stein committed
3580 3581
    
    def generate_assignment_code(self, rhs, code):
3582
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3583 3584
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
3585 3586 3587
            code.put_error_if_neg(self.pos, 
                'PyObject_SetAttr(%s, %s, %s)' % (
                    self.obj.py_result(),
3588
                    interned_attr_cname,
3589
                    rhs.py_result()))
William Stein's avatar
William Stein committed
3590
            rhs.generate_disposal_code(code)
3591
            rhs.free_temps(code)
3592 3593 3594 3595 3596
        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
3597
        else:
3598 3599 3600 3601 3602
            if (self.obj.type.is_extension_type
                  and self.needs_none_check
                  and code.globalstate.directives['nonecheck']):
                self.put_nonecheck(code)

3603
            select_code = self.result()
3604
            if self.type.is_pyobject and self.use_managed_ref:
William Stein's avatar
William Stein committed
3605
                rhs.make_owned_reference(code)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3606
                code.put_giveref(rhs.py_result())
3607
                code.put_gotref(select_code)
William Stein's avatar
William Stein committed
3608 3609 3610 3611
                code.put_decref(select_code, self.ctype())
            code.putln(
                "%s = %s;" % (
                    select_code,
3612
                    rhs.result_as(self.ctype())))
3613
                    #rhs.result()))
William Stein's avatar
William Stein committed
3614
            rhs.generate_post_assignment_code(code)
3615
            rhs.free_temps(code)
William Stein's avatar
William Stein committed
3616
        self.obj.generate_disposal_code(code)
3617
        self.obj.free_temps(code)
William Stein's avatar
William Stein committed
3618 3619
    
    def generate_deletion_code(self, code):
3620
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3621
        self.obj.generate_evaluation_code(code)
3622
        if self.is_py_attr or (isinstance(self.entry.scope, Symtab.PropertyScope)
3623
                               and u'__del__' in self.entry.scope.entries):
3624 3625 3626
            code.put_error_if_neg(self.pos,
                'PyObject_DelAttr(%s, %s)' % (
                    self.obj.py_result(),
3627
                    interned_attr_cname))
William Stein's avatar
William Stein committed
3628 3629 3630
        else:
            error(self.pos, "Cannot delete C attribute of extension type")
        self.obj.generate_disposal_code(code)
3631
        self.obj.free_temps(code)
3632 3633 3634 3635 3636 3637
        
    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
3638

3639 3640 3641
    def put_nonecheck(self, code):
        code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
        code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
Stefan Behnel's avatar
Stefan Behnel committed
3642
        code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3643 3644 3645 3646
        code.putln(code.error_goto(self.pos))
        code.putln("}")


William Stein's avatar
William Stein committed
3647 3648 3649 3650 3651 3652
#-------------------------------------------------------------------
#
#  Constructor nodes
#
#-------------------------------------------------------------------

3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667
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
3668
    is_temp = 1
3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696

    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


3697
class SequenceNode(ExprNode):
William Stein's avatar
William Stein committed
3698 3699 3700 3701
    #  Base class for list and tuple constructor nodes.
    #  Contains common code for performing sequence unpacking.
    #
    #  args                    [ExprNode]
3702
    #  iterator                ExprNode
William Stein's avatar
William Stein committed
3703 3704 3705 3706 3707 3708 3709
    #  unpacked_items          [ExprNode] or None
    #  coerced_unpacked_items  [ExprNode] or None
    
    subexprs = ['args']
    
    is_sequence_constructor = 1
    unpacked_items = None
3710

3711 3712 3713
    def compile_time_value_list(self, denv):
        return [arg.compile_time_value(denv) for arg in self.args]

3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727
    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
3728
    def analyse_target_declaration(self, env):
3729
        self.replace_starred_target_node()
William Stein's avatar
William Stein committed
3730 3731 3732
        for arg in self.args:
            arg.analyse_target_declaration(env)

3733
    def analyse_types(self, env, skip_children=False):
William Stein's avatar
William Stein committed
3734 3735
        for i in range(len(self.args)):
            arg = self.args[i]
3736
            if not skip_children: arg.analyse_types(env)
William Stein's avatar
William Stein committed
3737 3738
            self.args[i] = arg.coerce_to_pyobject(env)
        self.is_temp = 1
Stefan Behnel's avatar
Stefan Behnel committed
3739
        # not setting self.type here, subtypes do this
3740

3741 3742 3743
    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
3744
    def analyse_target_types(self, env):
3745 3746
        self.iterator = PyTempNode(self.pos, env)
        self.unpacked_items = []
William Stein's avatar
William Stein committed
3747 3748 3749
        self.coerced_unpacked_items = []
        for arg in self.args:
            arg.analyse_target_types(env)
3750 3751 3752 3753 3754 3755
            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
3756 3757 3758 3759 3760
            unpacked_item = PyTempNode(self.pos, env)
            coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
            self.unpacked_items.append(unpacked_item)
            self.coerced_unpacked_items.append(coerced_unpacked_item)
        self.type = py_object_type
3761

William Stein's avatar
William Stein committed
3762 3763 3764 3765
    def generate_result_code(self, code):
        self.generate_operation_code(code)
    
    def generate_assignment_code(self, rhs, code):
3766 3767 3768
        if self.starred_assignment:
            self.generate_starred_assignment_code(rhs, code)
        else:
3769
            self.generate_parallel_assignment_code(rhs, code)
3770 3771 3772 3773 3774

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

3775
    def generate_parallel_assignment_code(self, rhs, code):
3776 3777 3778 3779
        # 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.

3780 3781 3782 3783
        if rhs.type is tuple_type:
            tuple_check = "likely(%s != Py_None)"
        else:
            tuple_check = "PyTuple_CheckExact(%s)"
Robert Bradshaw's avatar
Robert Bradshaw committed
3784
        code.putln(
3785 3786
            "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
                tuple_check % rhs.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
3787 3788
                rhs.py_result(), 
                len(self.args)))
Stefan Behnel's avatar
Stefan Behnel committed
3789
        code.putln("PyObject* tuple = %s;" % rhs.py_result())
3790 3791
        for item in self.unpacked_items:
            item.allocate(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3792 3793
        for i in range(len(self.args)):
            item = self.unpacked_items[i]
3794 3795
            code.put(
                "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3796
                    item.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3797
                    i))
3798
            code.put_incref(item.result(), item.ctype())
3799 3800
            value_node = self.coerced_unpacked_items[i]
            value_node.generate_evaluation_code(code)
3801
        rhs.generate_disposal_code(code)
3802

3803 3804 3805 3806
        for i in range(len(self.args)):
            self.args[i].generate_assignment_code(
                self.coerced_unpacked_items[i], code)
                 
3807
        code.putln("} else {")
Robert Bradshaw's avatar
Robert Bradshaw committed
3808

3809
        if rhs.type is tuple_type:
3810 3811 3812 3813
            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))
3814
        else:
3815 3816
            code.globalstate.use_utility_code(unpacking_utility_code)

3817
            self.iterator.allocate(code)
3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836
            code.putln(
                "%s = PyObject_GetIter(%s); %s" % (
                    self.iterator.result(),
                    rhs.py_result(),
                    code.error_goto_if_null(self.iterator.result(), self.pos)))
            code.put_gotref(self.iterator.py_result())
            rhs.generate_disposal_code(code)
            for i in range(len(self.args)):
                item = self.unpacked_items[i]
                unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
                    self.iterator.py_result(), i)
                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)
3837 3838 3839
            code.put_error_if_neg(self.pos, "__Pyx_EndUnpack(%s, %d)" % (
                self.iterator.py_result(),
                len(self.args)))
3840 3841 3842 3843 3844
            if debug_disposal_code:
                print("UnpackNode.generate_assignment_code:")
                print("...generating disposal code for %s" % self.iterator)
            self.iterator.generate_disposal_code(code)
            self.iterator.free_temps(code)
3845
            self.iterator.release(code)
3846 3847 3848 3849

            for i in range(len(self.args)):
                self.args[i].generate_assignment_code(
                    self.coerced_unpacked_items[i], code)
William Stein's avatar
William Stein committed
3850

3851
        code.putln("}")
3852 3853

    def generate_starred_assignment_code(self, rhs, code):
3854 3855
        code.globalstate.use_utility_code(unpacking_utility_code)

3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871
        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

        self.iterator.allocate(code)
        code.putln(
            "%s = PyObject_GetIter(%s); %s" % (
                self.iterator.result(),
                rhs.py_result(),
                code.error_goto_if_null(self.iterator.result(), self.pos)))
        code.put_gotref(self.iterator.py_result())
        rhs.generate_disposal_code(code)

3872
        for item in self.unpacked_items:
3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907
            item.allocate(code)
        for i in range(len(fixed_args_left)):
            item = self.unpacked_items[i]
            unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
                self.iterator.py_result(), i)
            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" % (
            target_list, self.iterator.py_result(),
            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
3908
                code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919
                code.put_gotref(arg.py_result())
                coerced_arg.generate_evaluation_code(code)

        self.iterator.generate_disposal_code(code)
        self.iterator.free_temps(code)
        self.iterator.release(code)

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

3920 3921 3922 3923 3924 3925 3926 3927
    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
3928 3929 3930 3931


class TupleNode(SequenceNode):
    #  Tuple constructor.
3932 3933
    
    type = tuple_type
3934 3935 3936

    gil_message = "Constructing Python tuple"

3937
    def analyse_types(self, env, skip_children=False):
Robert Bradshaw's avatar
Robert Bradshaw committed
3938 3939
        if len(self.args) == 0:
            self.is_temp = 0
3940
            self.is_literal = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3941
        else:
3942
            SequenceNode.analyse_types(self, env, skip_children)
3943 3944 3945 3946 3947 3948
            for child in self.args:
                if not child.is_literal:
                    break
            else:
                self.is_temp = 0
                self.is_literal = 1
3949

Robert Bradshaw's avatar
Robert Bradshaw committed
3950 3951
    def calculate_result_code(self):
        if len(self.args) > 0:
3952
            return self.result_code
Robert Bradshaw's avatar
Robert Bradshaw committed
3953 3954
        else:
            return Naming.empty_tuple
William Stein's avatar
William Stein committed
3955

3956 3957 3958 3959
    def calculate_constant_result(self):
        self.constant_result = tuple([
                arg.constant_result for arg in self.args])

3960 3961 3962 3963 3964 3965 3966
    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)
    
William Stein's avatar
William Stein committed
3967
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3968 3969 3970
        if len(self.args) == 0:
            # result_code is Naming.empty_tuple
            return
3971 3972 3973
        if self.is_literal:
            # non-empty cached tuple => result is global constant,
            # creation code goes into separate code writer
3974
            self.result_code = code.get_py_const(py_object_type, 'tuple_', cleanup_level=2)
3975 3976 3977
            code = code.get_cached_constants_writer()
            code.mark_pos(self.pos)

William Stein's avatar
William Stein committed
3978
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3979
            "%s = PyTuple_New(%s); %s" % (
3980
                self.result(),
William Stein's avatar
William Stein committed
3981
                len(self.args),
3982
                code.error_goto_if_null(self.result(), self.pos)))
3983
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3984 3985 3986
        for i in range(len(self.args)):
            arg = self.args[i]
            if not arg.result_in_temp():
3987
                code.put_incref(arg.result(), arg.ctype())
William Stein's avatar
William Stein committed
3988 3989
            code.putln(
                "PyTuple_SET_ITEM(%s, %s, %s);" % (
3990
                    self.result(),
William Stein's avatar
William Stein committed
3991 3992
                    i,
                    arg.py_result()))
3993
            code.put_giveref(arg.py_result())
3994 3995
        if self.is_literal:
            code.put_giveref(self.py_result())
William Stein's avatar
William Stein committed
3996 3997 3998 3999 4000 4001
    
    def generate_subexpr_disposal_code(self, code):
        # 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:
4002 4003 4004
            arg.generate_post_assignment_code(code)
            # Should NOT call free_temps -- this is invoked by the default
            # generate_evaluation_code which will do that.
William Stein's avatar
William Stein committed
4005 4006 4007 4008


class ListNode(SequenceNode):
    #  List constructor.
4009 4010 4011
    
    # obj_conversion_errors    [PyrexError]   used internally
    # orignial_args            [ExprNode]     used internally
4012

4013
    obj_conversion_errors = []
Stefan Behnel's avatar
Stefan Behnel committed
4014
    type = list_type
4015

4016
    gil_message = "Constructing Python list"
4017
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4018
    def type_dependencies(self, env):
4019 4020 4021 4022 4023
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer non-object list arrays.
        return list_type
4024

4025
    def analyse_expressions(self, env):
4026
        SequenceNode.analyse_expressions(self, env)
4027 4028
        self.coerce_to_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
4029
    def analyse_types(self, env):
4030 4031 4032 4033 4034
        hold_errors()
        self.original_args = list(self.args)
        SequenceNode.analyse_types(self, env)
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
Robert Bradshaw's avatar
Robert Bradshaw committed
4035 4036 4037
        
    def coerce_to(self, dst_type, env):
        if dst_type.is_pyobject:
4038 4039 4040
            for err in self.obj_conversion_errors:
                report_error(err)
            self.obj_conversion_errors = []
Robert Bradshaw's avatar
Robert Bradshaw committed
4041 4042 4043 4044
            if not self.type.subtype_of(dst_type):
                error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
        elif dst_type.is_ptr:
            base_type = dst_type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4045
            self.type = PyrexTypes.CArrayType(base_type, len(self.args))
4046
            for i in range(len(self.original_args)):
Robert Bradshaw's avatar
Robert Bradshaw committed
4047
                arg = self.args[i]
4048 4049
                if isinstance(arg, CoerceToPyTypeNode):
                    arg = arg.arg
Robert Bradshaw's avatar
Robert Bradshaw committed
4050
                self.args[i] = arg.coerce_to(base_type, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4051 4052 4053 4054 4055 4056
        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)
4057 4058 4059
                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
4060 4061
                    self.args[i] = arg.coerce_to(member.type, env)
            self.type = dst_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4062 4063 4064 4065
        else:
            self.type = error_type
            error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
4066 4067 4068 4069 4070 4071 4072 4073
        
    def release_temp(self, env):
        if self.type.is_array:
            # To be valid C++, we must allocate the memory on the stack 
            # manually and be sure not to reuse it for something else. 
            pass
        else:
            SequenceNode.release_temp(self, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4074

4075 4076 4077 4078
    def calculate_constant_result(self):
        self.constant_result = [
            arg.constant_result for arg in self.args]

4079 4080 4081
    def compile_time_value(self, denv):
        return self.compile_time_value_list(denv)

William Stein's avatar
William Stein committed
4082
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4083
        if self.type.is_pyobject:
4084 4085
            for err in self.obj_conversion_errors:
                report_error(err)
Robert Bradshaw's avatar
Robert Bradshaw committed
4086
            code.putln("%s = PyList_New(%s); %s" %
4087
                (self.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
4088 4089
                len(self.args),
                code.error_goto_if_null(self.result(), self.pos)))
4090
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
4091 4092 4093 4094 4095 4096 4097 4098 4099
            for i in range(len(self.args)):
                arg = self.args[i]
                #if not arg.is_temp:
                if not arg.result_in_temp():
                    code.put_incref(arg.result(), arg.ctype())
                code.putln("PyList_SET_ITEM(%s, %s, %s);" %
                    (self.result(),
                    i,
                    arg.py_result()))
4100
                code.put_giveref(arg.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
4101 4102 4103 4104 4105 4106
        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
4107
        elif self.type.is_struct:
Robert Bradshaw's avatar
Robert Bradshaw committed
4108 4109 4110 4111 4112
            for arg, member in zip(self.args, self.type.scope.var_entries):
                code.putln("%s.%s = %s;" % (
                        self.result(),
                        member.cname,
                        arg.result()))
4113 4114
        else:
            raise InternalError("List type never specified")
4115

William Stein's avatar
William Stein committed
4116 4117 4118 4119 4120
    def generate_subexpr_disposal_code(self, code):
        # We call generate_post_assignment_code here instead
        # of generate_disposal_code, because values were stored
        # in the list using a reference-stealing operation.
        for arg in self.args:
4121 4122 4123
            arg.generate_post_assignment_code(code)
            # Should NOT call free_temps -- this is invoked by the default
            # generate_evaluation_code which will do that.
William Stein's avatar
William Stein committed
4124

Robert Bradshaw's avatar
Robert Bradshaw committed
4125

4126 4127 4128 4129 4130 4131 4132 4133 4134
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

4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153
    # 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
4154 4155
        pass

4156 4157
    def analyse_types(self, env):
        # no recursion here, the children will be analysed separately below
4158 4159 4160 4161 4162 4163
        pass

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

4164 4165

class ComprehensionNode(ScopedExprNode):
4166
    subexprs = ["target"]
4167 4168
    child_attrs = ["loop", "append"]

4169 4170
    def infer_type(self, env):
        return self.target.infer_type(env)
4171 4172 4173

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

4176 4177
    def analyse_scoped_declarations(self, env):
        self.loop.analyse_declarations(env)
4178

4179 4180 4181
    def analyse_types(self, env):
        self.target.analyse_expressions(env)
        self.type = self.target.type
4182 4183
        if not self.has_local_scope:
            self.loop.analyse_expressions(env)
4184

4185 4186 4187
    def analyse_scoped_expressions(self, env):
        if self.has_local_scope:
            self.loop.analyse_expressions(env)
4188

4189 4190 4191
    def may_be_none(self):
        return False

4192 4193 4194 4195 4196
    def calculate_result_code(self):
        return self.target.result()
    
    def generate_result_code(self, code):
        self.generate_operation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4197

4198 4199 4200
    def generate_operation_code(self, code):
        self.loop.generate_execution_code(code)

4201 4202
    def annotate(self, code):
        self.loop.annotate(code)
4203 4204


4205
class ComprehensionAppendNode(Node):
4206 4207
    # Need to be careful to avoid infinite recursion:
    # target must not be in child_attrs/subexprs
4208 4209

    child_attrs = ['expr']
4210 4211

    type = PyrexTypes.c_int_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4212
    
4213 4214
    def analyse_expressions(self, env):
        self.expr.analyse_expressions(env)
4215
        if not self.expr.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
4216
            self.expr = self.expr.coerce_to_pyobject(env)
4217

4218
    def generate_execution_code(self, code):
4219 4220 4221 4222 4223 4224 4225
        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)
4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240

        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)
4241 4242

class DictComprehensionAppendNode(ComprehensionAppendNode):
4243
    child_attrs = ['key_expr', 'value_expr']
4244

4245 4246
    def analyse_expressions(self, env):
        self.key_expr.analyse_expressions(env)
4247 4248
        if not self.key_expr.type.is_pyobject:
            self.key_expr = self.key_expr.coerce_to_pyobject(env)
4249
        self.value_expr.analyse_expressions(env)
4250 4251 4252
        if not self.value_expr.type.is_pyobject:
            self.value_expr = self.value_expr.coerce_to_pyobject(env)

4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272
    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)
4273 4274


4275
class GeneratorExpressionNode(ScopedExprNode):
4276 4277 4278 4279
    # A generator expression, e.g.  (i for i in range(10))
    #
    # Result is a generator.
    #
4280 4281
    # loop      ForStatNode   the for-loop, containing a YieldExprNode

4282 4283 4284 4285
    child_attrs = ["loop"]

    type = py_object_type

4286 4287
    def analyse_scoped_declarations(self, env):
        self.loop.analyse_declarations(env)
4288

4289
    def analyse_types(self, env):
4290 4291
        if not self.has_local_scope:
            self.loop.analyse_expressions(env)
4292 4293 4294
        self.is_temp = True

    def analyse_scoped_expressions(self, env):
4295 4296
        if self.has_local_scope:
            self.loop.analyse_expressions(env)
4297 4298 4299 4300 4301 4302 4303 4304

    def may_be_none(self):
        return False

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


4305 4306
class InlinedGeneratorExpressionNode(GeneratorExpressionNode):
    # An inlined generator expression for which the result is
4307 4308 4309
    # calculated inside of the loop.  This will only be created by
    # transforms when replacing builtin calls on generator
    # expressions.
4310 4311 4312
    #
    # loop           ForStatNode      the for-loop, not containing any YieldExprNodes
    # result_node    ResultRefNode    the reference to the result value temp
4313
    # orig_func      String           the name of the builtin function this node replaces
4314 4315

    child_attrs = ["loop"]
4316 4317 4318 4319
    loop_analysed = False

    def infer_type(self, env):
        return self.result_node.infer_type(env)
4320 4321

    def analyse_types(self, env):
4322 4323 4324
        if not self.has_local_scope:
            self.loop_analysed = True
            self.loop.analyse_expressions(env)
4325 4326 4327
        self.type = self.result_node.type
        self.is_temp = True

4328 4329 4330 4331
    def analyse_scoped_expressions(self, env):
        self.loop_analysed = True
        GeneratorExpressionNode.analyse_scoped_expressions(self, env)

4332
    def coerce_to(self, dst_type, env):
4333 4334 4335 4336 4337 4338
        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.
4339 4340 4341 4342
            self.result_node.type = self.type = dst_type
            return self
        return GeneratorExpressionNode.coerce_to(self, dst_type, env)

4343 4344 4345 4346 4347
    def generate_result_code(self, code):
        self.result_node.result_code = self.result()
        self.loop.generate_execution_code(code)


4348
class SetNode(ExprNode):
4349 4350
    #  Set constructor.

4351 4352
    type = set_type

4353 4354 4355
    subexprs = ['args']

    gil_message = "Constructing Python set"
4356
    
4357 4358 4359 4360 4361 4362 4363 4364
    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

4365 4366 4367
    def may_be_none(self):
        return False

4368 4369 4370 4371
    def calculate_constant_result(self):
        self.constant_result = set([
                arg.constant_result for arg in self.args])

4372 4373 4374 4375 4376 4377 4378 4379
    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):
4380
        code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
4381 4382 4383 4384 4385
        self.allocate_temp_result(code)
        code.putln(
            "%s = PySet_New(0); %s" % (
                self.result(),
                code.error_goto_if_null(self.result(), self.pos)))
4386
        code.put_gotref(self.py_result())
4387 4388 4389 4390 4391 4392 4393 4394
        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
4395

William Stein's avatar
William Stein committed
4396

4397
class DictNode(ExprNode):
William Stein's avatar
William Stein committed
4398 4399
    #  Dictionary constructor.
    #
4400
    #  key_value_pairs  [DictItemNode]
4401 4402
    #
    # obj_conversion_errors    [PyrexError]   used internally
4403 4404
    
    subexprs = ['key_value_pairs']
4405 4406
    is_temp = 1
    type = dict_type
4407

4408
    obj_conversion_errors = []
4409 4410 4411 4412

    def calculate_constant_result(self):
        self.constant_result = dict([
                item.constant_result for item in self.key_value_pairs])
William Stein's avatar
William Stein committed
4413
    
4414
    def compile_time_value(self, denv):
Robert Bradshaw's avatar
Robert Bradshaw committed
4415 4416
        pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
            for item in self.key_value_pairs]
4417 4418 4419 4420 4421
        try:
            return dict(pairs)
        except Exception, e:
            self.compile_time_value_error(e)
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4422
    def type_dependencies(self, env):
4423 4424 4425 4426 4427 4428
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer struct constructors.
        return dict_type

William Stein's avatar
William Stein committed
4429
    def analyse_types(self, env):
4430
        hold_errors()
Robert Bradshaw's avatar
Robert Bradshaw committed
4431 4432
        for item in self.key_value_pairs:
            item.analyse_types(env)
4433 4434
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
4435 4436 4437

    def may_be_none(self):
        return False
4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452
        
    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
4453
                if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
4454
                    error(item.key.pos, "Invalid struct field identifier")
4455
                    item.key = StringNode(item.key.pos, value="<error>")
4456
                else:
Stefan Behnel's avatar
Stefan Behnel committed
4457 4458
                    key = str(item.key.value) # converts string literals to unicode in Py3
                    member = dst_type.scope.lookup_here(key)
4459
                    if not member:
Stefan Behnel's avatar
Stefan Behnel committed
4460
                        error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474
                    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
    
    def release_errors(self):
        for err in self.obj_conversion_errors:
            report_error(err)
        self.obj_conversion_errors = []
4475 4476 4477

    gil_message = "Constructing Python dict"

William Stein's avatar
William Stein committed
4478 4479 4480
    def generate_evaluation_code(self, code):
        #  Custom method used here because key-value
        #  pairs are evaluated and used one at a time.
4481 4482
        code.mark_pos(self.pos)
        self.allocate_temp_result(code)
4483 4484 4485 4486 4487 4488
        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)))
4489
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
4490 4491
        for item in self.key_value_pairs:
            item.generate_evaluation_code(code)
4492 4493 4494 4495 4496 4497 4498 4499 4500
            if self.type.is_pyobject:
                code.put_error_if_neg(self.pos, 
                    "PyDict_SetItem(%s, %s, %s)" % (
                        self.result(),
                        item.key.py_result(),
                        item.value.py_result()))
            else:
                code.putln("%s.%s = %s;" % (
                        self.result(),
4501
                        item.key.value,
4502
                        item.value.result()))
Robert Bradshaw's avatar
Robert Bradshaw committed
4503
            item.generate_disposal_code(code)
4504
            item.free_temps(code)
4505 4506
            
    def annotate(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4507 4508 4509
        for item in self.key_value_pairs:
            item.annotate(code)
            
4510
class DictItemNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
4511 4512 4513 4514 4515
    # Represents a single item in a DictNode
    #
    # key          ExprNode
    # value        ExprNode
    subexprs = ['key', 'value']
4516

4517
    nogil_check = None # Parent DictNode takes care of it
4518

4519 4520 4521
    def calculate_constant_result(self):
        self.constant_result = (
            self.key.constant_result, self.value.constant_result)
Robert Bradshaw's avatar
Robert Bradshaw committed
4522 4523 4524 4525 4526 4527 4528 4529 4530 4531
            
    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)
        
    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
4532

4533 4534 4535
    def generate_disposal_code(self, code):
        self.key.generate_disposal_code(code)
        self.value.generate_disposal_code(code)
4536 4537 4538 4539

    def free_temps(self, code):
        self.key.free_temps(code)
        self.value.free_temps(code)
4540 4541 4542
        
    def __iter__(self):
        return iter([self.key, self.value])
William Stein's avatar
William Stein committed
4543

4544 4545 4546 4547 4548 4549 4550
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
4551

4552
class ClassNode(ExprNode, ModuleNameMixin):
William Stein's avatar
William Stein committed
4553 4554 4555 4556
    #  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
4557
    #  name         EncodedString      Name of the class
William Stein's avatar
William Stein committed
4558 4559 4560
    #  bases        ExprNode           Base class tuple
    #  dict         ExprNode           Class dict (not owned by this node)
    #  doc          ExprNode or None   Doc string
4561
    #  module_name  EncodedString      Name of defining module
William Stein's avatar
William Stein committed
4562
    
4563
    subexprs = ['bases', 'doc']
4564

William Stein's avatar
William Stein committed
4565 4566 4567 4568 4569 4570 4571 4572
    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);
4573 4574
        #TODO(craig,haoyu) This should be moved to a better place
        self.set_mod_name(env)
4575

4576
    def may_be_none(self):
Stefan Behnel's avatar
Stefan Behnel committed
4577
        return True
4578

4579 4580
    gil_message = "Constructing Python class"

William Stein's avatar
William Stein committed
4581
    def generate_result_code(self, code):
4582
        cname = code.intern_identifier(self.name)
4583

William Stein's avatar
William Stein committed
4584
        if self.doc:
Robert Bradshaw's avatar
Robert Bradshaw committed
4585 4586
            code.put_error_if_neg(self.pos, 
                'PyDict_SetItemString(%s, "__doc__", %s)' % (
William Stein's avatar
William Stein committed
4587
                    self.dict.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
4588
                    self.doc.py_result()))
4589
        py_mod_name = self.get_py_mod_name(code)
William Stein's avatar
William Stein committed
4590
        code.putln(
4591
            '%s = __Pyx_CreateClass(%s, %s, %s, %s); %s' % (
4592
                self.result(),
William Stein's avatar
William Stein committed
4593 4594
                self.bases.py_result(),
                self.dict.py_result(),
4595
                cname,
4596
                py_mod_name,
4597
                code.error_goto_if_null(self.result(), self.pos)))
4598
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4599

Stefan Behnel's avatar
Stefan Behnel committed
4600

4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618
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

4619
    gil_message = "Constructing Python class"
4620 4621

    def generate_result_code(self, code):
4622
        code.globalstate.use_utility_code(create_py3class_utility_code)
4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670
        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):
    # Helper class for keyword arguments
    #
    # keyword_args ExprNode or None     Keyword arguments
    # starstar_arg ExprNode or None     Extra arguments

    subexprs = ['keyword_args', 'starstar_arg']

    def analyse_types(self, env):
        if self.keyword_args:
            self.keyword_args.analyse_types(env)
        if self.starstar_arg:
            self.starstar_arg.analyse_types(env)
            # make sure we have a Python object as **kwargs mapping
            self.starstar_arg = \
                self.starstar_arg.coerce_to_pyobject(env)
        self.type = py_object_type
        self.is_temp = 1

    gil_message = "Constructing Keyword Args"

    def generate_result_code(self, code):
        if self.keyword_args and self.starstar_arg:
            code.put_error_if_neg(self.pos,
                "PyDict_Update(%s, %s)" % (
                    self.keyword_args.py_result(),
                    self.starstar_arg.py_result()))
        if self.keyword_args:
            code.putln("%s = %s;" % (self.result(), self.keyword_args.result()))
            code.put_incref(self.keyword_args.result(), self.keyword_args.ctype())
        elif self.starstar_arg:
            code.putln(
                "%s = PyDict_Copy(%s); %s" % (
                    self.result(),
                    self.starstar_arg.py_result(),
                    code.error_goto_if_null(self.result(), self.pos)))
4671
            code.put_gotref(self.py_result())
4672 4673 4674 4675 4676
        else:
            code.putln(
                "%s = PyDict_New(); %s" % (
                    self.result(),
                    code.error_goto_if_null(self.result(), self.pos)))
4677
            code.put_gotref(self.py_result())
4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745

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
4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771
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
    
    subexprs = ['function']
    
    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
4772

4773
class UnboundMethodNode(ExprNode):
William Stein's avatar
William Stein committed
4774 4775 4776 4777 4778 4779
    #  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
    
4780 4781 4782
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4783 4784 4785 4786
    subexprs = ['function']
    
    def analyse_types(self, env):
        self.function.analyse_types(env)
4787

4788 4789 4790
    def may_be_none(self):
        return False

4791 4792
    gil_message = "Constructing an unbound method"

William Stein's avatar
William Stein committed
4793
    def generate_result_code(self, code):
4794
        class_cname = code.pyclass_stack[-1].classobj.result()
William Stein's avatar
William Stein committed
4795
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4796
            "%s = PyMethod_New(%s, 0, %s); %s" % (
4797
                self.result(),
William Stein's avatar
William Stein committed
4798
                self.function.py_result(),
4799
                class_cname,
4800
                code.error_goto_if_null(self.result(), self.pos)))
4801
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4802

Robert Bradshaw's avatar
Robert Bradshaw committed
4803

4804
class PyCFunctionNode(ExprNode, ModuleNameMixin):
William Stein's avatar
William Stein committed
4805 4806 4807 4808
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs a PyCFunction object
    #  from a PyMethodDef struct.
    #
4809
    #  pymethdef_cname   string             PyMethodDef structure
Robert Bradshaw's avatar
Robert Bradshaw committed
4810
    #  self_object       ExprNode or None
Robert Bradshaw's avatar
Robert Bradshaw committed
4811
    #  binding           bool
4812
    #  module_name       EncodedString      Name of defining module
Stefan Behnel's avatar
Stefan Behnel committed
4813 4814

    subexprs = []
Robert Bradshaw's avatar
Robert Bradshaw committed
4815
    self_object = None
Robert Bradshaw's avatar
Robert Bradshaw committed
4816
    binding = False
William Stein's avatar
William Stein committed
4817
    
4818 4819 4820
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4821
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
4822 4823
        if self.binding:
            env.use_utility_code(binding_cfunc_utility_code)
4824

4825 4826 4827
        #TODO(craig,haoyu) This should be moved to a better place
        self.set_mod_name(env)

4828 4829
    def may_be_none(self):
        return False
4830
    
4831 4832
    gil_message = "Constructing Python function"

Stefan Behnel's avatar
Stefan Behnel committed
4833
    def self_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4834 4835 4836 4837
        if self.self_object is None:
            self_result = "NULL"
        else:
            self_result = self.self_object.py_result()
Stefan Behnel's avatar
Stefan Behnel committed
4838 4839 4840
        return self_result

    def generate_result_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4841
        if self.binding:
4842
            constructor = "%s_NewEx" % Naming.binding_cfunc
Robert Bradshaw's avatar
Robert Bradshaw committed
4843
        else:
4844 4845
            constructor = "PyCFunction_NewEx"
        py_mod_name = self.get_py_mod_name(code)
William Stein's avatar
William Stein committed
4846
        code.putln(
4847
            '%s = %s(&%s, %s, %s); %s' % (
4848
                self.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
4849
                constructor,
William Stein's avatar
William Stein committed
4850
                self.pymethdef_cname,
Stefan Behnel's avatar
Stefan Behnel committed
4851
                self.self_result_code(),
4852
                py_mod_name,
4853
                code.error_goto_if_null(self.result(), self.pos)))
4854
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4855

Stefan Behnel's avatar
Stefan Behnel committed
4856 4857 4858
class InnerFunctionNode(PyCFunctionNode):
    # Special PyCFunctionNode that depends on a closure class
    #
Vitja Makarov's avatar
Vitja Makarov committed
4859

Robert Bradshaw's avatar
Robert Bradshaw committed
4860
    binding = True
Vitja Makarov's avatar
Vitja Makarov committed
4861 4862
    needs_self_code = True

Stefan Behnel's avatar
Stefan Behnel committed
4863
    def self_result_code(self):
Vitja Makarov's avatar
Vitja Makarov committed
4864 4865 4866
        if self.needs_self_code:
            return "((PyObject*)%s)" % (Naming.cur_scope_cname)
        return "NULL"
Stefan Behnel's avatar
Stefan Behnel committed
4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887

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):
        self.def_node.analyse_declarations(env)
        self.pymethdef_cname = self.def_node.entry.pymethdef_cname
        env.add_lambda_def(self.def_node)

4888 4889 4890 4891 4892 4893
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

4894
    subexprs = ['arg']
4895 4896 4897 4898 4899 4900 4901 4902
    type = py_object_type

    def analyse_types(self, env):
        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)
4903
        error(self.pos, "Generators are not supported")
4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914

    def generate_result_code(self, code):
        self.label_name = code.new_label('resume_from_yield')
        code.use_label(self.label_name)
        code.putln("/* FIXME: save temporary variables */")
        code.putln("/* FIXME: return from function, yielding value */")
        code.put_label(self.label_name)
        code.putln("/* FIXME: restore temporary variables and  */")
        code.putln("/* FIXME: extract sent value from closure */")


William Stein's avatar
William Stein committed
4915 4916 4917 4918 4919 4920
#-------------------------------------------------------------------
#
#  Unary operator nodes
#
#-------------------------------------------------------------------

4921 4922 4923 4924 4925 4926 4927
compile_time_unary_operators = {
    'not': operator.not_,
    '~': operator.inv,
    '-': operator.neg,
    '+': operator.pos,
}

4928
class UnopNode(ExprNode):
William Stein's avatar
William Stein committed
4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940
    #  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.
    
    subexprs = ['operand']
Robert Bradshaw's avatar
Robert Bradshaw committed
4941
    infix = True
4942 4943 4944 4945

    def calculate_constant_result(self):
        func = compile_time_unary_operators[self.operator]
        self.constant_result = func(self.operand.constant_result)
William Stein's avatar
William Stein committed
4946
    
4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957
    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)
4958 4959
    
    def infer_type(self, env):
4960 4961 4962 4963 4964
        operand_type = self.operand.infer_type(env)
        if operand_type.is_pyobject:
            return py_object_type
        else:
            return operand_type
4965

William Stein's avatar
William Stein committed
4966 4967 4968 4969 4970 4971
    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
4972 4973
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
4974 4975 4976 4977
        else:
            self.analyse_c_operation(env)
    
    def check_const(self):
4978
        return self.operand.check_const()
William Stein's avatar
William Stein committed
4979 4980 4981
    
    def is_py_operation(self):
        return self.operand.type.is_pyobject
4982

4983
    def nogil_check(self, env):
4984
        if self.is_py_operation():
4985
            self.gil_error()
4986

Danilo Freitas's avatar
Danilo Freitas committed
4987
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4988
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
4989
        return type.is_cpp_class
William Stein's avatar
William Stein committed
4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000
    
    def coerce_operand_to_pyobject(self, env):
        self.operand = self.operand.coerce_to_pyobject(env)
    
    def generate_result_code(self, code):
        if self.operand.type.is_pyobject:
            self.generate_py_operation_code(code)
    
    def generate_py_operation_code(self, code):
        function = self.py_operation_function()
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
5001
            "%s = %s(%s); %s" % (
5002
                self.result(), 
William Stein's avatar
William Stein committed
5003 5004
                function, 
                self.operand.py_result(),
5005
                code.error_goto_if_null(self.result(), self.pos)))
5006
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5007 5008 5009 5010 5011 5012 5013
        
    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
5014
    def analyse_cpp_operation(self, env):
5015
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
5016
        if type.is_ptr:
Danilo Freitas's avatar
Danilo Freitas committed
5017
            type = type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
5018
        function = type.scope.lookup("operator%s" % self.operator)
Danilo Freitas's avatar
Danilo Freitas committed
5019 5020
        if not function:
            error(self.pos, "'%s' operator not defined for %s"
5021
                % (self.operator, type))
Danilo Freitas's avatar
Danilo Freitas committed
5022 5023
            self.type_error()
            return
5024 5025 5026 5027
        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
5028

William Stein's avatar
William Stein committed
5029

5030
class NotNode(ExprNode):
William Stein's avatar
William Stein committed
5031 5032 5033
    #  'not' operator
    #
    #  operand   ExprNode
5034 5035
    
    type = PyrexTypes.c_bint_type
5036

5037 5038
    subexprs = ['operand']
    
5039 5040 5041
    def calculate_constant_result(self):
        self.constant_result = not self.operand.constant_result

5042 5043 5044 5045 5046 5047 5048
    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)

5049 5050
    def infer_type(self, env):
        return PyrexTypes.c_bint_type
William Stein's avatar
William Stein committed
5051 5052 5053 5054 5055 5056
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
        self.operand = self.operand.coerce_to_boolean(env)
    
    def calculate_result_code(self):
5057
        return "(!%s)" % self.operand.result()
William Stein's avatar
William Stein committed
5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074
    
    def generate_result_code(self, code):
        pass


class UnaryPlusNode(UnopNode):
    #  unary '+' operator
    
    operator = '+'
    
    def analyse_c_operation(self, env):
        self.type = self.operand.type
    
    def py_operation_function(self):
        return "PyNumber_Positive"
    
    def calculate_result_code(self):
5075 5076 5077 5078
        if self.is_cpp_operation():
            return "(+%s)" % self.operand.result()
        else:
            return self.operand.result()
William Stein's avatar
William Stein committed
5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090


class UnaryMinusNode(UnopNode):
    #  unary '-' operator
    
    operator = '-'
    
    def analyse_c_operation(self, env):
        if self.operand.type.is_numeric:
            self.type = self.operand.type
        else:
            self.type_error()
Robert Bradshaw's avatar
Robert Bradshaw committed
5091
        if self.type.is_complex:
5092
            self.infix = False
William Stein's avatar
William Stein committed
5093 5094 5095 5096 5097
    
    def py_operation_function(self):
        return "PyNumber_Negative"
    
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5098 5099 5100 5101
        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
5102

5103 5104 5105 5106 5107
    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
5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120
class TildeNode(UnopNode):
    #  unary '~' operator

    def analyse_c_operation(self, env):
        if self.operand.type.is_int:
            self.type = self.operand.type
        else:
            self.type_error()

    def py_operation_function(self):
        return "PyNumber_Invert"
    
    def calculate_result_code(self):
5121
        return "(~%s)" % self.operand.result()
William Stein's avatar
William Stein committed
5122 5123


5124 5125
class CUnopNode(UnopNode):

Robert Bradshaw's avatar
Robert Bradshaw committed
5126 5127 5128
    def is_py_operation(self):
        return False

5129 5130
class DereferenceNode(CUnopNode):
    #  unary * operator
5131 5132

    operator = '*'
5133
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5134 5135 5136 5137 5138 5139 5140 5141
    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
5142 5143


5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162
class DecrementIncrementNode(CUnopNode):
    #  unary ++/-- operator
    
    def analyse_c_operation(self, env):
        if self.operand.type.is_ptr or self.operand.type.is_numeric:
            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)


5163
class AmpersandNode(ExprNode):
William Stein's avatar
William Stein committed
5164 5165 5166 5167 5168
    #  The C address-of operator.
    #
    #  operand  ExprNode
    
    subexprs = ['operand']
5169 5170 5171
    
    def infer_type(self, env):
        return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
William Stein's avatar
William Stein committed
5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184

    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)
    
    def check_const(self):
5185
        return self.operand.check_const_addr()
William Stein's avatar
William Stein committed
5186 5187 5188 5189 5190 5191 5192
    
    def error(self, mess):
        error(self.pos, mess)
        self.type = PyrexTypes.error_type
        self.result_code = "<error>"
    
    def calculate_result_code(self):
5193
        return "(&%s)" % self.operand.result()
William Stein's avatar
William Stein committed
5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207

    def generate_result_code(self, code):
        pass
    

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

def unop_node(pos, operator, operand):
    # Construct unnop node of appropriate class for 
    # given operator.
5208
    if isinstance(operand, IntNode) and operator == '-':
5209
        return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)))
Robert Bradshaw's avatar
Robert Bradshaw committed
5210 5211
    elif isinstance(operand, UnopNode) and operand.operator == operator:
        warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
William Stein's avatar
William Stein committed
5212 5213 5214 5215 5216
    return unop_node_classes[operator](pos, 
        operator = operator, 
        operand = operand)


5217
class TypecastNode(ExprNode):
William Stein's avatar
William Stein committed
5218 5219
    #  C type cast
    #
5220
    #  operand      ExprNode
William Stein's avatar
William Stein committed
5221 5222
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
5223 5224 5225
    #
    #  If used from a transform, one can if wanted specify the attribute
    #  "type" directly and leave base_type and declarator to None
William Stein's avatar
William Stein committed
5226 5227
    
    subexprs = ['operand']
5228
    base_type = declarator = type = None
William Stein's avatar
William Stein committed
5229
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5230
    def type_dependencies(self, env):
5231 5232
        return ()
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5233
    def infer_type(self, env):
5234 5235 5236 5237 5238
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
        return self.type
    
William Stein's avatar
William Stein committed
5239
    def analyse_types(self, env):
5240 5241 5242
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
5243 5244 5245 5246
        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
5247 5248 5249
        self.operand.analyse_types(env)
        to_py = self.type.is_pyobject
        from_py = self.operand.type.is_pyobject
5250 5251
        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
5252
        if to_py and not from_py:
5253 5254 5255 5256 5257 5258
            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
5259
                self.result_ctype = py_object_type
5260
                self.operand = self.operand.coerce_to_pyobject(env)
5261
            else:
5262 5263 5264 5265 5266
                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:
                    # Should this be an error? 
5267
                    warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
5268
                self.operand = self.operand.coerce_to_simple(env)
5269
        elif from_py and not to_py:
5270
            if self.type.create_from_py_utility_code(env):
5271
                self.operand = self.operand.coerce_to(self.type, env)
5272 5273 5274
            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")
5275 5276
            else:
                warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
5277 5278
        elif from_py and to_py:
            if self.typecheck and self.type.is_extension_type:
5279
                self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
5280 5281
        elif self.type.is_complex and self.operand.type.is_complex:
            self.operand = self.operand.coerce_to_simple(env)
5282

5283 5284 5285
    def nogil_check(self, env):
        if self.type and self.type.is_pyobject and self.is_temp:
            self.gil_error()
5286

William Stein's avatar
William Stein committed
5287
    def check_const(self):
5288
        return self.operand.check_const()
Stefan Behnel's avatar
Stefan Behnel committed
5289 5290

    def calculate_constant_result(self):
5291 5292 5293
        # we usually do not know the result of a type cast at code
        # generation time
        pass
William Stein's avatar
William Stein committed
5294 5295
    
    def calculate_result_code(self):
5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309
        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,
                    imag_part)    
        else:
            return self.type.cast_code(self.operand.result())
William Stein's avatar
William Stein committed
5310
    
5311 5312 5313 5314 5315
    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)
    
William Stein's avatar
William Stein committed
5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326
    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;" % (
5327 5328 5329
                    self.result(),
                    self.operand.result()))
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
5330 5331


5332
class SizeofNode(ExprNode):
William Stein's avatar
William Stein committed
5333
    #  Abstract base class for sizeof(x) expression nodes.
5334
    
5335
    type = PyrexTypes.c_size_t_type
William Stein's avatar
William Stein committed
5336 5337

    def check_const(self):
5338
        return True
William Stein's avatar
William Stein committed
5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350

    def generate_result_code(self, code):
        pass


class SizeofTypeNode(SizeofNode):
    #  C sizeof function applied to a type
    #
    #  base_type   CBaseTypeNode
    #  declarator  CDeclaratorNode
    
    subexprs = []
5351
    arg_type = None
William Stein's avatar
William Stein committed
5352 5353
    
    def analyse_types(self, env):
5354 5355
        # 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
5356
        if 0 and self.base_type.module_path:
5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
            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
5368 5369 5370 5371
        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
5372 5373 5374 5375
        self.check_type()
        
    def check_type(self):
        arg_type = self.arg_type
5376
        if arg_type.is_pyobject and not arg_type.is_extension_type:
William Stein's avatar
William Stein committed
5377 5378 5379 5380 5381 5382 5383
            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)
        
    def calculate_result_code(self):
5384 5385 5386 5387 5388 5389
        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
5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400
        return "(sizeof(%s))" % arg_code
    

class SizeofVarNode(SizeofNode):
    #  C sizeof function applied to a variable
    #
    #  operand   ExprNode
    
    subexprs = ['operand']
    
    def analyse_types(self, env):
5401 5402 5403 5404 5405 5406 5407 5408 5409
        # 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)
William Stein's avatar
William Stein committed
5410 5411
    
    def calculate_result_code(self):
5412
        return "(sizeof(%s))" % self.operand.result()
William Stein's avatar
William Stein committed
5413 5414 5415 5416
    
    def generate_result_code(self, code):
        pass

Robert Bradshaw's avatar
Robert Bradshaw committed
5417
class TypeofNode(ExprNode):
5418 5419 5420
    #  Compile-time type of an expression, as a string.
    #
    #  operand   ExprNode
Robert Bradshaw's avatar
Robert Bradshaw committed
5421
    #  literal   StringNode # internal
5422
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5423 5424 5425
    literal = None
    type = py_object_type
    
Stefan Behnel's avatar
Stefan Behnel committed
5426
    subexprs = ['literal'] # 'operand' will be ignored after type analysis!
5427 5428 5429
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
5430 5431
        self.literal = StringNode(
            self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
Robert Bradshaw's avatar
Robert Bradshaw committed
5432 5433
        self.literal.analyse_types(env)
        self.literal = self.literal.coerce_to_pyobject(env)
5434 5435 5436 5437

    def may_be_none(self):
        return False

5438
    def generate_evaluation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
5439 5440 5441 5442
        self.literal.generate_evaluation_code(code)
    
    def calculate_result_code(self):
        return self.literal.calculate_result_code()
William Stein's avatar
William Stein committed
5443 5444 5445 5446 5447 5448 5449

#-------------------------------------------------------------------
#
#  Binary operator nodes
#
#-------------------------------------------------------------------

Stefan Behnel's avatar
Stefan Behnel committed
5450 5451 5452
def _not_in(x, seq):
    return x not in seq

5453 5454 5455
compile_time_binary_operators = {
    '<': operator.lt,
    '<=': operator.le,
5456
    '==': operator.eq,
5457 5458 5459 5460 5461 5462 5463
    '!=': operator.ne,
    '>=': operator.ge,
    '>': operator.gt,
    'is': operator.is_,
    'is_not': operator.is_not,
    '+': operator.add,
    '&': operator.and_,
5464
    '/': operator.truediv,
5465 5466 5467 5468 5469 5470 5471 5472 5473
    '//': 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
5474 5475
    'in': operator.contains,
    'not_in': _not_in,
5476 5477 5478 5479 5480 5481 5482
}

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"
5483
                % node.operator)
5484 5485
    return func

5486
class BinopNode(ExprNode):
William Stein's avatar
William Stein committed
5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499
    #  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.
    
    subexprs = ['operand1', 'operand2']
5500
    inplace = False
5501 5502 5503 5504 5505 5506 5507

    def calculate_constant_result(self):
        func = compile_time_binary_operators[self.operator]
        self.constant_result = func(
            self.operand1.constant_result,
            self.operand2.constant_result)

5508 5509 5510 5511 5512 5513 5514 5515
    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)
5516 5517 5518
    
    def infer_type(self, env):
        return self.result_type(self.operand1.infer_type(env),
Robert Bradshaw's avatar
Robert Bradshaw committed
5519 5520
                                self.operand2.infer_type(env))
    
William Stein's avatar
William Stein committed
5521 5522 5523
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
5524 5525 5526
        self.analyse_operation(env)
    
    def analyse_operation(self, env):
William Stein's avatar
William Stein committed
5527 5528
        if self.is_py_operation():
            self.coerce_operands_to_pyobjects(env)
5529 5530 5531
            self.type = self.result_type(self.operand1.type,
                                         self.operand2.type)
            assert self.type.is_pyobject
William Stein's avatar
William Stein committed
5532
            self.is_temp = 1
DaniloFreitas's avatar
DaniloFreitas committed
5533 5534
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
5535 5536 5537 5538
        else:
            self.analyse_c_operation(env)
    
    def is_py_operation(self):
5539 5540 5541 5542 5543
        return self.is_py_operation_types(self.operand1.type, self.operand2.type)
    
    def is_py_operation_types(self, type1, type2):
        return type1.is_pyobject or type2.is_pyobject

DaniloFreitas's avatar
DaniloFreitas committed
5544
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5545 5546
        return (self.operand1.type.is_cpp_class
            or self.operand2.type.is_cpp_class)
DaniloFreitas's avatar
DaniloFreitas committed
5547
    
5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564
    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
    
5565 5566
    def result_type(self, type1, type2):
        if self.is_py_operation_types(type1, type2):
5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584
            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
5585
                    if type2.is_int:
5586
                        return type1
5587 5588 5589 5590
            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
5591 5592 5593
            return py_object_type
        else:
            return self.compute_c_result_type(type1, type2)
5594

5595
    def nogil_check(self, env):
5596
        if self.is_py_operation():
5597
            self.gil_error()
5598
        
William Stein's avatar
William Stein committed
5599 5600 5601 5602 5603
    def coerce_operands_to_pyobjects(self, env):
        self.operand1 = self.operand1.coerce_to_pyobject(env)
        self.operand2 = self.operand2.coerce_to_pyobject(env)
    
    def check_const(self):
5604
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
5605 5606 5607 5608 5609
    
    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()
5610
            if self.operator == '**':
William Stein's avatar
William Stein committed
5611 5612 5613 5614
                extra_args = ", Py_None"
            else:
                extra_args = ""
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
5615
                "%s = %s(%s, %s%s); %s" % (
5616
                    self.result(), 
William Stein's avatar
William Stein committed
5617 5618 5619 5620
                    function, 
                    self.operand1.py_result(),
                    self.operand2.py_result(),
                    extra_args,
5621
                    code.error_goto_if_null(self.result(), self.pos)))
5622
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
5623 5624 5625 5626 5627 5628 5629 5630 5631 5632
    
    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)" %
                (self.operator, self.operand1.type, 
                    self.operand2.type))
        self.type = PyrexTypes.error_type


Robert Bradshaw's avatar
Robert Bradshaw committed
5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654
class CBinopNode(BinopNode):
    
    def analyse_types(self, env):
        BinopNode.analyse_types(self, env)
        if self.is_py_operation():
            self.type = PyrexTypes.error_type
    
    def py_operation_function():
        return ""
        
    def calculate_result_code(self):
        return "(%s %s %s)" % (
            self.operand1.result(), 
            self.operator, 
            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
5655 5656 5657
class NumBinopNode(BinopNode):
    #  Binary operation taking numeric arguments.
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5658 5659
    infix = True
    
William Stein's avatar
William Stein committed
5660 5661 5662 5663 5664 5665
    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()
5666
            return
5667
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
5668
            self.infix = False
5669
        if not self.infix or (type1.is_numeric and type2.is_numeric):
5670 5671
            self.operand1 = self.operand1.coerce_to(self.type, env)
            self.operand2 = self.operand2.coerce_to(self.type, env)
William Stein's avatar
William Stein committed
5672 5673 5674
    
    def compute_c_result_type(self, type1, type2):
        if self.c_types_okay(type1, type2):
5675 5676 5677 5678 5679 5680
            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
            return widest_type
William Stein's avatar
William Stein committed
5681 5682
        else:
            return None
5683 5684 5685 5686 5687 5688 5689 5690

    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
William Stein's avatar
William Stein committed
5691 5692
    
    def c_types_okay(self, type1, type2):
5693 5694 5695
        #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
5696 5697

    def calculate_result_code(self):
5698 5699 5700 5701 5702 5703
        if self.infix:
            return "(%s %s %s)" % (
                self.operand1.result(), 
                self.operator, 
                self.operand2.result())
        else:
5704 5705 5706
            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))
5707
            return "%s(%s, %s)" % (
5708
                func,
5709 5710
                self.operand1.result(),
                self.operand2.result())
William Stein's avatar
William Stein committed
5711
    
5712 5713 5714 5715 5716
    def is_py_operation_types(self, type1, type2):
        return (type1 is PyrexTypes.c_py_unicode_type or
                type2 is PyrexTypes.c_py_unicode_type or
                BinopNode.is_py_operation_types(self, type1, type2))
    
William Stein's avatar
William Stein committed
5717
    def py_operation_function(self):
5718 5719 5720 5721
        fuction = self.py_functions[self.operator]
        if self.inplace:
            fuction = fuction.replace('PyNumber_', 'PyNumber_InPlace')
        return fuction
William Stein's avatar
William Stein committed
5722 5723

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
5724 5725 5726
        "|":        "PyNumber_Or",
        "^":        "PyNumber_Xor",
        "&":        "PyNumber_And",
5727 5728
        "<<":       "PyNumber_Lshift",
        ">>":       "PyNumber_Rshift",
Robert Bradshaw's avatar
Robert Bradshaw committed
5729 5730 5731 5732
        "+":        "PyNumber_Add",
        "-":        "PyNumber_Subtract",
        "*":        "PyNumber_Multiply",
        "/":        "__Pyx_PyNumber_Divide",
5733
        "//":       "PyNumber_FloorDivide",
Robert Bradshaw's avatar
Robert Bradshaw committed
5734
        "%":        "PyNumber_Remainder",
5735
        "**":       "PyNumber_Power"
William Stein's avatar
William Stein committed
5736 5737 5738 5739 5740 5741
    }

class IntBinopNode(NumBinopNode):
    #  Binary operation taking integer arguments.
    
    def c_types_okay(self, type1, type2):
5742 5743 5744
        #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
5745 5746 5747 5748 5749

    
class AddNode(NumBinopNode):
    #  '+' operator.
    
5750 5751 5752
    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
5753
        else:
5754
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5755 5756

    def compute_c_result_type(self, type1, type2):
5757 5758
        #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
5759
            return type1
5760
        elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
William Stein's avatar
William Stein committed
5761 5762 5763 5764 5765 5766 5767 5768 5769 5770
            return type2
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class SubNode(NumBinopNode):
    #  '-' operator.
    
    def compute_c_result_type(self, type1, type2):
5771
        if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
William Stein's avatar
William Stein committed
5772
            return type1
5773
        elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
William Stein's avatar
William Stein committed
5774 5775 5776 5777 5778 5779 5780 5781 5782
            return PyrexTypes.c_int_type
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class MulNode(NumBinopNode):
    #  '*' operator.
    
5783
    def is_py_operation_types(self, type1, type2):
William Stein's avatar
William Stein committed
5784 5785 5786 5787
        if (type1.is_string and type2.is_int) \
            or (type2.is_string and type1.is_int):
                return 1
        else:
5788
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5789 5790


5791 5792 5793
class DivNode(NumBinopNode):
    #  '/' or '//' operator.
    
5794
    cdivision = None
5795 5796
    truedivision = None   # == "unknown" if operator == '/'
    ctruedivision = False
Robert Bradshaw's avatar
Robert Bradshaw committed
5797
    cdivision_warnings = False
5798
    zerodivision_check = None
5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825

    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(
                self, operand1, operand2)
            return func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)

Robert Bradshaw's avatar
Robert Bradshaw committed
5826
    def analyse_operation(self, env):
5827 5828 5829 5830
        if self.cdivision or env.directives['cdivision']:
            self.ctruedivision = False
        else:
            self.ctruedivision = self.truedivision
Robert Bradshaw's avatar
Robert Bradshaw committed
5831
        NumBinopNode.analyse_operation(self, env)
5832 5833
        if self.is_cpp_operation():
            self.cdivision = True
5834
        if not self.type.is_pyobject:
5835 5836
            self.zerodivision_check = (
                self.cdivision is None and not env.directives['cdivision']
5837
                and (not self.operand2.has_constant_result() or
5838
                     self.operand2.constant_result == 0))
5839 5840 5841 5842
            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)
5843 5844
                if env.nogil:
                    error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
5845 5846 5847 5848 5849 5850 5851 5852 5853

    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)

5854 5855 5856 5857 5858
    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
5859

5860
    def generate_evaluation_code(self, code):
5861
        if not self.type.is_pyobject and not self.type.is_complex:
5862 5863 5864 5865 5866
            if self.cdivision is None:
                self.cdivision = (code.globalstate.directives['cdivision'] 
                                    or not self.type.signed
                                    or self.type.is_float)
            if not self.cdivision:
5867
                code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
5868
        NumBinopNode.generate_evaluation_code(self, code)
5869
        self.generate_div_warning_code(code)
5870 5871
    
    def generate_div_warning_code(self, code):
5872 5873
        if not self.type.is_pyobject:
            if self.zerodivision_check:
5874 5875 5876 5877 5878
                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)
5879 5880 5881
                code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
                code.putln(code.error_goto(self.pos))
                code.putln("}")
5882 5883 5884 5885 5886 5887 5888 5889 5890
                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))) {" % (
                                    self.type.declaration_code(''), 
                                    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
5891
            if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
5892 5893 5894 5895 5896 5897 5898 5899
                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));
                code.put("if (__Pyx_cdivision_warning()) ")
                code.put_goto(code.error_label)
                code.putln("}")
Robert Bradshaw's avatar
Robert Bradshaw committed
5900 5901
    
    def calculate_result_code(self):
5902 5903 5904
        if self.type.is_complex:
            return NumBinopNode.calculate_result_code(self)
        elif self.type.is_float and self.operator == '//':
5905
            return "floor(%s / %s)" % (
5906
                self.operand1.result(),
5907
                self.operand2.result())
5908 5909 5910 5911 5912 5913 5914 5915 5916
        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)
5917 5918
        else:
            return "__Pyx_div_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5919
                    self.type.specialization_name(),
5920 5921
                    self.operand1.result(), 
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
5922 5923


Robert Bradshaw's avatar
Robert Bradshaw committed
5924
class ModNode(DivNode):
William Stein's avatar
William Stein committed
5925
    #  '%' operator.
5926

5927 5928 5929 5930
    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
5931

5932 5933 5934 5935 5936 5937
    def zero_division_message(self):
        if self.type.is_int:
            return "integer division or modulo by zero"
        else:
            return "float divmod()"
    
5938
    def generate_evaluation_code(self, code):
5939 5940 5941 5942 5943
        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:
5944
                    code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
5945
                else:
5946 5947
                    code.globalstate.use_utility_code(
                        mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
5948
        NumBinopNode.generate_evaluation_code(self, code)
5949
        self.generate_div_warning_code(code)
5950
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5951
    def calculate_result_code(self):
5952 5953 5954 5955 5956 5957 5958 5959 5960 5961
        if self.cdivision:
            if self.type.is_float:
                return "fmod%s(%s, %s)" % (
                    self.type.math_h_modifier,
                    self.operand1.result(), 
                    self.operand2.result())
            else:
                return "(%s %% %s)" % (
                    self.operand1.result(), 
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
5962
        else:
5963
            return "__Pyx_mod_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5964
                    self.type.specialization_name(),
5965 5966
                    self.operand1.result(), 
                    self.operand2.result())
William Stein's avatar
William Stein committed
5967 5968 5969

class PowNode(NumBinopNode):
    #  '**' operator.
Robert Bradshaw's avatar
Robert Bradshaw committed
5970 5971 5972
    
    def analyse_c_operation(self, env):
        NumBinopNode.analyse_c_operation(self, env)
5973
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
5974 5975 5976 5977 5978 5979 5980
            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>"
5981
        elif self.type.is_float:
5982
            self.pow_func = "pow" + self.type.math_h_modifier
William Stein's avatar
William Stein committed
5983
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
5984 5985 5986 5987
            self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
            env.use_utility_code(
                    int_pow_utility_code.specialize(func_name=self.pow_func, 
                                                type=self.type.declaration_code('')))
5988

William Stein's avatar
William Stein committed
5989
    def calculate_result_code(self):
5990 5991 5992 5993 5994 5995
        # 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
5996 5997
        return "%s(%s, %s)" % (
            self.pow_func, 
5998 5999
            typecast(self.operand1), 
            typecast(self.operand2))
6000

William Stein's avatar
William Stein committed
6001

Craig Citro's avatar
Craig Citro committed
6002
# Note: This class is temporarily "shut down" into an ineffective temp
6003 6004
# allocation mode.
#
Craig Citro's avatar
Craig Citro committed
6005 6006 6007
# 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).
6008
class BoolBinopNode(ExprNode):
William Stein's avatar
William Stein committed
6009 6010 6011 6012 6013 6014
    #  Short-circuiting boolean operation.
    #
    #  operator     string
    #  operand1     ExprNode
    #  operand2     ExprNode
    
6015
    subexprs = ['operand1', 'operand2']
6016 6017
    
    def infer_type(self, env):
6018 6019
        type1 = self.operand1.infer_type(env)
        type2 = self.operand2.infer_type(env)
6020
        return PyrexTypes.independent_spanning_type(type1, type2)
6021

Stefan Behnel's avatar
Stefan Behnel committed
6022 6023 6024 6025 6026 6027
    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()

6028 6029 6030 6031 6032 6033 6034 6035 6036
    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
William Stein's avatar
William Stein committed
6037
    
6038 6039 6040 6041 6042 6043 6044
    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)
6045 6046
    
    def coerce_to_boolean(self, env):
6047 6048 6049 6050 6051 6052 6053
        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)
6054

William Stein's avatar
William Stein committed
6055 6056 6057
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
6058
        self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
6059 6060
        self.operand1 = self.operand1.coerce_to(self.type, env)
        self.operand2 = self.operand2.coerce_to(self.type, env)
6061
        
William Stein's avatar
William Stein committed
6062 6063
        # For what we're about to do, it's vital that
        # both operands be temp nodes.
6064 6065
        self.operand1 = self.operand1.coerce_to_simple(env)
        self.operand2 = self.operand2.coerce_to_simple(env)
William Stein's avatar
William Stein committed
6066
        self.is_temp = 1
6067 6068 6069

    gil_message = "Truth-testing Python object"

William Stein's avatar
William Stein committed
6070
    def check_const(self):
6071
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
6072 6073
    
    def generate_evaluation_code(self, code):
6074
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
6075
        self.operand1.generate_evaluation_code(code)
6076
        test_result, uses_temp = self.generate_operand1_test(code)
William Stein's avatar
William Stein committed
6077 6078 6079 6080 6081 6082 6083 6084
        if self.operator == 'and':
            sense = ""
        else:
            sense = "!"
        code.putln(
            "if (%s%s) {" % (
                sense,
                test_result))
6085 6086
        if uses_temp:
            code.funcstate.release_temp(test_result)
6087
        self.operand1.generate_disposal_code(code)
William Stein's avatar
William Stein committed
6088
        self.operand2.generate_evaluation_code(code)
6089
        self.allocate_temp_result(code)
6090
        self.operand2.make_owned_reference(code)
6091
        code.putln("%s = %s;" % (self.result(), self.operand2.result()))
6092 6093
        self.operand2.generate_post_assignment_code(code)
        self.operand2.free_temps(code)
6094
        code.putln("} else {")
6095
        self.operand1.make_owned_reference(code)
6096
        code.putln("%s = %s;" % (self.result(), self.operand1.result()))
6097 6098
        self.operand1.generate_post_assignment_code(code)
        self.operand1.free_temps(code)
6099
        code.putln("}")
William Stein's avatar
William Stein committed
6100 6101 6102 6103
    
    def generate_operand1_test(self, code):
        #  Generate code to test the truth of the first operand.
        if self.type.is_pyobject:
6104 6105
            test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
                                                       manage_ref=False)
William Stein's avatar
William Stein committed
6106
            code.putln(
6107
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
William Stein's avatar
William Stein committed
6108 6109
                    test_result,
                    self.operand1.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
6110
                    code.error_goto_if_neg(test_result, self.pos)))
William Stein's avatar
William Stein committed
6111
        else:
6112
            test_result = self.operand1.result()
6113
        return (test_result, self.type.is_pyobject)
William Stein's avatar
William Stein committed
6114 6115


6116
class CondExprNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
6117 6118 6119 6120 6121 6122
    #  Short-circuiting conditional expression.
    #
    #  test        ExprNode
    #  true_val    ExprNode
    #  false_val   ExprNode
    
6123 6124
    true_val = None
    false_val = None
Robert Bradshaw's avatar
Robert Bradshaw committed
6125 6126
    
    subexprs = ['test', 'true_val', 'false_val']
6127
    
Robert Bradshaw's avatar
Robert Bradshaw committed
6128 6129
    def type_dependencies(self, env):
        return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
6130
    
Robert Bradshaw's avatar
Robert Bradshaw committed
6131
    def infer_type(self, env):
6132 6133
        return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
                                                    self.false_val.infer_type(env))
6134 6135 6136 6137 6138 6139 6140

    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
6141 6142 6143 6144 6145
    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)
6146
        self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
6147 6148 6149 6150 6151
        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
6152 6153 6154 6155 6156 6157 6158
            self.type_error()
        
    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
6159
    
Robert Bradshaw's avatar
Robert Bradshaw committed
6160
    def check_const(self):
6161 6162 6163
        return (self.test.check_const() 
            and self.true_val.check_const()
            and self.false_val.check_const())
Robert Bradshaw's avatar
Robert Bradshaw committed
6164 6165
    
    def generate_evaluation_code(self, code):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
6166 6167 6168 6169
        # Because subexprs may not be evaluated we can use a more optimal
        # subexpr allocation strategy than the default, so override evaluation_code.
        
        code.mark_pos(self.pos)
6170
        self.allocate_temp_result(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
6171
        self.test.generate_evaluation_code(code)
6172
        code.putln("if (%s) {" % self.test.result() )
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
6173
        self.eval_and_get(code, self.true_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
6174
        code.putln("} else {")
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
6175
        self.eval_and_get(code, self.false_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
6176 6177
        code.putln("}")
        self.test.generate_disposal_code(code)
6178
        self.test.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
6179

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
6180 6181 6182 6183 6184 6185 6186
    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)

6187 6188 6189 6190 6191 6192 6193 6194 6195 6196
richcmp_constants = {
    "<" : "Py_LT",
    "<=": "Py_LE",
    "==": "Py_EQ",
    "!=": "Py_NE",
    "<>": "Py_NE",
    ">" : "Py_GT",
    ">=": "Py_GE",
}

6197
class CmpNode(object):
William Stein's avatar
William Stein committed
6198 6199
    #  Mixin class containing code common to PrimaryCmpNodes
    #  and CascadedCmpNodes.
6200 6201 6202

    special_bool_cmp_function = None

Stefan Behnel's avatar
typo  
Stefan Behnel committed
6203
    def infer_type(self, env):
6204 6205
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type
6206 6207 6208 6209 6210

    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)
6211 6212 6213 6214 6215 6216 6217
        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

6218 6219
    def cascaded_compile_time_value(self, operand1, denv):
        func = get_compile_time_binop(self)
6220
        operand2 = self.operand2.compile_time_value(denv)
6221 6222 6223 6224
        try:
            result = func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)
6225
            result = None
6226 6227 6228
        if result:
            cascade = self.cascade
            if cascade:
6229
                # FIXME: I bet this must call cascaded_compile_time_value()
6230
                result = result and cascade.cascaded_compile_time_value(operand2, denv)
6231 6232
        return result

6233
    def is_cpp_comparison(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
6234
        return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
6235

6236
    def find_common_int_type(self, env, op, operand1, operand2):
6237 6238 6239 6240 6241 6242
        # 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

6243
        if isinstance(operand1, (StringNode, BytesNode, UnicodeNode)) \
6244 6245
               and operand1.can_coerce_to_char_literal():
            type1_can_be_int = True
6246
        if isinstance(operand2, (StringNode, BytesNode, UnicodeNode)) \
6247 6248 6249 6250 6251
                 and operand2.can_coerce_to_char_literal():
            type2_can_be_int = True

        if type1.is_int:
            if type2_can_be_int:
6252
                return type1
6253 6254
        elif type2.is_int:
            if type1_can_be_int:
6255
                return type2
6256 6257
        elif type1_can_be_int:
            if type2_can_be_int:
6258
                return PyrexTypes.c_uchar_type
William Stein's avatar
William Stein committed
6259

6260
        return None
6261

6262
    def find_common_type(self, env, op, operand1, common_type=None):
6263
        operand2 = self.operand2
William Stein's avatar
William Stein committed
6264 6265
        type1 = operand1.type
        type2 = operand2.type
6266

6267 6268
        new_common_type = None

Stefan Behnel's avatar
Stefan Behnel committed
6269
        # catch general errors
6270 6271 6272
        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")
6273
            new_common_type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
6274 6275

        # try to use numeric comparisons where possible
6276
        elif type1.is_complex or type2.is_complex:
6277
            if op not in ('==', '!='):
6278 6279 6280 6281 6282 6283
                error(self.pos, "complex types are unordered")
                new_common_type = error_type
            if type1.is_pyobject:
                new_common_type = type1
            elif type2.is_pyobject:
                new_common_type = type2
6284
            else:
6285
                new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
6286 6287
        elif type1.is_numeric and type2.is_numeric:
            new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
6288
        elif common_type is None or not common_type.is_pyobject:
6289
            new_common_type = self.find_common_int_type(env, op, operand1, operand2)
6290 6291

        if new_common_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
6292
            # fall back to generic type compatibility tests
6293
            if type1 == type2:
6294 6295 6296 6297 6298 6299
                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
6300
                        new_common_type = py_object_type
6301 6302 6303 6304
                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
6305 6306 6307
                        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
6308 6309 6310 6311
                else:
                    # one Python type and one non-Python type, not assignable
                    self.invalid_types_error(operand1, op, operand2)
                    new_common_type = error_type
6312 6313 6314 6315
            elif type1.assignable_from(type2):
                new_common_type = type1
            elif type2.assignable_from(type1):
                new_common_type = type2
6316 6317 6318 6319
            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
6320

6321 6322 6323 6324 6325 6326
        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
6327
        # recursively merge types
6328
        if common_type is None or new_common_type.is_error:
6329
            common_type = new_common_type
William Stein's avatar
William Stein committed
6330
        else:
6331 6332 6333
            # 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
6334
            common_type = PyrexTypes.spanning_type(common_type, new_common_type)
6335 6336

        if self.cascade:
6337
            common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
6338

6339 6340
        return common_type

6341 6342 6343 6344
    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
6345
    def is_python_comparison(self):
6346 6347 6348 6349 6350
        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
6351

6352 6353 6354 6355 6356 6357
    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)
6358

6359
    def is_python_result(self):
6360
        return ((self.has_python_operands() and
6361
                 self.special_bool_cmp_function is None and
6362
                 self.operator not in ('is', 'is_not', 'in', 'not_in') and
6363 6364
                 not self.is_c_string_contains() and
                 not self.is_ptr_contains())
6365
            or (self.cascade and self.cascade.is_python_result()))
William Stein's avatar
William Stein committed
6366

6367 6368
    def is_c_string_contains(self):
        return self.operator in ('in', 'not_in') and \
6369 6370
               ((self.operand1.type.is_int
                 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
6371 6372
                (self.operand1.type is PyrexTypes.c_py_unicode_type
                 and self.operand2.type is unicode_type))
6373 6374 6375
    
    def is_ptr_contains(self):
        if self.operator in ('in', 'not_in'):
6376 6377 6378
            container_type = self.operand2.type
            return (container_type.is_ptr or container_type.is_array) \
                and not container_type.is_string
6379

6380 6381 6382 6383 6384 6385 6386 6387 6388 6389
    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
        return False

William Stein's avatar
William Stein committed
6390 6391
    def generate_operation_code(self, code, result_code, 
            operand1, op , operand2):
6392
        if self.type.is_pyobject:
6393 6394 6395
            coerce_result = "__Pyx_PyBool_FromLong"
        else:
            coerce_result = ""
6396 6397 6398 6399
        if 'not' in op: 
            negation = "!"
        else: 
            negation = ""
6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416
        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
6417
            code.globalstate.use_utility_code(contains_utility_code)
6418
            if self.type.is_pyobject:
6419
                coerce_result = "__Pyx_PyBoolOrNull_FromLong"
6420
            if op == 'not_in':
6421
                negation = "__Pyx_NegateNonNeg"
6422
            if operand2.type is dict_type:
6423
                method = "PyDict_Contains"
6424
            else:
6425
                method = "PySequence_Contains"
6426
            if self.type.is_pyobject:
6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441
                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,
                    operand2.py_result(), 
                    operand1.py_result(), 
                    got_ref,
                    error_clause(result_code, self.pos)))
William Stein's avatar
William Stein committed
6442 6443
        elif (operand1.type.is_pyobject
            and op not in ('is', 'is_not')):
6444 6445
                code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
                        result_code, 
William Stein's avatar
William Stein committed
6446 6447
                        operand1.py_result(), 
                        operand2.py_result(), 
6448 6449
                        richcmp_constants[op],
                        code.error_goto_if_null(result_code, self.pos)))
6450
                code.put_gotref(result_code)
6451 6452 6453 6454 6455
        elif operand1.type.is_complex:
            if op == "!=": 
                negation = "!"
            else: 
                negation = ""
6456 6457 6458 6459 6460 6461 6462
            code.putln("%s = %s(%s%s(%s, %s));" % (
                result_code, 
                coerce_result,
                negation,
                operand1.type.unary_op('eq'), 
                operand1.result(), 
                operand2.result()))
William Stein's avatar
William Stein committed
6463
        else:
6464 6465 6466 6467 6468
            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
6469 6470
            elif type1.is_numeric:
                common_type = PyrexTypes.widest_numeric_type(type1, type2)
6471
            else:
6472 6473 6474
                common_type = type1
            code1 = operand1.result_as(common_type)
            code2 = operand2.result_as(common_type)
6475
            code.putln("%s = %s(%s %s %s);" % (
William Stein's avatar
William Stein committed
6476
                result_code, 
6477
                coerce_result, 
6478
                code1, 
William Stein's avatar
William Stein committed
6479
                self.c_operator(op), 
6480 6481
                code2))

William Stein's avatar
William Stein committed
6482 6483 6484 6485 6486 6487 6488 6489
    def c_operator(self, op):
        if op == 'is':
            return "=="
        elif op == 'is_not':
            return "!="
        else:
            return op
    
Stefan Behnel's avatar
typo  
Stefan Behnel committed
6490
contains_utility_code = UtilityCode(
6491
proto="""
6492 6493
static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
6494 6495 6496 6497
    return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
}
""")

6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529
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;
}
""")

pyunicode_in_unicode_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) {
    const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
    Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
    Py_UNICODE* pos;
    for (pos=char_start; pos < char_start+length; pos++) {
        if (character == pos[0]) return 1;
    }
    return 0;
}
""")

6530 6531 6532 6533 6534 6535
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
6536
    if (s1 == s2) {   /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */
6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569
        return (equals == Py_EQ);
    } else if (PyUnicode_CheckExact(s1) & PyUnicode_CheckExact(s2)) {
        if (PyUnicode_GET_SIZE(s1) != PyUnicode_GET_SIZE(s2)) {
            return (equals == Py_NE);
        } else if (PyUnicode_GET_SIZE(s1) == 1) {
            if (equals == Py_EQ)
                return (PyUnicode_AS_UNICODE(s1)[0] == PyUnicode_AS_UNICODE(s2)[0]);
            else
                return (PyUnicode_AS_UNICODE(s1)[0] != PyUnicode_AS_UNICODE(s2)[0]);
        } 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) & (s2 == Py_None)) {
        return (equals == Py_EQ);
    } 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;
    }
}
""")

William Stein's avatar
William Stein committed
6570

6571
class PrimaryCmpNode(ExprNode, CmpNode):
William Stein's avatar
William Stein committed
6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584
    #  Non-cascaded comparison or first comparison of
    #  a cascaded sequence.
    #
    #  operator      string
    #  operand1      ExprNode
    #  operand2      ExprNode
    #  cascade       CascadedCmpNode
    
    #  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.
    
Robert Bradshaw's avatar
Robert Bradshaw committed
6585 6586
    child_attrs = ['operand1', 'operand2', 'cascade']
    
William Stein's avatar
William Stein committed
6587
    cascade = None
6588

Robert Bradshaw's avatar
Robert Bradshaw committed
6589 6590 6591 6592 6593 6594 6595
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

6596
    def calculate_constant_result(self):
6597
        self.calculate_cascaded_constant_result(self.operand1.constant_result)
William Stein's avatar
William Stein committed
6598
    
6599
    def compile_time_value(self, denv):
6600
        operand1 = self.operand1.compile_time_value(denv)
6601 6602
        return self.cascaded_compile_time_value(operand1, denv)

William Stein's avatar
William Stein committed
6603 6604 6605
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
6606 6607
        if self.is_cpp_comparison():
            self.analyse_cpp_comparison(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
6608 6609 6610
            if self.cascade:
                error(self.pos, "Cascading comparison not yet supported for cpp types.")
            return
William Stein's avatar
William Stein committed
6611
        if self.cascade:
6612 6613
            self.cascade.analyse_types(env)

6614
        if self.operator in ('in', 'not_in'):
6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628
            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:
                    env.use_utility_code(pyunicode_in_unicode_utility_code)
                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
6629 6630
                self.operand2 = self.operand2.as_none_safe_node(
                    "argument of type 'NoneType' is not iterable")
6631 6632 6633 6634 6635 6636
            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
6637
            else:
6638 6639
                if self.operand2.type is dict_type:
                    self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
6640 6641
                common_type = py_object_type
                self.is_pycmp = True
6642 6643 6644 6645
        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
6646 6647 6648 6649
        else:
            common_type = self.find_common_type(env, self.operator, self.operand1)
            self.is_pycmp = common_type.is_pyobject

6650
        if common_type is not None and not common_type.is_error:
6651 6652 6653
            if self.operand1.type != common_type:
                self.operand1 = self.operand1.coerce_to(common_type, env)
            self.coerce_operands_to(common_type, env)
6654

William Stein's avatar
William Stein committed
6655 6656 6657
        if self.cascade:
            self.operand2 = self.operand2.coerce_to_simple(env)
            self.cascade.coerce_cascaded_operands_to_temp(env)
6658 6659 6660 6661 6662 6663 6664 6665
        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
6666 6667 6668
        if self.is_pycmp or self.cascade:
            self.is_temp = 1
    
6669 6670 6671
    def analyse_cpp_comparison(self, env):
        type1 = self.operand1.type
        type2 = self.operand2.type
6672 6673
        entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
        if entry is None:
6674 6675
            error(self.pos, "Invalid types for '%s' (%s, %s)" %
                (self.operator, type1, type2))
6676 6677 6678
            self.type = PyrexTypes.error_type
            self.result_code = "<error>"
            return
6679 6680 6681 6682 6683
        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)
6684
        else:
6685 6686 6687
            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
6688
    
William Stein's avatar
William Stein committed
6689 6690 6691
    def has_python_operands(self):
        return (self.operand1.type.is_pyobject
            or self.operand2.type.is_pyobject)
6692
    
William Stein's avatar
William Stein committed
6693 6694 6695
    def check_const(self):
        if self.cascade:
            self.not_const()
6696 6697 6698
            return False
        else:
            return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
6699 6700

    def calculate_result_code(self):
6701 6702 6703 6704 6705 6706 6707 6708 6709 6710
        if self.operand1.type.is_complex:
            if self.operator == "!=":
                negation = "!"
            else:
                negation = ""
            return "(%s%s(%s, %s))" % (
                negation,
                self.operand1.type.binary_op('=='), 
                self.operand1.result(), 
                self.operand2.result())
6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724
        elif self.is_c_string_contains():
            if self.operand2.type is bytes_type:
                method = "__Pyx_BytesContains"
            else:
                method = "__Pyx_UnicodeContains"
            if self.operator == "not_in":
                negation = "!"
            else:
                negation = ""
            return "(%s%s(%s, %s))" % (
                negation,
                method,
                self.operand2.result(), 
                self.operand1.result())
6725 6726 6727 6728 6729
        else:
            return "(%s %s %s)" % (
                self.operand1.result(),
                self.c_operator(self.operator),
                self.operand2.result())
6730

William Stein's avatar
William Stein committed
6731 6732 6733 6734
    def generate_evaluation_code(self, code):
        self.operand1.generate_evaluation_code(code)
        self.operand2.generate_evaluation_code(code)
        if self.is_temp:
6735
            self.allocate_temp_result(code)
6736
            self.generate_operation_code(code, self.result(), 
William Stein's avatar
William Stein committed
6737 6738 6739
                self.operand1, self.operator, self.operand2)
            if self.cascade:
                self.cascade.generate_evaluation_code(code,
6740
                    self.result(), self.operand2)
William Stein's avatar
William Stein committed
6741
            self.operand1.generate_disposal_code(code)
6742
            self.operand1.free_temps(code)
William Stein's avatar
William Stein committed
6743
            self.operand2.generate_disposal_code(code)
6744
            self.operand2.free_temps(code)
6745

William Stein's avatar
William Stein committed
6746 6747 6748 6749 6750
    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)
6751
        
6752 6753 6754 6755 6756 6757
    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)
        
6758 6759 6760 6761 6762
    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
6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774


class CascadedCmpNode(Node, CmpNode):
    #  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 
    #  with the PrimaryCmpNode at the head of the chain.
    #
    #  operator      string
    #  operand2      ExprNode
    #  cascade       CascadedCmpNode

Robert Bradshaw's avatar
Robert Bradshaw committed
6775 6776
    child_attrs = ['operand2', 'cascade']

William Stein's avatar
William Stein committed
6777
    cascade = None
6778 6779
    constant_result = constant_value_not_set # FIXME: where to calculate this?

Robert Bradshaw's avatar
Robert Bradshaw committed
6780 6781 6782 6783 6784 6785 6786
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

6787 6788 6789 6790
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

6791
    def analyse_types(self, env):
William Stein's avatar
William Stein committed
6792 6793
        self.operand2.analyse_types(env)
        if self.cascade:
6794
            self.cascade.analyse_types(env)
6795

William Stein's avatar
William Stein committed
6796 6797
    def has_python_operands(self):
        return self.operand2.type.is_pyobject
6798
        
William Stein's avatar
William Stein committed
6799 6800
    def coerce_operands_to_pyobjects(self, env):
        self.operand2 = self.operand2.coerce_to_pyobject(env)
6801 6802
        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
6803 6804 6805 6806 6807 6808 6809 6810 6811 6812
        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)
    
    def generate_evaluation_code(self, code, result, operand1):
6813 6814
        if self.type.is_pyobject:
            code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
6815
            code.put_decref(result, self.type)
6816 6817
        else:
            code.putln("if (%s) {" % result)
William Stein's avatar
William Stein committed
6818 6819 6820 6821 6822 6823 6824 6825
        self.operand2.generate_evaluation_code(code)
        self.generate_operation_code(code, result, 
            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)
6826
        self.operand2.free_temps(code)
William Stein's avatar
William Stein committed
6827 6828
        code.putln("}")

6829 6830 6831 6832 6833
    def annotate(self, code):
        self.operand2.annotate(code)
        if self.cascade:
            self.cascade.annotate(code)

William Stein's avatar
William Stein committed
6834 6835

binop_node_classes = {
6836 6837
    "or":       BoolBinopNode,
    "and":      BoolBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6838 6839 6840
    "|":        IntBinopNode,
    "^":        IntBinopNode,
    "&":        IntBinopNode,
6841 6842
    "<<":       IntBinopNode,
    ">>":       IntBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6843 6844 6845
    "+":        AddNode,
    "-":        SubNode,
    "*":        MulNode,
6846 6847
    "/":        DivNode,
    "//":       DivNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6848
    "%":        ModNode,
6849
    "**":       PowNode
William Stein's avatar
William Stein committed
6850 6851
}

6852
def binop_node(pos, operator, operand1, operand2, inplace=False):
William Stein's avatar
William Stein committed
6853 6854 6855 6856 6857
    # Construct binop node of appropriate class for 
    # given operator.
    return binop_node_classes[operator](pos, 
        operator = operator, 
        operand1 = operand1, 
6858 6859
        operand2 = operand2,
        inplace = inplace)
William Stein's avatar
William Stein committed
6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871

#-------------------------------------------------------------------
#
#  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.
#
#-------------------------------------------------------------------

6872
class CoercionNode(ExprNode):
William Stein's avatar
William Stein committed
6873 6874 6875 6876 6877
    #  Abstract base class for coercion nodes.
    #
    #  arg       ExprNode       node being coerced
    
    subexprs = ['arg']
6878
    constant_result = not_a_constant
William Stein's avatar
William Stein committed
6879 6880 6881 6882 6883
    
    def __init__(self, arg):
        self.pos = arg.pos
        self.arg = arg
        if debug_coercion:
Stefan Behnel's avatar
Stefan Behnel committed
6884
            print("%s Coercing %s" % (self, self.arg))
6885 6886

    def calculate_constant_result(self):
6887 6888
        # constant folding can break type coercion, so this is disabled
        pass
6889 6890 6891 6892 6893 6894
            
    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
6895 6896 6897 6898 6899 6900 6901 6902


class CastNode(CoercionNode):
    #  Wrap a node in a C type cast.
    
    def __init__(self, arg, new_type):
        CoercionNode.__init__(self, arg)
        self.type = new_type
Stefan Behnel's avatar
Stefan Behnel committed
6903 6904 6905

    def may_be_none(self):
        return self.arg.may_be_none()
William Stein's avatar
William Stein committed
6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918
    
    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.

6919
    def __init__(self, arg, dst_type, env, notnone=False):
William Stein's avatar
William Stein committed
6920 6921
        #  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
6922
        assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
William Stein's avatar
William Stein committed
6923 6924 6925
        CoercionNode.__init__(self, arg)
        self.type = dst_type
        self.result_ctype = arg.ctype()
6926
        self.notnone = notnone
6927

6928
    nogil_check = Node.gil_error
6929
    gil_message = "Python type test"
William Stein's avatar
William Stein committed
6930
    
6931 6932
    def analyse_types(self, env):
        pass
Stefan Behnel's avatar
Stefan Behnel committed
6933 6934 6935 6936 6937

    def may_be_none(self):
        if self.notnone:
            return False
        return self.arg.may_be_none()
6938
    
William Stein's avatar
William Stein committed
6939 6940 6941 6942 6943
    def result_in_temp(self):
        return self.arg.result_in_temp()
    
    def is_ephemeral(self):
        return self.arg.is_ephemeral()
6944 6945 6946 6947 6948

    def calculate_constant_result(self):
        # FIXME
        pass

William Stein's avatar
William Stein committed
6949
    def calculate_result_code(self):
6950
        return self.arg.result()
William Stein's avatar
William Stein committed
6951 6952 6953
    
    def generate_result_code(self, code):
        if self.type.typeobj_is_available():
6954
            if not self.type.is_builtin_type:
6955
                code.globalstate.use_utility_code(type_test_utility_code)
William Stein's avatar
William Stein committed
6956
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
6957
                "if (!(%s)) %s" % (
6958
                    self.type.type_test_code(self.arg.py_result(), self.notnone),
William Stein's avatar
William Stein committed
6959 6960 6961 6962 6963 6964 6965
                    code.error_goto(self.pos)))
        else:
            error(self.pos, "Cannot test type of extern C class "
                "without type object name specification")
                
    def generate_post_assignment_code(self, code):
        self.arg.generate_post_assignment_code(code)
6966 6967 6968

    def free_temps(self, code):
        self.arg.free_temps(code)
6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985


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).

    def __init__(self, arg, exception_type_cname, exception_message):
        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

    def analyse_types(self, env):
        pass

6986 6987 6988
    def may_be_none(self):
        return False

6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999
    def result_in_temp(self):
        return self.arg.result_in_temp()

    def calculate_result_code(self):
        return self.arg.result()
    
    def generate_result_code(self, code):
        code.putln(
            "if (unlikely(%s == Py_None)) {" % self.arg.result())
        code.putln('PyErr_SetString(%s, "%s"); %s ' % (
            self.exception_type_cname,
Stefan Behnel's avatar
Stefan Behnel committed
7000 7001
            StringEncoding.escape_byte_string(
                self.exception_message.encode('UTF-8')),
7002 7003 7004 7005 7006 7007 7008 7009 7010
            code.error_goto(self.pos)))
        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)

7011

William Stein's avatar
William Stein committed
7012 7013 7014
class CoerceToPyTypeNode(CoercionNode):
    #  This node is used to convert a C data type
    #  to a Python object.
7015 7016
    
    type = py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
7017
    is_temp = 1
William Stein's avatar
William Stein committed
7018

7019
    def __init__(self, arg, env, type=py_object_type):
William Stein's avatar
William Stein committed
7020
        CoercionNode.__init__(self, arg)
7021
        if not arg.type.create_to_py_utility_code(env):
William Stein's avatar
William Stein committed
7022
            error(arg.pos,
7023
                  "Cannot convert '%s' to Python object" % arg.type)
7024 7025 7026
        if type is not py_object_type:
            self.type = py_object_type
        elif arg.type.is_string:
7027 7028 7029
            self.type = bytes_type
        elif arg.type is PyrexTypes.c_py_unicode_type:
            self.type = unicode_type
7030

7031
    gil_message = "Converting to Python object"
7032

7033 7034 7035 7036
    def may_be_none(self):
        # FIXME: is this always safe?
        return False

7037
    def coerce_to_boolean(self, env):
7038 7039 7040 7041 7042 7043
        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)
7044 7045 7046 7047 7048 7049 7050
    
    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)
7051

7052 7053 7054 7055
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
7056 7057
    def generate_result_code(self, code):
        function = self.arg.type.to_py_function
Robert Bradshaw's avatar
Robert Bradshaw committed
7058
        code.putln('%s = %s(%s); %s' % (
7059
            self.result(), 
William Stein's avatar
William Stein committed
7060
            function, 
7061 7062
            self.arg.result(), 
            code.error_goto_if_null(self.result(), self.pos)))
7063
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
7064 7065


7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105
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
7106 7107 7108 7109 7110 7111 7112 7113
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
7114
        if not result_type.create_from_py_utility_code(env):
William Stein's avatar
William Stein committed
7115
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
7116
                  "Cannot convert Python object to '%s'" % result_type)
William Stein's avatar
William Stein committed
7117 7118
        if self.type.is_string and self.arg.is_ephemeral():
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
7119
                  "Obtaining char * from temporary Python value")
William Stein's avatar
William Stein committed
7120
    
7121 7122 7123 7124
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
7125 7126
    def generate_result_code(self, code):
        function = self.type.from_py_function
7127 7128 7129 7130
        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
7131
        code.putln('%s = %s; %s' % (
7132
            self.result(), 
7133
            rhs,
7134
            code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
7135
        if self.type.is_pyobject:
7136
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
7137 7138 7139 7140 7141 7142


class CoerceToBooleanNode(CoercionNode):
    #  This node is used when a result needs to be used
    #  in a boolean context.
    
7143
    type = PyrexTypes.c_bint_type
7144 7145 7146 7147

    _special_builtins = {
        Builtin.list_type    : 'PyList_GET_SIZE',
        Builtin.tuple_type   : 'PyTuple_GET_SIZE',
7148
        Builtin.bytes_type   : 'PyBytes_GET_SIZE',
7149 7150 7151
        Builtin.unicode_type : 'PyUnicode_GET_SIZE',
        }

William Stein's avatar
William Stein committed
7152 7153 7154 7155
    def __init__(self, arg, env):
        CoercionNode.__init__(self, arg)
        if arg.type.is_pyobject:
            self.is_temp = 1
7156

7157
    def nogil_check(self, env):
7158
        if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
7159
            self.gil_error()
7160

7161
    gil_message = "Truth-testing Python object"
William Stein's avatar
William Stein committed
7162 7163 7164 7165
    
    def check_const(self):
        if self.is_temp:
            self.not_const()
7166 7167
            return False
        return self.arg.check_const()
William Stein's avatar
William Stein committed
7168 7169
    
    def calculate_result_code(self):
7170
        return "(%s != 0)" % self.arg.result()
William Stein's avatar
William Stein committed
7171 7172

    def generate_result_code(self, code):
7173 7174 7175 7176
        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
7177
            code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
7178 7179 7180 7181 7182
                       self.result(),
                       self.arg.py_result(),
                       test_func,
                       self.arg.py_result()))
        else:
William Stein's avatar
William Stein committed
7183
            code.putln(
7184
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
7185
                    self.result(), 
William Stein's avatar
William Stein committed
7186
                    self.arg.py_result(), 
7187
                    code.error_goto_if_neg(self.result(), self.pos)))
William Stein's avatar
William Stein committed
7188

7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199
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:
7200 7201
            real_part = "__Pyx_CREAL(%s)" % self.arg.result()
            imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
7202 7203 7204 7205 7206 7207 7208 7209 7210 7211
        else:
            real_part = self.arg.result()
            imag_part = "0"
        return "%s(%s, %s)" % (
                self.type.from_parts,
                real_part,
                imag_part)
    
    def generate_result_code(self, code):
        pass
William Stein's avatar
William Stein committed
7212 7213 7214 7215 7216 7217 7218 7219 7220

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
7221
        self.constant_result = self.arg.constant_result
William Stein's avatar
William Stein committed
7222 7223 7224
        self.is_temp = 1
        if self.type.is_pyobject:
            self.result_ctype = py_object_type
7225 7226 7227

    gil_message = "Creating temporary Python reference"

7228 7229 7230
    def analyse_types(self, env):
        # The arg is always already analysed
        pass
7231 7232 7233
        
    def coerce_to_boolean(self, env):
        self.arg = self.arg.coerce_to_boolean(env)
7234 7235
        if self.arg.is_simple():
            return self.arg
7236 7237 7238
        self.type = self.arg.type
        self.result_ctype = self.type
        return self
7239

William Stein's avatar
William Stein committed
7240 7241 7242 7243
    def generate_result_code(self, code):
        #self.arg.generate_evaluation_code(code) # Already done
        # by generic generate_subexpr_evaluation_code!
        code.putln("%s = %s;" % (
7244
            self.result(), self.arg.result_as(self.ctype())))
7245
        if self.type.is_pyobject and self.use_managed_ref:
7246
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257


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
    #  disposal code for it. The original owner of the argument 
    #  node is responsible for doing those things.
    
    subexprs = [] # Arg is not considered a subexpr
7258
    nogil_check = None
William Stein's avatar
William Stein committed
7259 7260 7261
    
    def __init__(self, arg):
        CoercionNode.__init__(self, arg)
7262 7263 7264 7265 7266
        if hasattr(arg, 'type'):
            self.type = arg.type
            self.result_ctype = arg.result_ctype
        if hasattr(arg, 'entry'):
            self.entry = arg.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
7267
            
7268
    def result(self):
7269
        return self.arg.result()
7270
    
Robert Bradshaw's avatar
Robert Bradshaw committed
7271 7272
    def type_dependencies(self, env):
        return self.arg.type_dependencies(env)
7273 7274 7275
    
    def infer_type(self, env):
        return self.arg.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
7276

Robert Bradshaw's avatar
Robert Bradshaw committed
7277 7278 7279 7280
    def analyse_types(self, env):
        self.type = self.arg.type
        self.result_ctype = self.arg.result_ctype
        self.is_temp = 1
7281 7282
        if hasattr(self.arg, 'entry'):
            self.entry = self.arg.entry
William Stein's avatar
William Stein committed
7283 7284 7285 7286 7287 7288
    
    def generate_evaluation_code(self, code):
        pass

    def generate_result_code(self, code):
        pass
7289
        
7290
    def generate_disposal_code(self, code):
7291 7292
        pass
                
7293 7294
    def free_temps(self, code):
        pass
7295

7296

7297 7298 7299 7300 7301 7302 7303 7304 7305 7306
class ModuleRefNode(ExprNode):
    # Simple returns the module object
    
    type = py_object_type
    is_temp = False
    subexprs = []
    
    def analyse_types(self, env):
        pass

7307 7308 7309
    def may_be_none(self):
        return False

7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331
    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
    
    subexprs = ['body']
    type = py_object_type
    is_temp = True
    
    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):
7332 7333 7334
        code.putln('%s = __Pyx_GetAttrString(%s, "__doc__"); %s' % (
            self.result(), self.body.result(),
            code.error_goto_if_null(self.result(), self.pos)))
7335 7336 7337 7338
        code.put_gotref(self.result())



William Stein's avatar
William Stein committed
7339 7340 7341 7342 7343 7344
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

7345 7346
get_name_interned_utility_code = UtilityCode(
proto = """
7347
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
7348 7349
""",
impl = """
William Stein's avatar
William Stein committed
7350 7351 7352 7353 7354 7355 7356
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
    PyObject *result;
    result = PyObject_GetAttr(dict, name);
    if (!result)
        PyErr_SetObject(PyExc_NameError, name);
    return result;
}
7357
""")
William Stein's avatar
William Stein committed
7358 7359 7360

#------------------------------------------------------------------------------------

7361 7362
import_utility_code = UtilityCode(
proto = """
7363
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
7364 7365
""",
impl = """
William Stein's avatar
William Stein committed
7366
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
7367
    PyObject *py_import = 0;
William Stein's avatar
William Stein committed
7368 7369 7370 7371 7372
    PyObject *empty_list = 0;
    PyObject *module = 0;
    PyObject *global_dict = 0;
    PyObject *empty_dict = 0;
    PyObject *list;
7373 7374
    py_import = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
    if (!py_import)
William Stein's avatar
William Stein committed
7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389
        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;
7390
    module = PyObject_CallFunctionObjArgs(py_import,
7391
        name, global_dict, empty_dict, list, NULL);
William Stein's avatar
William Stein committed
7392 7393
bad:
    Py_XDECREF(empty_list);
7394
    Py_XDECREF(py_import);
William Stein's avatar
William Stein committed
7395 7396 7397 7398 7399 7400
    Py_XDECREF(empty_dict);
    return module;
}
""" % {
    "BUILTINS": Naming.builtins_cname,
    "GLOBALS":  Naming.module_cname,
7401
})
William Stein's avatar
William Stein committed
7402 7403 7404

#------------------------------------------------------------------------------------

7405 7406
get_exception_utility_code = UtilityCode(
proto = """
7407
static PyObject *__Pyx_GetExcValue(void); /*proto*/
7408 7409
""",
impl = """
William Stein's avatar
William Stein committed
7410 7411
static PyObject *__Pyx_GetExcValue(void) {
    PyObject *type = 0, *value = 0, *tb = 0;
7412
    PyObject *tmp_type, *tmp_value, *tmp_tb;
William Stein's avatar
William Stein committed
7413 7414 7415 7416 7417 7418 7419 7420 7421 7422
    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);
    }
7423 7424 7425
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
William Stein's avatar
William Stein committed
7426 7427 7428
    tstate->exc_type = type;
    tstate->exc_value = value;
    tstate->exc_traceback = tb;
7429 7430 7431 7432 7433
    /* 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
7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444
    result = value;
    Py_XINCREF(result);
    type = 0;
    value = 0;
    tb = 0;
bad:
    Py_XDECREF(type);
    Py_XDECREF(value);
    Py_XDECREF(tb);
    return result;
}
7445
""")
William Stein's avatar
William Stein committed
7446 7447 7448

#------------------------------------------------------------------------------------

7449 7450
type_test_utility_code = UtilityCode(
proto = """
7451
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
7452 7453
""",
impl = """
7454
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
7455
    if (unlikely(!type)) {
William Stein's avatar
William Stein committed
7456 7457 7458
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
7459
    if (likely(PyObject_TypeCheck(obj, type)))
William Stein's avatar
William Stein committed
7460
        return 1;
7461 7462
    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
                 Py_TYPE(obj)->tp_name, type->tp_name);
William Stein's avatar
William Stein committed
7463 7464
    return 0;
}
7465
""")
William Stein's avatar
William Stein committed
7466 7467 7468

#------------------------------------------------------------------------------------

7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500
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);
        metaclass = PyObject_GetAttrString(base, "__class__");
        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;
}
''')

7501 7502
create_class_utility_code = UtilityCode(
proto = """
7503
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
7504 7505 7506 7507 7508
                                   PyObject *modname); /*proto*/
""",
impl = """
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
                                   PyObject *modname) {
7509 7510
    PyObject *result;
    PyObject *metaclass;
7511 7512 7513 7514 7515 7516

    if (PyDict_SetItemString(dict, "__module__", modname) < 0)
        return NULL;

    /* Python2 __metaclass__ */
    metaclass = PyDict_GetItemString(dict, "__metaclass__");
7517 7518 7519 7520
    if (metaclass) {
        Py_INCREF(metaclass);
    } else {
        metaclass = __Pyx_FindPy2Metaclass(bases);
7521 7522 7523 7524 7525
    }
    result = PyObject_CallFunctionObjArgs(metaclass, name, bases, dict, NULL);
    Py_DECREF(metaclass);
    return result;
}
7526 7527
""",
requires = [find_py2_metaclass_utility_code])
7528 7529 7530 7531 7532

#------------------------------------------------------------------------------------

create_py3class_utility_code = UtilityCode(
proto = """
Stefan Behnel's avatar
Stefan Behnel committed
7533 7534 7535
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*/
7536 7537
""",
impl = """
Stefan Behnel's avatar
Stefan Behnel committed
7538
PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw) {
7539
    PyObject *metaclass = PyDict_GetItemString(mkw, "metaclass");
7540 7541 7542 7543 7544 7545 7546 7547
    if (metaclass) {
        Py_INCREF(metaclass);
        if (PyDict_DelItemString(mkw, "metaclass") < 0) {
            Py_DECREF(metaclass);
            return NULL;
        }
        return metaclass;
    }
7548
    return __Pyx_FindPy2Metaclass(bases);
7549 7550
}

Stefan Behnel's avatar
Stefan Behnel committed
7551 7552
PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw,
                                    PyObject *modname, PyObject *doc) {
7553 7554 7555
    PyObject *prep;
    PyObject *pargs;
    PyObject *ns;
7556
    PyObject *str;
7557 7558

    prep = PyObject_GetAttrString(metaclass, "__prepare__");
Stefan Behnel's avatar
Stefan Behnel committed
7559
    if (!prep) {
7560
        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
7561
            return NULL;
7562
        PyErr_Clear();
7563
        return PyDict_New();
7564
    }
Stefan Behnel's avatar
Stefan Behnel committed
7565 7566
    pargs = PyTuple_New(2);
    if (!pargs) {
7567
        Py_DECREF(prep);
7568
        return NULL;
7569
    }
7570

Stefan Behnel's avatar
Stefan Behnel committed
7571 7572 7573 7574
    Py_INCREF(name);
    Py_INCREF(bases);
    PyTuple_SET_ITEM(pargs, 0, name);
    PyTuple_SET_ITEM(pargs, 1, bases);
7575

Stefan Behnel's avatar
Stefan Behnel committed
7576
    ns = PyObject_Call(prep, pargs, mkw);
7577

7578
    Py_DECREF(prep);
7579 7580
    Py_DECREF(pargs);

7581
    if (ns == NULL)
7582 7583 7584 7585
        return NULL;

    /* Required here to emulate assignment order */
    /* XXX: use consts here */
Stefan Behnel's avatar
Stefan Behnel committed
7586 7587 7588
    #if PY_MAJOR_VERSION >= 3
    str = PyUnicode_FromString("__module__");
    #else
7589
    str = PyString_FromString("__module__");
Stefan Behnel's avatar
Stefan Behnel committed
7590
    #endif
7591
    if (!str) {
7592
        Py_DECREF(ns);
7593
        return NULL;
7594
    }
Vitja Makarov's avatar
Vitja Makarov committed
7595

7596 7597 7598
    if (PyObject_SetItem(ns, str, modname) < 0) {
        Py_DECREF(ns);
        Py_DECREF(str);
7599
        return NULL;
7600 7601 7602
    }
    Py_DECREF(str);
    if (doc) {
Stefan Behnel's avatar
Stefan Behnel committed
7603 7604 7605
        #if PY_MAJOR_VERSION >= 3
        str = PyUnicode_FromString("__doc__");
        #else
7606
        str = PyString_FromString("__doc__");
Stefan Behnel's avatar
Stefan Behnel committed
7607
        #endif
7608 7609
        if (!str) {
            Py_DECREF(ns);
7610
            return NULL;
Vitja Makarov's avatar
Vitja Makarov committed
7611
        }
7612 7613 7614 7615
        if (PyObject_SetItem(ns, str, doc) < 0) {
            Py_DECREF(ns);
            Py_DECREF(str);
            return NULL;
Stefan Behnel's avatar
Stefan Behnel committed
7616
        }
7617
        Py_DECREF(str);
Vitja Makarov's avatar
Vitja Makarov committed
7618
    }
7619 7620 7621
    return ns;
}

Stefan Behnel's avatar
Stefan Behnel committed
7622
PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw) {
7623
    PyObject *result;
7624
    PyObject *margs = PyTuple_New(3);
7625 7626
    if (!margs)
        return NULL;
7627 7628 7629 7630 7631 7632
    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
7633
    result = PyObject_Call(metaclass, margs, mkw);
7634
    Py_DECREF(margs);
William Stein's avatar
William Stein committed
7635 7636
    return result;
}
7637 7638
""",
requires = [find_py2_metaclass_utility_code])
William Stein's avatar
William Stein committed
7639 7640

#------------------------------------------------------------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
7641

7642 7643
cpp_exception_utility_code = UtilityCode(
proto = """
7644 7645
#ifndef __Pyx_CppExn2PyErr
static void __Pyx_CppExn2PyErr() {
Robert Bradshaw's avatar
Robert Bradshaw committed
7646 7647 7648 7649 7650
  try {
    if (PyErr_Occurred())
      ; // let the latest Python exn pass through and ignore the current one
    else
      throw;
7651 7652 7653 7654 7655
  } catch (const std::invalid_argument& exn) {
    // Catch a handful of different errors here and turn them into the
    // equivalent Python errors.
    // Change invalid_argument to ValueError
    PyErr_SetString(PyExc_ValueError, exn.what());
Robert Bradshaw's avatar
Robert Bradshaw committed
7656
  } catch (const std::out_of_range& exn) {
7657
    // Change out_of_range to IndexError
Robert Bradshaw's avatar
Robert Bradshaw committed
7658 7659 7660 7661 7662 7663 7664 7665 7666
    PyErr_SetString(PyExc_IndexError, exn.what());
  } catch (const std::exception& exn) {
    PyErr_SetString(PyExc_RuntimeError, exn.what());
  }
  catch (...)
  {
    PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
  }
}
7667
#endif
7668 7669 7670
""",
impl = ""
)
Robert Bradshaw's avatar
Robert Bradshaw committed
7671

7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690
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
7691
#------------------------------------------------------------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
7692

7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726
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);
}
''')

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");
}
''')

#------------------------------------------------------------------------------------

getitem_dict_utility_code = UtilityCode(
proto = """
7727
#if PY_MAJOR_VERSION >= 3
7728
static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
7729
    PyObject *value;
7730
    if (unlikely(d == Py_None)) {
7731 7732 7733
        __Pyx_RaiseNoneIndexingError();
        return NULL;
    }
7734 7735 7736
    value = PyDict_GetItemWithError(d, key);
    if (unlikely(!value)) {
        if (!PyErr_Occurred())
7737
            PyErr_SetObject(PyExc_KeyError, key);
7738
        return NULL;
7739
    }
7740 7741
    Py_INCREF(value);
    return value;
7742
}
7743 7744 7745
#else
    #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
#endif
7746 7747 7748 7749
""", 
requires = [raise_noneindex_error_utility_code])

#------------------------------------------------------------------------------------
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7750

7751 7752 7753 7754
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
7755
                                               __Pyx_GetItemInt_Unicode_Generic(o, to_py_func(i)))
7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770

static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i) {
    if (likely((0 <= i) & (i < PyUnicode_GET_SIZE(ustring)))) {
        return PyUnicode_AS_UNICODE(ustring)[i];
    } else if ((-PyUnicode_GET_SIZE(ustring) <= i) & (i < 0)) {
        i += PyUnicode_GET_SIZE(ustring);
        return PyUnicode_AS_UNICODE(ustring)[i];
    } else {
        PyErr_SetString(PyExc_IndexError, "string index out of range");
        return (Py_UNICODE)-1;
    }
}

static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Generic(PyObject* ustring, PyObject* j) {
    Py_UNICODE uchar;
7771
    PyObject *uchar_string;
7772
    if (!j) return (Py_UNICODE)-1;
7773
    uchar_string = PyObject_GetItem(ustring, j);
7774
    Py_DECREF(j);
7775 7776 7777
    if (!uchar_string) return (Py_UNICODE)-1;
    uchar = PyUnicode_AS_UNICODE(uchar_string)[0];
    Py_DECREF(uchar_string);
7778 7779
    return uchar;
}
7780
''')
7781

7782 7783
getitem_int_utility_code = UtilityCode(
proto = """
7784

7785
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
7786
    PyObject *r;
7787
    if (!j) return NULL;
7788 7789 7790 7791
    r = PyObject_GetItem(o, j);
    Py_DECREF(j);
    return r;
}
7792

7793 7794
""" + ''.join([
"""
7795 7796
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
7797 7798
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

7799
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
7800 7801 7802 7803 7804 7805
    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;
        }
7806 7807
        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);
7808 7809 7810
            Py_INCREF(r);
            return r;
        }
7811
    }
7812
    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
7813
}
7814 7815
""" % {'type' : type_name} for type_name in ('List', 'Tuple')
]) + """
7816

7817 7818
#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_Fast(o, i) : \\
7819 7820
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

7821
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7822
    PyObject *r;
Robert Bradshaw's avatar
Robert Bradshaw committed
7823
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7824 7825 7826
        r = PyList_GET_ITEM(o, i);
        Py_INCREF(r);
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
7827
    else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7828 7829 7830
        r = PyTuple_GET_ITEM(o, i);
        Py_INCREF(r);
    }
7831
    else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7832
        r = PySequence_GetItem(o, i);
7833
    }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7834
    else {
7835
        r = __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7836 7837 7838 7839
    }
    return r;
}
""",
7840 7841
impl = """
""")
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7842

7843 7844


Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7845 7846
#------------------------------------------------------------------------------------

7847 7848
setitem_int_utility_code = UtilityCode(
proto = """
7849 7850
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_SetItemInt_Fast(o, i, v) : \\
7851 7852
                                                    __Pyx_SetItemInt_Generic(o, to_py_func(i), v))

7853
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7854
    int r;
7855 7856 7857 7858 7859 7860
    if (!j) return -1;
    r = PyObject_SetItem(o, j, v);
    Py_DECREF(j);
    return r;
}

7861
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
Stefan Behnel's avatar
Stefan Behnel committed
7862
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7863
        Py_INCREF(v);
7864
        Py_DECREF(PyList_GET_ITEM(o, i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7865 7866 7867
        PyList_SET_ITEM(o, i, v);
        return 1;
    }
7868 7869
    else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
        return PySequence_SetItem(o, i, v);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7870
    else {
7871
        PyObject *j = PyInt_FromSsize_t(i);
7872
        return __Pyx_SetItemInt_Generic(o, j, v);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
7873 7874 7875
    }
}
""",
7876 7877 7878
impl = """
""")

7879 7880
#------------------------------------------------------------------------------------

7881 7882
delitem_int_utility_code = UtilityCode(
proto = """
7883 7884
#define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_DelItemInt_Fast(o, i) : \\
7885 7886
                                                    __Pyx_DelItem_Generic(o, to_py_func(i)))

7887
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
7888
    int r;
7889 7890 7891 7892 7893 7894
    if (!j) return -1;
    r = PyObject_DelItem(o, j);
    Py_DECREF(j);
    return r;
}

7895
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
7896 7897
    if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
        return PySequence_DelItem(o, i);
7898
    else {
7899
        PyObject *j = PyInt_FromSsize_t(i);
7900
        return __Pyx_DelItem_Generic(o, j);
7901 7902 7903 7904 7905 7906 7907 7908
    }
}
""",
impl = """
""")

#------------------------------------------------------------------------------------

7909 7910
raise_too_many_values_to_unpack = UtilityCode(
proto = """
7911
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
7912 7913
""",
impl = '''
7914 7915 7916 7917 7918 7919 7920
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
    PyErr_Format(PyExc_ValueError,
        #if PY_VERSION_HEX < 0x02050000
            "too many values to unpack (expected %d)", (int)expected);
        #else
            "too many values to unpack (expected %zd)", expected);
        #endif
7921 7922 7923 7924 7925
}
''')

raise_need_more_values_to_unpack = UtilityCode(
proto = """
7926
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
7927 7928
""",
impl = '''
7929
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941
    PyErr_Format(PyExc_ValueError,
        #if PY_VERSION_HEX < 0x02050000
                 "need more than %d value%s to unpack", (int)index,
        #else
                 "need more than %zd value%s to unpack", index,
        #endif
                 (index == 1) ? "" : "s");
}
''')

#------------------------------------------------------------------------------------

7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952
tuple_unpacking_error_code = UtilityCode(
proto = """
static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
""", 
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 {
7953
      __Pyx_RaiseTooManyValuesError(index);
7954 7955 7956 7957 7958 7959 7960 7961
    }
}
""", 
requires = [raise_none_iter_error_utility_code,
            raise_need_more_values_to_unpack,
            raise_too_many_values_to_unpack]
)

7962 7963 7964
unpacking_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
7965
static int __Pyx_EndUnpack(PyObject *, Py_ssize_t expected); /*proto*/
7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977
""",
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;
}

7978
static int __Pyx_EndUnpack(PyObject *iter, Py_ssize_t expected) {
7979 7980 7981
    PyObject *item;
    if ((item = PyIter_Next(iter))) {
        Py_DECREF(item);
7982
        __Pyx_RaiseTooManyValuesError(expected);
7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993
        return -1;
    }
    else if (!PyErr_Occurred())
        return 0;
    else
        return -1;
}
""",
requires = [raise_need_more_values_to_unpack,
            raise_too_many_values_to_unpack]
)
Robert Bradshaw's avatar
Robert Bradshaw committed
7994

7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006
#------------------------------------------------------------------------------------

# 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;
8007
    if (likely(PyDict_Check(kwargs))) {
8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021
        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 */
    }
}
""", 
)

Robert Bradshaw's avatar
Robert Bradshaw committed
8022 8023 8024 8025 8026

#------------------------------------------------------------------------------------

int_pow_utility_code = UtilityCode(
proto="""
8027
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
8028 8029
""",
impl="""
8030
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
Robert Bradshaw's avatar
Robert Bradshaw committed
8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051
    %(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;
}
""")
8052 8053 8054

# ------------------------------ Division ------------------------------------

8055 8056
div_int_utility_code = UtilityCode(
proto="""
8057
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
8058 8059
""",
impl="""
8060
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
8061 8062 8063 8064 8065
    %(type)s q = a / b;
    %(type)s r = a - q*b;
    q -= ((r != 0) & ((r ^ b) < 0));
    return q;
}
8066 8067
""")

8068
mod_int_utility_code = UtilityCode(
8069
proto="""
8070
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
8071 8072
""",
impl="""
8073
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
8074 8075 8076
    %(type)s r = a %% b;
    r += ((r != 0) & ((r ^ b) < 0)) * b;
    return r;
8077 8078 8079
}
""")

8080
mod_float_utility_code = UtilityCode(
8081
proto="""
8082
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
8083 8084
""",
impl="""
8085
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
8086 8087 8088
    %(type)s r = fmod%(math_h_modifier)s(a, b);
    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
    return r;
8089 8090
}
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
8091

8092
cdivision_warning_utility_code = UtilityCode(
Robert Bradshaw's avatar
Robert Bradshaw committed
8093
proto="""
8094
static int __Pyx_cdivision_warning(void); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
8095 8096
""",
impl="""
8097 8098 8099 8100 8101
static int __Pyx_cdivision_warning(void) {
    return PyErr_WarnExplicit(PyExc_RuntimeWarning, 
                              "division with oppositely signed operands, C and Python semantics differ",
                              %(FILENAME)s, 
                              %(LINENO)s,
8102
                              __Pyx_MODULE_NAME,
8103
                              NULL);
Robert Bradshaw's avatar
Robert Bradshaw committed
8104
}
8105 8106 8107 8108
""" % {
    'FILENAME': Naming.filename_cname,
    'LINENO':  Naming.lineno_cname,
})
8109 8110 8111 8112 8113 8114 8115

# from intobject.c
division_overflow_test_code = UtilityCode(
proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x)	\
	(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144


binding_cfunc_utility_code = UtilityCode(
proto="""
#define %(binding_cfunc)s_USED 1

typedef struct {
    PyCFunctionObject func;
} %(binding_cfunc)s_object;

PyTypeObject %(binding_cfunc)s_type;
PyTypeObject *%(binding_cfunc)s = NULL;

PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
#define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)

int %(binding_cfunc)s_init(void); /* proto */
""" % Naming.__dict__,
impl="""

PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
	%(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
    if (op == NULL)
        return NULL;
	op->func.m_ml = ml;
	Py_XINCREF(self);
	op->func.m_self = self;
	Py_XINCREF(module);
	op->func.m_module = module;
8145
	PyObject_GC_Track(op);
Robert Bradshaw's avatar
Robert Bradshaw committed
8146 8147 8148 8149
	return (PyObject *)op;
}

static void %(binding_cfunc)s_dealloc(%(binding_cfunc)s_object *m) {
8150
	PyObject_GC_UnTrack(m);
Robert Bradshaw's avatar
Robert Bradshaw committed
8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163
	Py_XDECREF(m->func.m_self);
	Py_XDECREF(m->func.m_module);
    PyObject_GC_Del(m);
}

static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyObject *type) {
	if (obj == Py_None)
		obj = NULL;
	return PyMethod_New(func, obj, type);
}

int %(binding_cfunc)s_init(void) {
    %(binding_cfunc)s_type = PyCFunction_Type;
8164
    %(binding_cfunc)s_type.tp_name = __Pyx_NAMESTR("cython_binding_builtin_function_or_method");
Robert Bradshaw's avatar
Robert Bradshaw committed
8165 8166 8167 8168 8169 8170 8171 8172 8173 8174
    %(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;
    %(binding_cfunc)s_type.tp_descr_get = %(binding_cfunc)s_descr_get;
    if (PyType_Ready(&%(binding_cfunc)s_type) < 0) {
        return -1;
    }
    %(binding_cfunc)s = &%(binding_cfunc)s_type;
    return 0;

}
""" % Naming.__dict__)