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

5
import operator
William Stein's avatar
William Stein committed
6

Robert Bradshaw's avatar
Robert Bradshaw committed
7
from Errors import error, warning, warn_once, InternalError
8
from Errors import hold_errors, release_errors, held_errors, report_error
9
from Code import UtilityCode
10
import StringEncoding
William Stein's avatar
William Stein committed
11
import Naming
Robert Bradshaw's avatar
Robert Bradshaw committed
12
import Nodes
William Stein's avatar
William Stein committed
13 14
from Nodes import Node
import PyrexTypes
15
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
16 17
from Builtin import list_type, tuple_type, set_type, dict_type, \
     unicode_type, str_type, bytes_type, type_type
18
import Builtin
William Stein's avatar
William Stein committed
19 20
import Symtab
import Options
21
from Annotate import AnnotationItem
William Stein's avatar
William Stein committed
22

William Stein's avatar
William Stein committed
23
from Cython.Debugging import print_call_chain
William Stein's avatar
William Stein committed
24 25 26
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
    debug_coercion

27 28 29 30 31
try:
    set
except NameError:
    from sets import Set as set

32 33
class NotConstant(object): pass # just for the name
not_a_constant = NotConstant()
34
constant_value_not_set = object()
35

36 37 38 39 40 41 42 43 44 45
# 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.",
46
    (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
47 48 49 50 51
    (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
52 53 54 55 56 57 58 59
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
60
    #  is_starred   boolean      Is a starred expression (e.g. '*a')
William Stein's avatar
William Stein committed
61 62 63
    #  saved_subexpr_nodes
    #               [ExprNode or [ExprNode or None] or None]
    #                            Cached result of subexpr_nodes()
64
    #  use_managed_ref boolean   use ref-counted temps/assignments/etc.
William Stein's avatar
William Stein committed
65 66
    
    result_ctype = None
67
    type = None
68 69
    temp_code = None
    old_temp = None # error checker for multiple frees etc.
70
    use_managed_ref = True # can be set by optimisation transforms
William Stein's avatar
William Stein committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 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

    #  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.
    #
125 126 127 128
    #      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
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
    #
    #      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
157
    #        is provided which uses the following abstract methods:
William Stein's avatar
William Stein committed
158 159 160 161 162 163
    #
    #          generate_result_code
    #            - Generate any C statements necessary to calculate
    #              the result of this node from the results of its
    #              sub-expressions.
    #
164 165 166 167 168
    #          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
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    #      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
190
    is_target = 0
191
    is_starred = 0
William Stein's avatar
William Stein committed
192

193 194
    constant_result = constant_value_not_set

195 196 197 198 199 200 201
    try:
        _get_child_attrs = operator.attrgetter('subexprs')
    except AttributeError:
        # Python 2.3
        def _get_child_attrs(self):
            return self.subexprs
    child_attrs = property(fget=_get_child_attrs)
202
        
William Stein's avatar
William Stein committed
203 204 205 206
    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
207
                (self.__class__.__name__, method_name))
William Stein's avatar
William Stein committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
                
    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.
223 224 225
        nodes = []
        for name in self.subexprs:
            item = getattr(self, name)
Stefan Behnel's avatar
Stefan Behnel committed
226 227
            if item is not None:
                if type(item) is list:
228
                    nodes.extend(item)
Stefan Behnel's avatar
Stefan Behnel committed
229 230
                else:
                    nodes.append(item)
231
        return nodes
232 233
        
    def result(self):
234 235 236
        if self.is_temp:
            return self.temp_code
        else:
237
            return self.calculate_result_code()
William Stein's avatar
William Stein committed
238 239 240
    
    def result_as(self, type = None):
        #  Return the result code cast to the specified C type.
241
        return typecast(type, self.ctype(), self.result())
William Stein's avatar
William Stein committed
242 243 244 245 246 247 248 249 250
    
    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
251

252
    def get_constant_c_result_code(self):
253
        # Return the constant value of this node as a result code
254 255 256 257 258 259 260
        # 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.
261 262
        return None

263
    def calculate_constant_result(self):
264 265 266 267 268
        # 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.
269 270 271 272 273 274
        #
        # 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

275 276 277 278
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

279 280 281 282 283 284 285 286
    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
287 288 289 290 291 292 293 294 295 296 297 298 299
    # ------------- 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)
300
        return self.check_const()
William Stein's avatar
William Stein committed
301 302 303 304 305 306 307
    
    def analyse_expressions(self, env):
        #  Convenience routine performing both the Type
        #  Analysis and Temp Allocation phases for a whole 
        #  expression.
        self.analyse_types(env)
    
308
    def analyse_target_expression(self, env, rhs):
William Stein's avatar
William Stein committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
        #  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
329 330
        return self.coerce_to_boolean(env).coerce_to_simple(env)

331 332
    # --------------- Type Inference -----------------
    
Robert Bradshaw's avatar
Robert Bradshaw committed
333
    def type_dependencies(self, env):
334 335 336 337
        # 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
338
        return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
339 340 341 342 343 344 345 346 347 348 349 350 351
    
    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
352 353 354 355 356 357
    # --------------- 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
358 359 360 361 362
        
    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
363 364 365 366 367 368 369 370 371 372 373
    
    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)
374

375
    def nogil_check(self, env):
376 377 378 379
        # 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:
380
            self.gil_error()
381

382 383 384 385
    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
386 387
    def check_const(self):
        self.not_const()
388
        return False
William Stein's avatar
William Stein committed
389 390 391 392 393 394
    
    def not_const(self):
        error(self.pos, "Not allowed in a constant expression")
    
    def check_const_addr(self):
        self.addr_not_const()
395
        return False
William Stein's avatar
William Stein committed
396 397 398
    
    def addr_not_const(self):
        error(self.pos, "Address is not constant")
399

William Stein's avatar
William Stein committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    # ----------------- 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
416 417 418
#    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
419

420 421
    def allocate_temp_result(self, code):
        if self.temp_code:
422
            raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
423 424 425 426 427
        type = self.type
        if not type.is_void:
            if type.is_pyobject:
                type = PyrexTypes.py_object_type
            self.temp_code = code.funcstate.allocate_temp(
428
                type, manage_ref=self.use_managed_ref)
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
        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
444 445 446 447 448 449
    # ---------------- 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():
450
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
451 452
    
    def generate_evaluation_code(self, code):
453
        code.mark_pos(self.pos)
454
        
William Stein's avatar
William Stein committed
455 456 457 458
        #  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)
459 460 461 462

        if self.is_temp:
            self.allocate_temp_result(code)

William Stein's avatar
William Stein committed
463 464
        self.generate_result_code(code)
        if self.is_temp:
465 466
            # 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
467
            self.generate_subexpr_disposal_code(code)
468
            self.free_subexpr_temps(code)
469

William Stein's avatar
William Stein committed
470 471 472 473 474 475 476
    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")
    
477 478 479 480
    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
481
        else:
482
            # Already done if self.is_temp
483
            self.generate_subexpr_disposal_code(code)
484

William Stein's avatar
William Stein committed
485 486 487 488 489 490 491 492 493
    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:
494
                code.putln("%s = 0;" % self.result())
William Stein's avatar
William Stein committed
495 496
        else:
            self.generate_subexpr_disposal_code(code)
497

William Stein's avatar
William Stein committed
498 499 500 501 502 503 504 505 506 507 508
    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
509 510

    def free_temps(self, code):
511 512 513 514
        if self.is_temp:
            if not self.type.is_void:
                self.release_temp_result(code)
        else:
515
            self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
516
    
517 518 519 520
    def free_subexpr_temps(self, code):
        for sub in self.subexpr_nodes():
            sub.free_temps(code)

521 522 523 524 525 526
    # ---------------- Annotation ---------------------
    
    def annotate(self, code):
        for node in self.subexpr_nodes():
            node.annotate(code)
    
William Stein's avatar
William Stein committed
527 528 529 530 531 532 533 534 535 536
    # ----------------- 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.
537 538 539 540 541 542 543 544
        #
        #   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
545 546 547 548
        src = self
        src_type = self.type
        src_is_py_type = src_type.is_pyobject
        dst_is_py_type = dst_type.is_pyobject
549

550 551 552
        if self.check_for_coercion_error(dst_type):
            return self

William Stein's avatar
William Stein committed
553 554
        if dst_type.is_pyobject:
            if not src.type.is_pyobject:
555 556 557 558
                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
559
            if not src.type.subtype_of(dst_type):
560 561
                if not isinstance(src, NoneNode):
                    src = PyTypeTestNode(src, dst_type, env)
William Stein's avatar
William Stein committed
562 563
        elif src.type.is_pyobject:
            src = CoerceFromPyTypeNode(dst_type, src, env)
564
        elif (dst_type.is_complex 
565 566
              and src_type != dst_type
              and dst_type.assignable_from(src_type)):
567
            src = CoerceToComplexNode(src, dst_type, env)
William Stein's avatar
William Stein committed
568
        else: # neither src nor dst are py types
569
            # Added the string comparison, since for c types that
570
            # is enough, but Cython gets confused when the types are
571
            # in different pxi files.
572
            if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
573
                self.fail_assignment(dst_type)
William Stein's avatar
William Stein committed
574 575
        return src

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
    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
591 592 593 594 595 596
    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.
597 598 599 600 601 602 603

        # 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
604 605 606 607
        type = self.type
        if type.is_pyobject or type.is_ptr or type.is_float:
            return CoerceToBooleanNode(self, env)
        else:
608
            if not (type.is_int or type.is_enum or type.is_error):
William Stein's avatar
William Stein committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
                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()
640 641 642 643

    def may_be_none(self):
        return self.type.is_pyobject

644
    def as_cython_attribute(self):
645
        return None
William Stein's avatar
William Stein committed
646

647
    def as_none_safe_node(self, message, error="PyExc_TypeError"):
648 649 650 651 652 653 654 655
        # 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
656
class AtomicExprNode(ExprNode):
657 658 659 660 661 662
    #  Abstract base class for expression nodes which have
    #  no sub-expressions.
    
    subexprs = []

    # Override to optimize -- we know we have no children
663 664 665 666
    def generate_subexpr_evaluation_code(self, code):
        pass
    def generate_subexpr_disposal_code(self, code):
        pass
667

668
class PyConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
669 670
    #  Abstract base class for constant Python values.
    
671
    is_literal = 1
672
    type = py_object_type
673
    
William Stein's avatar
William Stein committed
674 675
    def is_simple(self):
        return 1
676 677 678 679

    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
680
    def analyse_types(self, env):
681
        pass
William Stein's avatar
William Stein committed
682 683 684 685 686 687 688 689 690 691 692 693
    
    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"
694 695

    constant_result = None
696 697
    
    nogil_check = None
698

699 700
    def compile_time_value(self, denv):
        return None
701 702 703 704 705

    def may_be_none(self):
        return True


William Stein's avatar
William Stein committed
706 707 708 709 710
class EllipsisNode(PyConstNode):
    #  '...' in a subscript list.
    
    value = "Py_Ellipsis"

711 712
    constant_result = Ellipsis

713 714 715
    def compile_time_value(self, denv):
        return Ellipsis

William Stein's avatar
William Stein committed
716

717
class ConstNode(AtomicExprNode):
William Stein's avatar
William Stein committed
718 719 720 721 722
    # Abstract base type for literal constant nodes.
    #
    # value     string      C code fragment
    
    is_literal = 1
723
    nogil_check = None
724

William Stein's avatar
William Stein committed
725 726
    def is_simple(self):
        return 1
727 728 729 730

    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
731 732 733 734
    def analyse_types(self, env):
        pass # Types are held in class variables
    
    def check_const(self):
735
        return True
William Stein's avatar
William Stein committed
736
    
737
    def get_constant_c_result_code(self):
738 739
        return self.calculate_result_code()

William Stein's avatar
William Stein committed
740 741 742 743 744 745 746
    def calculate_result_code(self):
        return str(self.value)

    def generate_result_code(self, code):
        pass


747 748 749
class BoolNode(ConstNode):
    type = PyrexTypes.c_bint_type
    #  The constant value True or False
750 751 752 753

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

754 755 756 757
    def compile_time_value(self, denv):
        return self.value
    
    def calculate_result_code(self):
758
        return str(int(self.value))
759

760

William Stein's avatar
William Stein committed
761 762
class NullNode(ConstNode):
    type = PyrexTypes.c_null_ptr_type
763
    value = "NULL"
764
    constant_result = 0
William Stein's avatar
William Stein committed
765

766
    def get_constant_c_result_code(self):
767 768
        return self.value

William Stein's avatar
William Stein committed
769 770 771

class CharNode(ConstNode):
    type = PyrexTypes.c_char_type
772 773 774

    def calculate_constant_result(self):
        self.constant_result = ord(self.value)
William Stein's avatar
William Stein committed
775
    
776
    def compile_time_value(self, denv):
777
        return ord(self.value)
778
    
William Stein's avatar
William Stein committed
779
    def calculate_result_code(self):
780
        return "'%s'" % StringEncoding.escape_char(self.value)
William Stein's avatar
William Stein committed
781 782 783


class IntNode(ConstNode):
784 785 786 787 788 789

    # unsigned     "" or "U"
    # longness     "" or "L" or "LL"

    unsigned = ""
    longness = ""
William Stein's avatar
William Stein committed
790 791
    type = PyrexTypes.c_long_type

792
    def coerce_to(self, dst_type, env):
793
        if self.type is dst_type:
794
            return self
795 796 797 798
        node = IntNode(self.pos, value=self.value,
                       unsigned=self.unsigned, longness=self.longness)
        if dst_type.is_numeric and not dst_type.is_complex:
            return node
799
        if dst_type.is_pyobject:
800
            node.type = PyrexTypes.py_object_type
801 802 803
        # 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.
804 805
        return ConstNode.coerce_to(node, dst_type, env)

806
    def coerce_to_boolean(self, env):
807 808 809 810
        return IntNode(
            self.pos, value=self.value,
            type = PyrexTypes.c_bint_type,
            unsigned=self.unsigned, longness=self.longness)
811

812
    def generate_evaluation_code(self, code):
813
        if self.type.is_pyobject:
814
            # pre-allocate a Python version of the number
815
            self.result_code = code.get_py_num(self.value, self.longness)
816
        else:
817
            self.result_code = self.get_constant_c_result_code()
818
    
819
    def get_constant_c_result_code(self):
820
        return str(self.value) + self.unsigned + self.longness
821 822 823

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

825 826 827
    def calculate_constant_result(self):
        self.constant_result = int(self.value, 0)

828
    def compile_time_value(self, denv):
829
        return int(self.value, 0)
830 831


William Stein's avatar
William Stein committed
832 833 834
class FloatNode(ConstNode):
    type = PyrexTypes.c_double_type

835
    def calculate_constant_result(self):
836
        self.constant_result = float(self.value)
837

838 839
    def compile_time_value(self, denv):
        return float(self.value)
Stefan Behnel's avatar
Stefan Behnel committed
840 841
    
    def calculate_result_code(self):
842
        strval = repr(float(self.value))
Stefan Behnel's avatar
Stefan Behnel committed
843
        if strval == 'nan':
844
            return "(Py_HUGE_VAL * 0)"
Stefan Behnel's avatar
Stefan Behnel committed
845
        elif strval == 'inf':
846
            return "Py_HUGE_VAL"
Stefan Behnel's avatar
Stefan Behnel committed
847
        elif strval == '-inf':
848
            return "(-Py_HUGE_VAL)"
Stefan Behnel's avatar
Stefan Behnel committed
849 850
        else:
            return strval
851

William Stein's avatar
William Stein committed
852

853
class BytesNode(ConstNode):
854 855 856 857
    # A char* or bytes literal
    #
    # value      BytesLiteral

William Stein's avatar
William Stein committed
858
    type = PyrexTypes.c_char_ptr_type
859 860

    def compile_time_value(self, denv):
861
        return self.value
862

863
    def analyse_as_type(self, env):
864 865 866
        type = PyrexTypes.parse_basic_type(self.value)
        if type is not None:    
            return type
867 868 869 870 871 872 873
        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
874

875 876 877
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

878 879 880 881 882
    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
883
    def coerce_to(self, dst_type, env):
884
        if dst_type.is_int:
885
            if not self.can_coerce_to_char_literal():
886 887 888 889
                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.")
890
                return self
891 892
            return CharNode(self.pos, value=self.value)

893 894 895 896 897 898 899 900
        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)

901 902
        if not self.type.is_pyobject:
            if dst_type in (py_object_type, Builtin.bytes_type):
903
                node.type = Builtin.bytes_type
904
            elif dst_type.is_pyobject:
905 906 907 908
                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)
909
            return node
910

William Stein's avatar
William Stein committed
911 912 913 914 915 916
        # 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):
917
        # Return a new BytesNode with the same value as this node
William Stein's avatar
William Stein committed
918
        # but whose type is a Python type instead of a C type.
919
        return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
920 921

    def generate_evaluation_code(self, code):
William Stein's avatar
William Stein committed
922
        if self.type.is_pyobject:
923
            self.result_code = code.get_py_string_const(self.value)
William Stein's avatar
William Stein committed
924
        else:
925
            self.result_code = code.get_string_const(self.value)
926

927
    def get_constant_c_result_code(self):
928
        return None # FIXME
929 930 931
    
    def calculate_result_code(self):
        return self.result_code
William Stein's avatar
William Stein committed
932

933

934
class UnicodeNode(PyConstNode):
935 936 937
    # A Python unicode object
    #
    # value    EncodedString
Robert Bradshaw's avatar
Robert Bradshaw committed
938

939
    type = unicode_type
940

941
    def coerce_to(self, dst_type, env):
942 943
        if dst_type is self.type:
            pass
944 945 946 947 948 949
        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)
950
        elif not dst_type.is_pyobject:
951
            error(self.pos, "Unicode literals do not support coercion to C types other than Py_UNICODE.")
952 953 954 955
        elif dst_type is not py_object_type:
            if not self.check_for_coercion_error(dst_type):
                self.fail_assignment(dst_type)
        return self
956

957 958 959
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

960
    def generate_evaluation_code(self, code):
961
        self.result_code = code.get_py_string_const(self.value)
962 963 964

    def calculate_result_code(self):
        return self.result_code
965 966 967
        
    def compile_time_value(self, env):
        return self.value
968 969


970 971 972 973
class StringNode(PyConstNode):
    # A Python str object, i.e. a byte string in Python 2.x and a
    # unicode string in Python 3.x
    #
974
    # value          BytesLiteral or EncodedString
975
    # is_identifier  boolean
976

977
    type = str_type
978
    is_identifier = None
979

980
    def coerce_to(self, dst_type, env):
981
        if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
982 983 984 985 986
#            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)
987
            self.check_for_coercion_error(dst_type, fail=True)
988 989

        # this will be a unicode string in Py3, so make sure we can decode it
990 991
        if self.value.encoding:
            encoding = self.value.encoding
992 993 994 995
            try:
                self.value.decode(encoding)
            except UnicodeDecodeError:
                error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
996

997
        return self
998

999 1000 1001
    def can_coerce_to_char_literal(self):
        return not self.is_identifier and len(self.value) == 1

1002
    def generate_evaluation_code(self, code):
1003 1004
        self.result_code = code.get_py_string_const(
            self.value, identifier=self.is_identifier, is_str=True)
1005

1006
    def get_constant_c_result_code(self):
1007 1008
        return None

1009
    def calculate_result_code(self):
1010
        return self.result_code
1011 1012 1013
        
    def compile_time_value(self, env):
        return self.value
1014 1015


1016 1017 1018 1019 1020 1021
class IdentifierStringNode(StringNode):
    # A special str value that represents an identifier (bytes in Py2,
    # unicode in Py3).
    is_identifier = True


1022
class LongNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1023 1024 1025
    #  Python long integer literal
    #
    #  value   string
1026

1027 1028
    type = py_object_type

1029 1030
    def calculate_constant_result(self):
        self.constant_result = long(self.value)
William Stein's avatar
William Stein committed
1031
    
1032 1033 1034
    def compile_time_value(self, denv):
        return long(self.value)
    
William Stein's avatar
William Stein committed
1035 1036
    def analyse_types(self, env):
        self.is_temp = 1
1037

1038 1039 1040
    def may_be_none(self):
        return False

1041 1042
    gil_message = "Constructing Python long int"

1043
    def generate_result_code(self, code):
William Stein's avatar
William Stein committed
1044
        code.putln(
1045
            '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1046
                self.result(),
William Stein's avatar
William Stein committed
1047
                self.value,
1048
                code.error_goto_if_null(self.result(), self.pos)))
1049
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1050 1051


1052
class ImagNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1053 1054 1055
    #  Imaginary number literal
    #
    #  value   float    imaginary part
1056 1057
    
    type = PyrexTypes.c_double_complex_type
1058 1059 1060

    def calculate_constant_result(self):
        self.constant_result = complex(0.0, self.value)
William Stein's avatar
William Stein committed
1061
    
1062 1063 1064
    def compile_time_value(self, denv):
        return complex(0.0, self.value)
    
William Stein's avatar
William Stein committed
1065
    def analyse_types(self, env):
1066 1067
        self.type.create_declaration_utility_code(env)

1068 1069 1070
    def may_be_none(self):
        return False

1071
    def coerce_to(self, dst_type, env):
1072 1073 1074
        if self.type is dst_type:
            return self
        node = ImagNode(self.pos, value=self.value)
1075
        if dst_type.is_pyobject:
1076 1077
            node.is_temp = 1
            node.type = PyrexTypes.py_object_type
1078 1079 1080
        # 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.
1081
        return AtomicExprNode.coerce_to(node, dst_type, env)
1082 1083 1084

    gil_message = "Constructing complex number"

1085 1086 1087 1088 1089 1090
    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))

1091
    def generate_result_code(self, code):
1092 1093 1094 1095 1096 1097 1098
        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())
1099
        
William Stein's avatar
William Stein committed
1100

Danilo Freitas's avatar
Danilo Freitas committed
1101
class NewExprNode(AtomicExprNode):
1102 1103 1104

    # C++ new statement
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1105 1106 1107
    # cppclass              node                 c++ class to create
    
    type = None
Danilo Freitas's avatar
Danilo Freitas committed
1108
    
1109
    def infer_type(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1110 1111
        type = self.cppclass.analyse_as_type(env)
        if type is None or not type.is_cpp_class:
Danilo Freitas's avatar
Danilo Freitas committed
1112
            error(self.pos, "new operator can only be applied to a C++ class")
Robert Bradshaw's avatar
Robert Bradshaw committed
1113
            self.type = error_type
Danilo Freitas's avatar
Danilo Freitas committed
1114
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
1115
        self.cpp_check(env)
1116
        constructor = type.scope.lookup(u'<init>')
Danilo Freitas's avatar
Danilo Freitas committed
1117
        if constructor is None:
1118 1119
            return_type = PyrexTypes.CFuncType(type, [])
            return_type = PyrexTypes.CPtrType(return_type)
1120 1121
            type.scope.declare_cfunction(u'<init>', return_type, self.pos)
            constructor = type.scope.lookup(u'<init>')
1122
        self.class_type = type
DaniloFreitas's avatar
DaniloFreitas committed
1123
        self.entry = constructor
Robert Bradshaw's avatar
Robert Bradshaw committed
1124
        self.type = constructor.type
1125 1126 1127
        return self.type
    
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1128 1129
        if self.type is None:
            self.infer_type(env)
1130 1131 1132 1133

    def may_be_none(self):
        return False

Danilo Freitas's avatar
Danilo Freitas committed
1134 1135
    def generate_result_code(self, code):
        pass
Danilo Freitas's avatar
Danilo Freitas committed
1136
   
Danilo Freitas's avatar
Danilo Freitas committed
1137
    def calculate_result_code(self):
1138
        return "new " + self.class_type.declaration_code("")
Danilo Freitas's avatar
Danilo Freitas committed
1139

William Stein's avatar
William Stein committed
1140

1141
class NameNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1142 1143 1144 1145
    #  Reference to a local or global variable name.
    #
    #  name            string    Python name of the variable
    #  entry           Entry     Symbol table entry
1146
    #  type_entry      Entry     For extension type names, the original type entry
William Stein's avatar
William Stein committed
1147
    
1148 1149
    is_name = True
    is_cython_module = False
Robert Bradshaw's avatar
Robert Bradshaw committed
1150
    cython_attribute = None
1151
    lhs_of_first_assignment = False
1152
    is_used_as_rvalue = 0
1153
    entry = None
1154
    type_entry = None
1155 1156 1157 1158 1159

    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
1160
        
1161
    def as_cython_attribute(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
1162
        return self.cython_attribute
1163 1164
    
    create_analysed_rvalue = staticmethod(create_analysed_rvalue)
William Stein's avatar
William Stein committed
1165
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
    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
1179 1180 1181
        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
1182
            # is used for the pointer to the type they represent.
1183
            return type_type
Robert Bradshaw's avatar
Robert Bradshaw committed
1184 1185
        else:
            return self.entry.type
1186
    
1187 1188 1189 1190
    def compile_time_value(self, denv):
        try:
            return denv.lookup(self.name)
        except KeyError:
Stefan Behnel's avatar
Stefan Behnel committed
1191
            error(self.pos, "Compile-time name '%s' not defined" % self.name)
1192 1193 1194 1195 1196

    def get_constant_c_result_code(self):
        if not self.entry or self.entry.type.is_pyobject:
            return None
        return self.entry.cname
1197 1198 1199 1200 1201 1202 1203 1204
    
    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
1205
            if entry and entry.is_cfunction:
1206 1207
                var_entry = entry.as_variable
                if var_entry:
1208 1209
                    if var_entry.is_builtin and Options.cache_builtins:
                        var_entry = env.declare_builtin(var_entry.name, self.pos)
1210 1211 1212 1213
                    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
1214
        return super(NameNode, self).coerce_to(dst_type, env)
1215
    
William Stein's avatar
William Stein committed
1216 1217 1218
    def analyse_as_module(self, env):
        # Try to interpret this as a reference to a cimported module.
        # Returns the module scope, or None.
1219 1220 1221
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1222 1223 1224
        if entry and entry.as_module:
            return entry.as_module
        return None
1225 1226
        
    def analyse_as_type(self, env):
1227 1228 1229 1230
        if self.cython_attribute:
            type = PyrexTypes.parse_basic_type(self.cython_attribute)
        else:
            type = PyrexTypes.parse_basic_type(self.name)
1231 1232
        if type:
            return type
1233 1234 1235 1236 1237 1238 1239
        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
1240 1241 1242 1243
    
    def analyse_as_extension_type(self, env):
        # Try to interpret this as a reference to an extension type.
        # Returns the extension type, or None.
1244 1245 1246
        entry = self.entry
        if not entry:
            entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1247
        if entry and entry.is_type and entry.type.is_extension_type:
1248 1249 1250
            return entry.type
        else:
            return None
William Stein's avatar
William Stein committed
1251 1252
    
    def analyse_target_declaration(self, env):
1253 1254
        if not self.entry:
            self.entry = env.lookup_here(self.name)
William Stein's avatar
William Stein committed
1255
        if not self.entry:
1256 1257
            if env.directives['warn.undeclared']:
                warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1258
            if env.directives['infer_types'] != False:
1259 1260 1261 1262
                type = unspecified_type
            else:
                type = py_object_type
            self.entry = env.declare_var(self.name, type, self.pos)
1263
        env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
Robert Bradshaw's avatar
Robert Bradshaw committed
1264
        env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1265 1266
        if self.entry.is_declared_generic:
            self.result_ctype = py_object_type
William Stein's avatar
William Stein committed
1267
    
1268 1269 1270
    def analyse_types(self, env):
        if self.entry is None:
            self.entry = env.lookup(self.name)
William Stein's avatar
William Stein committed
1271 1272
        if not self.entry:
            self.entry = env.declare_builtin(self.name, self.pos)
1273 1274 1275
        if not self.entry:
            self.type = PyrexTypes.error_type
            return
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1276 1277 1278 1279 1280 1281 1282 1283
        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)
1284 1285 1286
        self.analyse_rvalue_entry(env)
        
    def analyse_target_types(self, env):
William Stein's avatar
William Stein committed
1287
        self.analyse_entry(env)
1288 1289 1290 1291
        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
1292
        self.entry.used = 1
1293
        if self.entry.type.is_buffer:
1294 1295 1296
            import Buffer
            Buffer.used_buffer_aux_vars(self.entry)
                
1297 1298 1299 1300
    def analyse_rvalue_entry(self, env):
        #print "NameNode.analyse_rvalue_entry:", self.name ###
        #print "Entry:", self.entry.__dict__ ###
        self.analyse_entry(env)
1301 1302
        entry = self.entry
        if entry.is_declared_generic:
William Stein's avatar
William Stein committed
1303
            self.result_ctype = py_object_type
1304
        if entry.is_pyglobal or entry.is_builtin:
1305 1306 1307 1308
            if Options.cache_builtins and entry.is_builtin:
                self.is_temp = 0
            else:
                self.is_temp = 1
1309
                env.use_utility_code(get_name_interned_utility_code)
1310 1311
            self.is_used_as_rvalue = 1

1312
    def nogil_check(self, env):
1313 1314 1315 1316
        if self.is_used_as_rvalue:
            entry = self.entry
            if entry.is_builtin:
                # if not Options.cache_builtins: # cached builtins are ok
1317
                self.gil_error()
1318
            elif entry.is_pyglobal:
1319
                self.gil_error()
1320 1321 1322

    gil_message = "Accessing Python global or builtin"

1323 1324
    def analyse_entry(self, env):
        #print "NameNode.analyse_entry:", self.name ###
William Stein's avatar
William Stein committed
1325
        self.check_identifier_kind()
1326 1327 1328 1329
        entry = self.entry
        type = entry.type
        self.type = type

William Stein's avatar
William Stein committed
1330
    def check_identifier_kind(self):
1331 1332 1333
        # 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
1334
        entry = self.entry
1335 1336
        if entry.is_type and entry.type.is_extension_type:
            self.type_entry = entry
William Stein's avatar
William Stein committed
1337
        if not (entry.is_const or entry.is_variable 
Danilo Freitas's avatar
Danilo Freitas committed
1338 1339
            or entry.is_builtin or entry.is_cfunction
            or entry.is_cpp_class):
William Stein's avatar
William Stein committed
1340 1341 1342 1343
                if self.entry.as_variable:
                    self.entry = self.entry.as_variable
                else:
                    error(self.pos, 
1344 1345
                          "'%s' is not a constant, variable or function identifier" % self.name)

William Stein's avatar
William Stein committed
1346 1347 1348 1349 1350 1351 1352 1353 1354
    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
1355
        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
1356
            self.not_const()
1357 1358
            return False
        return True
William Stein's avatar
William Stein committed
1359 1360 1361
    
    def check_const_addr(self):
        entry = self.entry
1362
        if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
William Stein's avatar
William Stein committed
1363
            self.addr_not_const()
1364 1365
            return False
        return True
William Stein's avatar
William Stein committed
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375

    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
1376
    
William Stein's avatar
William Stein committed
1377
    def calculate_result_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
1378 1379
        entry = self.entry
        if not entry:
William Stein's avatar
William Stein committed
1380
            return "<error>" # There was an error earlier
Stefan Behnel's avatar
Stefan Behnel committed
1381
        return entry.cname
William Stein's avatar
William Stein committed
1382 1383
    
    def generate_result_code(self, code):
1384
        assert hasattr(self, 'entry')
William Stein's avatar
William Stein committed
1385 1386 1387
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1388 1389 1390
        if entry.is_builtin and Options.cache_builtins:
            return # Lookup already cached
        elif entry.is_pyglobal or entry.is_builtin:
1391 1392
            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
1393 1394 1395
            if entry.is_builtin:
                namespace = Naming.builtins_cname
            else: # entry.is_pyglobal
1396
                namespace = entry.scope.namespace_cname
1397
            code.globalstate.use_utility_code(get_name_interned_utility_code)
1398 1399
            code.putln(
                '%s = __Pyx_GetName(%s, %s); %s' % (
1400
                self.result(),
1401
                namespace, 
1402
                interned_cname,
1403
                code.error_goto_if_null(self.result(), self.pos)))
1404
            code.put_gotref(self.py_result())
1405
            
1406 1407
        elif entry.is_local and False:
            # control flow not good enough yet
Robert Bradshaw's avatar
Robert Bradshaw committed
1408
            assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1409 1410
            if assigned is False:
                error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1411
            elif not Options.init_local_none and assigned is None:
1412 1413
                code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
                           (entry.cname, entry.name, code.error_goto(self.pos)))
Robert Bradshaw's avatar
Robert Bradshaw committed
1414
                entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
William Stein's avatar
William Stein committed
1415 1416

    def generate_assignment_code(self, rhs, code):
1417
        #print "NameNode.generate_assignment_code:", self.name ###
William Stein's avatar
William Stein committed
1418 1419 1420
        entry = self.entry
        if entry is None:
            return # There was an error earlier
1421 1422 1423 1424

        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")
1425
        
1426 1427
        # 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
1428
        if entry.is_pyglobal:
1429 1430
            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
            interned_cname = code.intern_identifier(self.entry.name)
1431
            namespace = self.entry.scope.namespace_cname
1432
            if entry.is_member:
Stefan Behnel's avatar
Stefan Behnel committed
1433
                # if the entry is a member we have to cheat: SetAttr does not work
1434
                # on types, so we create a descriptor which is then added to tp_dict
1435 1436 1437
                code.put_error_if_neg(self.pos,
                    'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
                        namespace,
1438
                        interned_cname,
1439
                        rhs.py_result()))
1440 1441
                rhs.generate_disposal_code(code)
                rhs.free_temps(code)
1442
                # in Py2.6+, we need to invalidate the method cache
1443
                code.putln("PyType_Modified(%s);" %
1444
                           entry.scope.parent_type.typeptr_cname)
1445
            else: 
1446 1447 1448
                code.put_error_if_neg(self.pos,
                    'PyObject_SetAttr(%s, %s, %s)' % (
                        namespace,
1449
                        interned_cname,
1450
                        rhs.py_result()))
1451
                if debug_disposal_code:
Stefan Behnel's avatar
Stefan Behnel committed
1452 1453
                    print("NameNode.generate_assignment_code:")
                    print("...generating disposal code for %s" % rhs)
1454
                rhs.generate_disposal_code(code)
1455
                rhs.free_temps(code)
William Stein's avatar
William Stein committed
1456
        else:
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
            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)

1467
            if self.type.is_pyobject:
William Stein's avatar
William Stein committed
1468 1469 1470 1471
                #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() ###
1472 1473 1474 1475 1476
                if self.use_managed_ref:
                    rhs.make_owned_reference(code)
                    if entry.is_cglobal:
                        code.put_gotref(self.py_result())
                if self.use_managed_ref and not self.lhs_of_first_assignment:
1477 1478 1479
                    if entry.is_local and not Options.init_local_none:
                        initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
                        if initalized is True:
1480
                            code.put_decref(self.result(), self.ctype())
1481
                        elif initalized is None:
1482
                            code.put_xdecref(self.result(), self.ctype())
1483
                    else:
1484
                        code.put_decref(self.result(), self.ctype())
1485 1486 1487
                if self.use_managed_ref:
                    if entry.is_cglobal:
                        code.put_giveref(rhs.py_result())
1488
            code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
William Stein's avatar
William Stein committed
1489
            if debug_disposal_code:
Stefan Behnel's avatar
Stefan Behnel committed
1490 1491
                print("NameNode.generate_assignment_code:")
                print("...generating post-assignment code for %s" % rhs)
William Stein's avatar
William Stein committed
1492
            rhs.generate_post_assignment_code(code)
1493
            rhs.free_temps(code)
1494 1495

    def generate_acquire_buffer(self, rhs, code):
1496 1497 1498
        # 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.
1499 1500 1501 1502 1503 1504 1505
        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())))

1506 1507 1508
        buffer_aux = self.entry.buffer_aux
        bufstruct = buffer_aux.buffer_info_var.cname
        import Buffer
1509
        Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1510
                                    is_initialized=not self.lhs_of_first_assignment,
1511
                                    pos=self.pos, code=code)
1512 1513 1514 1515
        
        if not pretty_rhs:
            code.putln("%s = 0;" % rhstmp)
            code.funcstate.release_temp(rhstmp)
William Stein's avatar
William Stein committed
1516 1517 1518 1519 1520 1521 1522
    
    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
Robert Bradshaw's avatar
Robert Bradshaw committed
1523
        code.put_error_if_neg(self.pos, 
1524
            '__Pyx_DelAttrString(%s, "%s")' % (
William Stein's avatar
William Stein committed
1525
                Naming.module_cname,
Robert Bradshaw's avatar
Robert Bradshaw committed
1526
                self.entry.name))
1527 1528 1529 1530 1531 1532 1533 1534
                
    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
1535
            
1536
class BackquoteNode(ExprNode):
William Stein's avatar
William Stein committed
1537 1538 1539 1540
    #  `expr`
    #
    #  arg    ExprNode
    
1541 1542
    type = py_object_type
    
William Stein's avatar
William Stein committed
1543 1544 1545 1546 1547 1548
    subexprs = ['arg']
    
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
        self.is_temp = 1
1549 1550 1551

    gil_message = "Backquote expression"

1552 1553 1554
    def calculate_constant_result(self):
        self.constant_result = repr(self.arg.constant_result)

William Stein's avatar
William Stein committed
1555 1556
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1557
            "%s = PyObject_Repr(%s); %s" % (
1558
                self.result(),
William Stein's avatar
William Stein committed
1559
                self.arg.py_result(),
1560
                code.error_goto_if_null(self.result(), self.pos)))
1561
        code.put_gotref(self.py_result())
1562
        
William Stein's avatar
William Stein committed
1563 1564


1565
class ImportNode(ExprNode):
William Stein's avatar
William Stein committed
1566 1567 1568 1569
    #  Used as part of import statement implementation.
    #  Implements result = 
    #    __import__(module_name, globals(), None, name_list)
    #
1570 1571
    #  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
1572
    
1573 1574
    type = py_object_type
    
William Stein's avatar
William Stein committed
1575
    subexprs = ['module_name', 'name_list']
1576
    
William Stein's avatar
William Stein committed
1577 1578 1579 1580 1581
    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)
1582
            self.name_list.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
1583 1584
        self.is_temp = 1
        env.use_utility_code(import_utility_code)
1585 1586 1587

    gil_message = "Python import"

William Stein's avatar
William Stein committed
1588 1589 1590 1591 1592 1593
    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
1594
            "%s = __Pyx_Import(%s, %s); %s" % (
1595
                self.result(),
William Stein's avatar
William Stein committed
1596 1597
                self.module_name.py_result(),
                name_list_code,
1598
                code.error_goto_if_null(self.result(), self.pos)))
1599
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
1600 1601


1602
class IteratorNode(ExprNode):
William Stein's avatar
William Stein committed
1603
    #  Used as part of for statement implementation.
1604 1605 1606 1607
    #
    #  allocate_counter_temp/release_counter_temp needs to be called
    #  by parent (ForInStatNode)
    #
William Stein's avatar
William Stein committed
1608 1609 1610 1611
    #  Implements result = iter(sequence)
    #
    #  sequence   ExprNode
    
1612 1613
    type = py_object_type
    
William Stein's avatar
William Stein committed
1614 1615 1616 1617
    subexprs = ['sequence']
    
    def analyse_types(self, env):
        self.sequence.analyse_types(env)
1618 1619 1620 1621 1622 1623 1624
        if isinstance(self.sequence, SliceIndexNode) and \
               (self.sequence.base.type.is_array or self.sequence.base.type.is_ptr) \
               or self.sequence.type.is_array and self.sequence.type.size is not None:
            # C array iteration will be transformed later on
            pass
        else:
            self.sequence = self.sequence.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
1625
        self.is_temp = 1
1626 1627 1628

    gil_message = "Iterating over Python object"

1629 1630 1631 1632 1633 1634 1635
    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
1636
    def generate_result_code(self, code):
1637
        is_builtin_sequence = self.sequence.type is list_type or \
1638 1639
                              self.sequence.type is tuple_type
        may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1640 1641 1642
        if is_builtin_sequence:
            code.putln(
                "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1643
        elif may_be_a_sequence:
1644 1645 1646 1647
            code.putln(
                "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
                    self.sequence.py_result(),
                    self.sequence.py_result()))
1648 1649 1650 1651 1652 1653 1654 1655
        if may_be_a_sequence:
            code.putln(
                "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
                    self.counter_cname,
                    self.result(),
                    self.sequence.py_result(),
                    self.result()))
            code.putln("} else {")
1656 1657 1658 1659 1660 1661
        if is_builtin_sequence:
            code.putln(
                'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
                code.error_goto(self.pos))
        else:
            code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1662
                    self.counter_cname,
1663 1664 1665
                    self.result(),
                    self.sequence.py_result(),
                    code.error_goto_if_null(self.result(), self.pos)))
1666
            code.put_gotref(self.py_result())
1667 1668
        if may_be_a_sequence:
            code.putln("}")
William Stein's avatar
William Stein committed
1669 1670


1671
class NextNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1672 1673 1674 1675 1676 1677 1678
    #  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
    
1679 1680
    type = py_object_type
    
William Stein's avatar
William Stein committed
1681 1682 1683 1684 1685 1686
    def __init__(self, iterator, env):
        self.pos = iterator.pos
        self.iterator = iterator
        self.is_temp = 1
    
    def generate_result_code(self, code):
1687 1688
        sequence_type = self.iterator.sequence.type
        if sequence_type is list_type:
1689
            type_checks = [(list_type, "List")]
1690
        elif sequence_type is tuple_type:
1691
            type_checks = [(tuple_type, "Tuple")]
1692
        elif not sequence_type.is_builtin_type:
1693
            type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1694 1695
        else:
            type_checks = []
1696 1697 1698 1699 1700 1701

        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()))
1702 1703
            code.putln(
                "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1704
                    self.iterator.counter_cname,
1705
                    prefix,
1706 1707
                    self.iterator.py_result()))
            code.putln(
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1708
                "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1709
                    self.result(),
1710
                    prefix,
1711
                    self.iterator.py_result(),
1712
                    self.iterator.counter_cname,
1713
                    self.result(),
1714
                    self.iterator.counter_cname))
1715 1716 1717 1718
            if len(type_checks) > 1:
                code.put("} else ")
        if len(type_checks) == 1:
            return
1719
        code.putln("{")
William Stein's avatar
William Stein committed
1720 1721
        code.putln(
            "%s = PyIter_Next(%s);" % (
1722
                self.result(),
William Stein's avatar
William Stein committed
1723 1724 1725
                self.iterator.py_result()))
        code.putln(
            "if (!%s) {" %
1726
                self.result())
1727
        code.putln(code.error_goto_if_PyErr(self.pos))
Robert Bradshaw's avatar
Robert Bradshaw committed
1728 1729
        code.putln("break;")
        code.putln("}")
1730
        code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
1731
        code.putln("}")
1732

William Stein's avatar
William Stein committed
1733

1734
class ExcValueNode(AtomicExprNode):
William Stein's avatar
William Stein committed
1735 1736 1737 1738
    #  Node created during analyse_types phase
    #  of an ExceptClauseNode to fetch the current
    #  exception value.
    
1739 1740
    type = py_object_type
    
1741
    def __init__(self, pos, env):
William Stein's avatar
William Stein committed
1742
        ExprNode.__init__(self, pos)
1743 1744

    def set_var(self, var):
1745
        self.var = var
William Stein's avatar
William Stein committed
1746
    
1747 1748 1749
    def calculate_result_code(self):
        return self.var

William Stein's avatar
William Stein committed
1750
    def generate_result_code(self, code):
1751
        pass
William Stein's avatar
William Stein committed
1752

1753 1754 1755
    def analyse_types(self, env):
        pass

William Stein's avatar
William Stein committed
1756

1757
class TempNode(ExprNode):
1758 1759 1760 1761 1762 1763 1764
    # 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.
1765 1766

    subexprs = []
William Stein's avatar
William Stein committed
1767 1768 1769 1770 1771 1772 1773
    
    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
1774 1775 1776
        
    def analyse_types(self, env):
        return self.type
William Stein's avatar
William Stein committed
1777 1778 1779 1780
    
    def generate_result_code(self, code):
        pass

1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
    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
1801 1802 1803 1804 1805 1806 1807

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

1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
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
1827 1828 1829 1830 1831 1832 1833

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

1834
class IndexNode(ExprNode):
William Stein's avatar
William Stein committed
1835 1836 1837 1838
    #  Sequence indexing.
    #
    #  base     ExprNode
    #  index    ExprNode
1839 1840 1841 1842 1843 1844
    #  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
1845
    
1846 1847 1848 1849 1850 1851
    subexprs = ['base', 'index', 'indices']
    indices = None

    def __init__(self, pos, index, *args, **kw):
        ExprNode.__init__(self, pos, index=index, *args, **kw)
        self._index = index
1852 1853 1854 1855 1856

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

1857 1858 1859 1860 1861 1862 1863 1864
    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
1865 1866 1867 1868 1869
    def is_ephemeral(self):
        return self.base.is_ephemeral()
    
    def analyse_target_declaration(self, env):
        pass
1870 1871 1872 1873
        
    def analyse_as_type(self, env):
        base_type = self.base.analyse_as_type(env)
        if base_type and not base_type.is_pyobject:
1874
            if base_type.is_cpp_class:
1875
                if isinstance(self.index, TupleNode):
1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
                    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)))
1887
        return None
William Stein's avatar
William Stein committed
1888
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1889 1890
    def type_dependencies(self, env):
        return self.base.type_dependencies(env)
1891 1892
    
    def infer_type(self, env):
1893
        if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1894 1895 1896 1897 1898 1899 1900 1901
            return py_object_type
        base_type = self.base.infer_type(env)
        if base_type.is_ptr or base_type.is_array:
            return base_type.base_type
        else:
            # TODO: Handle buffers (hopefully without too much redundancy).
            return py_object_type
    
William Stein's avatar
William Stein committed
1902
    def analyse_types(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
1903 1904 1905 1906
        self.analyse_base_and_index_types(env, getting = 1)
    
    def analyse_target_types(self, env):
        self.analyse_base_and_index_types(env, setting = 1)
1907

Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
1908
    def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1909 1910 1911
        # Note: This might be cleaned up by having IndexNode
        # parsed in a saner way and only construct the tuple if
        # needed.
1912 1913 1914 1915

        # 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.
1916 1917
        self.is_buffer_access = False

William Stein's avatar
William Stein committed
1918
        self.base.analyse_types(env)
1919 1920 1921 1922 1923 1924
        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
        
1925
        # Handle the case where base is a literal char* (and we expect a string, not an int)
1926
        if isinstance(self.base, BytesNode):
1927
            self.base = self.base.coerce_to_pyobject(env)
1928 1929 1930

        skip_child_analysis = False
        buffer_access = False
1931
        if self.base.type.is_buffer:
1932 1933 1934
            assert hasattr(self.base, "entry") # Must be a NameNode-like node
            if self.indices:
                indices = self.indices
1935
            else:
1936 1937 1938 1939
                if isinstance(self.index, TupleNode):
                    indices = self.index.args
                else:
                    indices = [self.index]
1940
            if len(indices) == self.base.type.ndim:
1941 1942 1943 1944 1945 1946
                buffer_access = True
                skip_child_analysis = True
                for x in indices:
                    x.analyse_types(env)
                    if not x.type.is_int:
                        buffer_access = False
1947

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

1951 1952
        if buffer_access:
            self.indices = indices
1953
            self.index = None
1954 1955
            self.type = self.base.type.dtype
            self.is_buffer_access = True
1956
            self.buffer_type = self.base.entry.type
1957 1958

            if getting and self.type.is_pyobject:
1959
                self.is_temp = True
1960 1961 1962 1963 1964
            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
1965
        else:
1966 1967 1968 1969
            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)
1970
            self.original_index_type = self.index.type
1971
            if self.base.type.is_pyobject:
1972
                if self.index.type.is_int:
1973 1974 1975 1976 1977 1978 1979
                    if (not setting
                        and (self.base.type is list_type or self.base.type is tuple_type)
                        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
1980 1981 1982
                    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)
1983
                    self.is_temp = 1
1984
                self.type = py_object_type
William Stein's avatar
William Stein committed
1985
            else:
1986 1987
                if self.base.type.is_ptr or self.base.type.is_array:
                    self.type = self.base.type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
1988 1989 1990 1991 1992 1993 1994 1995
                    if self.index.type.is_pyobject:
                        self.index = self.index.coerce_to(
                            PyrexTypes.c_py_ssize_t_type, env)
                    if not self.index.type.is_int:
                        error(self.pos,
                            "Invalid index type '%s'" %
                                self.index.type)
                elif self.base.type.is_cpp_class:
1996
                    function = env.lookup_operator("[]", [self.base, self.index])
Robert Bradshaw's avatar
Robert Bradshaw committed
1997
                    if function is None:
1998
                        error(self.pos, "Indexing '%s' not supported for index type '%s'" % (self.base.type, self.index.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
1999 2000 2001 2002 2003 2004 2005 2006 2007
                        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
2008
                        error(self.pos, "Can't set non-reference result '%s'" % self.type)
2009 2010 2011 2012 2013
                else:
                    error(self.pos,
                        "Attempting to index non-array type '%s'" %
                            self.base.type)
                    self.type = PyrexTypes.error_type
Stefan Behnel's avatar
Stefan Behnel committed
2014

2015 2016
    gil_message = "Indexing Python object"

2017 2018
    def nogil_check(self, env):
        if self.is_buffer_access:
2019 2020 2021 2022 2023 2024
            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
2025
        super(IndexNode, self).nogil_check(env)
2026 2027


William Stein's avatar
William Stein committed
2028
    def check_const_addr(self):
2029
        return self.base.check_const_addr() and self.index.check_const()
William Stein's avatar
William Stein committed
2030 2031 2032
    
    def is_lvalue(self):
        return 1
Dag Sverre Seljebotn's avatar
merge  
Dag Sverre Seljebotn committed
2033

William Stein's avatar
William Stein committed
2034
    def calculate_result_code(self):
2035
        if self.is_buffer_access:
2036
            return "(*%s)" % self.buffer_ptr_code
2037 2038 2039 2040
        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())
2041 2042
        else:
            return "(%s[%s])" % (
2043
                self.base.result(), self.index.result())
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2044
            
2045
    def extra_index_params(self):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2046 2047
        if self.index.type.is_int:
            if self.original_index_type.signed:
2048
                size_adjustment = ""
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2049
            else:
2050 2051
                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
2052 2053
        else:
            return ""
2054 2055 2056

    def generate_subexpr_evaluation_code(self, code):
        self.base.generate_evaluation_code(code)
2057
        if not self.indices:
2058 2059
            self.index.generate_evaluation_code(code)
        else:
2060 2061
            for i in self.indices:
                i.generate_evaluation_code(code)
2062
        
2063 2064
    def generate_subexpr_disposal_code(self, code):
        self.base.generate_disposal_code(code)
2065
        if not self.indices:
2066 2067
            self.index.generate_disposal_code(code)
        else:
2068 2069
            for i in self.indices:
                i.generate_disposal_code(code)
2070

2071 2072 2073 2074 2075 2076 2077 2078
    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
2079
    def generate_result_code(self, code):
2080
        if self.is_buffer_access:
2081 2082
            if code.globalstate.directives['nonecheck']:
                self.put_nonecheck(code)
2083 2084 2085 2086
            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
2087
                code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2088
        elif self.type.is_pyobject and self.is_temp:
2089
            if self.index.type.is_int:
2090
                index_code = self.index.result()
2091 2092 2093 2094 2095 2096
                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"
2097
                code.globalstate.use_utility_code(getitem_int_utility_code)
2098
            else:
2099 2100 2101 2102 2103
                if self.base.type is dict_type:
                    function = "__Pyx_PyDict_GetItem"
                    code.globalstate.use_utility_code(getitem_dict_utility_code)
                else:
                    function = "PyObject_GetItem"
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2104 2105 2106 2107
                index_code = self.index.py_result()
                sign_code = ""
            code.putln(
                "%s = %s(%s, %s%s); if (!%s) %s" % (
2108
                    self.result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2109 2110 2111
                    function,
                    self.base.py_result(),
                    index_code,
2112
                    self.extra_index_params(),
2113
                    self.result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2114
                    code.error_goto(self.pos)))
2115
            code.put_gotref(self.py_result())
2116
            
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2117 2118 2119
    def generate_setitem_code(self, value_code, code):
        if self.index.type.is_int:
            function = "__Pyx_SetItemInt"
2120
            index_code = self.index.result()
2121
            code.globalstate.use_utility_code(setitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2122 2123
        else:
            index_code = self.index.py_result()
2124 2125
            if self.base.type is dict_type:
                function = "PyDict_SetItem"
Craig Citro's avatar
Craig Citro committed
2126
            # It would seem that we could specialized lists/tuples, but that
2127 2128 2129 2130 2131 2132
            # 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). 
2133 2134
            else:
                function = "PyObject_SetItem"
2135
        code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2136 2137
            "if (%s(%s, %s, %s%s) < 0) %s" % (
                function,
2138
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2139 2140
                index_code,
                value_code,
2141
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2142
                code.error_goto(self.pos)))
2143 2144 2145

    def generate_buffer_setitem_code(self, rhs, code, op=""):
        # Used from generate_assignment_code and InPlaceAssignmentNode
2146 2147
        if code.globalstate.directives['nonecheck']:
            self.put_nonecheck(code)
2148 2149 2150 2151
        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.
2152
            ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2153
            rhs_code = rhs.result()
2154
            code.putln("%s = %s;" % (ptr, ptrexpr))
2155
            code.put_gotref("*%s" % ptr)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2156
            code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2157 2158 2159
                ptr, rhs_code
                ))
            code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2160
            code.put_giveref("*%s" % ptr)
2161 2162 2163
            code.funcstate.release_temp(ptr)
        else: 
            # Simple case
2164
            code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2165

William Stein's avatar
William Stein committed
2166 2167
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2168
        if self.is_buffer_access:
2169
            self.generate_buffer_setitem_code(rhs, code)
2170
        elif self.type.is_pyobject:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2171
            self.generate_setitem_code(rhs.py_result(), code)
William Stein's avatar
William Stein committed
2172 2173 2174
        else:
            code.putln(
                "%s = %s;" % (
2175
                    self.result(), rhs.result()))
2176
        self.generate_subexpr_disposal_code(code)
2177
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2178
        rhs.generate_disposal_code(code)
2179
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2180 2181 2182
    
    def generate_deletion_code(self, code):
        self.generate_subexpr_evaluation_code(code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2183 2184
        #if self.type.is_pyobject:
        if self.index.type.is_int:
2185
            function = "__Pyx_DelItemInt"
2186
            index_code = self.index.result()
2187
            code.globalstate.use_utility_code(delitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2188 2189
        else:
            index_code = self.index.py_result()
2190 2191 2192 2193
            if self.base.type is dict_type:
                function = "PyDict_DelItem"
            else:
                function = "PyObject_DelItem"
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2194
        code.putln(
2195
            "if (%s(%s, %s%s) < 0) %s" % (
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2196
                function,
William Stein's avatar
William Stein committed
2197
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2198
                index_code,
2199
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2200
                code.error_goto(self.pos)))
William Stein's avatar
William Stein committed
2201
        self.generate_subexpr_disposal_code(code)
2202
        self.free_subexpr_temps(code)
2203

2204
    def buffer_lookup_code(self, code):
2205
        # Assign indices to temps
2206
        index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2207
        for temp, index in zip(index_temps, self.indices):
2208
            code.putln("%s = %s;" % (temp, index.result()))
2209 2210
        # Generate buffer access code using these temps
        import Buffer
2211 2212
        # The above could happen because child_attrs is wrong somewhere so that
        # options are not propagated.
2213 2214 2215
        return Buffer.put_buffer_lookup_code(entry=self.base.entry,
                                             index_signeds=[i.type.signed for i in self.indices],
                                             index_cnames=index_temps,
2216
                                             directives=code.globalstate.directives,
2217
                                             pos=self.pos, code=code)
William Stein's avatar
William Stein committed
2218

2219 2220 2221 2222 2223 2224 2225
    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("}")

2226
class SliceIndexNode(ExprNode):
William Stein's avatar
William Stein committed
2227 2228 2229 2230 2231 2232 2233
    #  2-element slice indexing
    #
    #  base      ExprNode
    #  start     ExprNode or None
    #  stop      ExprNode or None
    
    subexprs = ['base', 'start', 'stop']
2234

2235 2236 2237 2238 2239 2240 2241 2242 2243
    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

2244 2245 2246 2247
    def calculate_constant_result(self):
        self.constant_result = self.base.constant_result[
            self.start.constant_result : self.stop.constant_result]

2248 2249
    def compile_time_value(self, denv):
        base = self.base.compile_time_value(denv)
2250 2251 2252 2253 2254 2255 2256 2257
        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)
2258 2259 2260 2261 2262
        try:
            return base[start:stop]
        except Exception, e:
            self.compile_time_value_error(e)
    
William Stein's avatar
William Stein committed
2263 2264
    def analyse_target_declaration(self, env):
        pass
2265 2266 2267 2268
    
    def analyse_target_types(self, env):
        self.analyse_types(env)
        # when assigning, we must accept any Python type
2269 2270
        if self.type.is_pyobject:
            self.type = py_object_type
William Stein's avatar
William Stein committed
2271 2272 2273 2274 2275 2276 2277

    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)
2278 2279 2280 2281
        base_type = self.base.type
        if base_type.is_string:
            self.type = bytes_type
        elif base_type.is_array or base_type.is_ptr:
2282 2283 2284
            # we need a ptr type here instead of an array type, as
            # array types can result in invalid type casts in the C
            # code
2285
            self.type = PyrexTypes.CPtrType(base_type.base_type)
2286 2287 2288
        else:
            self.base = self.base.coerce_to_pyobject(env)
            self.type = py_object_type
2289 2290 2291
        if base_type.is_builtin_type:
            # slicing builtin types returns something of the same type
            self.type = base_type
2292
        c_int = PyrexTypes.c_py_ssize_t_type
William Stein's avatar
William Stein committed
2293 2294 2295 2296 2297
        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
2298

2299
    nogil_check = Node.gil_error
2300 2301
    gil_message = "Slicing Python object"

William Stein's avatar
William Stein committed
2302
    def generate_result_code(self, code):
2303 2304 2305 2306
        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
2307 2308 2309
        if self.base.type.is_string:
            if self.stop is None:
                code.putln(
2310
                    "%s = PyBytes_FromString(%s + %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2311 2312 2313 2314 2315 2316
                        self.result(),
                        self.base.result(),
                        self.start_code(),
                        code.error_goto_if_null(self.result(), self.pos)))
            else:
                code.putln(
2317
                    "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331
                        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(
                "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
                    self.result(),
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
                    code.error_goto_if_null(self.result(), self.pos)))
2332
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2333 2334 2335
    
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2336 2337 2338 2339 2340 2341
        if self.type.is_pyobject:
            code.put_error_if_neg(self.pos, 
                "PySequence_SetSlice(%s, %s, %s, %s)" % (
                    self.base.py_result(),
                    self.start_code(),
                    self.stop_code(),
Lisandro Dalcin's avatar
Lisandro Dalcin committed
2342
                    rhs.py_result()))
2343 2344 2345 2346 2347 2348 2349 2350
        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
2351 2352
            if rhs.type.is_array:
                array_length = rhs.type.size
2353
                self.generate_slice_guard_code(code, array_length)
Stefan Behnel's avatar
Stefan Behnel committed
2354
            else:
Stefan Behnel's avatar
Stefan Behnel committed
2355 2356
                error(self.pos,
                      "Slice assignments from pointers are not yet supported.")
Stefan Behnel's avatar
Stefan Behnel committed
2357 2358
                # FIXME: fix the array size according to start/stop
                array_length = self.base.type.size
2359 2360 2361 2362
            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
2363
        self.generate_subexpr_disposal_code(code)
2364
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2365
        rhs.generate_disposal_code(code)
2366
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2367 2368

    def generate_deletion_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2369
        if not self.base.type.is_pyobject:
2370 2371 2372
            error(self.pos,
                  "Deleting slices is only supported for Python types, not '%s'." % self.type)
            return
William Stein's avatar
William Stein committed
2373
        self.generate_subexpr_evaluation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2374 2375
        code.put_error_if_neg(self.pos,
            "PySequence_DelSlice(%s, %s, %s)" % (
William Stein's avatar
William Stein committed
2376 2377
                self.base.py_result(),
                self.start_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
2378
                self.stop_code()))
William Stein's avatar
William Stein committed
2379
        self.generate_subexpr_disposal_code(code)
2380 2381 2382 2383 2384 2385 2386 2387 2388 2389

    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
2390
                if stop < 0:
2391
                    slice_size = self.base.type.size + stop
Stefan Behnel's avatar
Stefan Behnel committed
2392 2393
                else:
                    slice_size = stop
2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
                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))
2424
            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));' % (
2425 2426 2427
                        target_size, check))
            code.putln(code.error_goto(self.pos))
            code.putln("}")
William Stein's avatar
William Stein committed
2428 2429 2430
    
    def start_code(self):
        if self.start:
2431
            return self.start.result()
William Stein's avatar
William Stein committed
2432 2433 2434 2435 2436
        else:
            return "0"
    
    def stop_code(self):
        if self.stop:
2437
            return self.stop.result()
2438 2439
        elif self.base.type.is_array:
            return self.base.type.size
William Stein's avatar
William Stein committed
2440
        else:
2441
            return "PY_SSIZE_T_MAX"
William Stein's avatar
William Stein committed
2442 2443
    
    def calculate_result_code(self):
2444
        # self.result() is not used, but this method must exist
William Stein's avatar
William Stein committed
2445 2446 2447
        return "<unused>"
    

2448
class SliceNode(ExprNode):
William Stein's avatar
William Stein committed
2449 2450 2451 2452 2453
    #  start:stop:step in subscript list
    #
    #  start     ExprNode
    #  stop      ExprNode
    #  step      ExprNode
2454 2455 2456
    
    type = py_object_type
    is_temp = 1
2457 2458 2459 2460 2461 2462 2463

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

2464 2465
    def compile_time_value(self, denv):
        start = self.start.compile_time_value(denv)
2466 2467 2468 2469 2470 2471 2472 2473
        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)
2474 2475 2476 2477 2478
        try:
            return slice(start, stop, step)
        except Exception, e:
            self.compile_time_value_error(e)

William Stein's avatar
William Stein committed
2479 2480 2481 2482 2483 2484 2485 2486 2487
    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)
2488 2489 2490

    gil_message = "Constructing Python slice object"

William Stein's avatar
William Stein committed
2491 2492
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2493
            "%s = PySlice_New(%s, %s, %s); %s" % (
2494
                self.result(),
William Stein's avatar
William Stein committed
2495 2496 2497
                self.start.py_result(), 
                self.stop.py_result(), 
                self.step.py_result(),
2498
                code.error_goto_if_null(self.result(), self.pos)))
2499
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2500

2501

2502
class CallNode(ExprNode):
2503

Robert Bradshaw's avatar
Robert Bradshaw committed
2504 2505 2506 2507 2508 2509
    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):
2510
                items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
Robert Bradshaw's avatar
Robert Bradshaw committed
2511 2512 2513 2514 2515 2516 2517
            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
2518 2519 2520 2521 2522 2523 2524 2525 2526
        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
2527 2528 2529
    
    def is_lvalue(self):
        return self.type.is_reference
2530

2531
    def nogil_check(self, env):
2532 2533
        func_type = self.function_type()
        if func_type.is_pyobject:
2534
            self.gil_error()
2535
        elif not getattr(func_type, 'nogil', False):
2536
            self.gil_error()
2537 2538 2539

    gil_message = "Calling gil-requiring function"

2540 2541

class SimpleCallNode(CallNode):
William Stein's avatar
William Stein committed
2542 2543 2544 2545 2546 2547 2548
    #  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
2549
    #  wrapper_call   bool                 used internally
2550
    #  has_optional_args   bool            used internally
William Stein's avatar
William Stein committed
2551 2552 2553 2554 2555 2556
    
    subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
    
    self = None
    coerced_self = None
    arg_tuple = None
2557
    wrapper_call = False
2558
    has_optional_args = False
William Stein's avatar
William Stein committed
2559
    
2560 2561 2562 2563 2564 2565 2566
    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)
2567
            
Robert Bradshaw's avatar
Robert Bradshaw committed
2568
    def type_dependencies(self, env):
2569 2570
        # TODO: Update when Danilo's C++ code merged in to handle the
        # the case of function overloading.
Robert Bradshaw's avatar
Robert Bradshaw committed
2571
        return self.function.type_dependencies(env)
2572 2573
    
    def infer_type(self, env):
2574 2575
        function = self.function
        func_type = function.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
2576 2577
        if isinstance(self.function, NewExprNode):
            return PyrexTypes.CPtrType(self.function.class_type)
2578 2579 2580 2581
        if func_type.is_ptr:
            func_type = func_type.base_type
        if func_type.is_cfunction:
            return func_type.return_type
2582 2583 2584 2585 2586 2587
        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:
2588 2589 2590
                    if function.entry.name == 'float':
                        return PyrexTypes.c_double_type
                    elif function.entry.name in Builtin.types_that_construct_their_instance:
2591 2592 2593
                        return result_type
        return py_object_type

2594
    def analyse_as_type(self, env):
2595
        attr = self.function.as_cython_attribute()
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
        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
2608

William Stein's avatar
William Stein committed
2609
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2610 2611
        if self.analyse_as_type_constructor(env):
            return
William Stein's avatar
William Stein committed
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621
        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:
2622 2623
            self.arg_tuple = TupleNode(self.pos, args = self.args)
            self.arg_tuple.analyse_types(env)
William Stein's avatar
William Stein committed
2624
            self.args = None
2625 2626 2627
            if func_type is Builtin.type_type and function.is_name and \
                   function.entry and \
                   function.entry.is_builtin and \
2628 2629 2630 2631 2632 2633 2634 2635 2636 2637
                   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
            elif function.is_name and function.type_entry:
2638 2639 2640 2641 2642 2643 2644
                # 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
            else:
                self.type = py_object_type
William Stein's avatar
William Stein committed
2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666
            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.
                expected_type = func_type.args[0].type
                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
2667
        if self.function.type is error_type:
2668
            self.type = error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2669
            return
Robert Bradshaw's avatar
Robert Bradshaw committed
2670
        if self.function.type.is_cpp_class:
2671 2672
            overloaded_entry = self.function.type.scope.lookup("operator()")
            if overloaded_entry is None:
Robert Bradshaw's avatar
Robert Bradshaw committed
2673 2674 2675
                self.type = PyrexTypes.error_type
                self.result_code = "<error>"
                return
2676 2677
        elif hasattr(self.function, 'entry'):
            overloaded_entry = self.function.entry
Robert Bradshaw's avatar
Robert Bradshaw committed
2678
        else:
2679 2680 2681 2682 2683 2684 2685 2686 2687
            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
2688 2689 2690 2691 2692 2693 2694 2695
            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
2696
        # Check no. of args
2697 2698
        max_nargs = len(func_type.args)
        expected_nargs = max_nargs - func_type.optional_arg_count
William Stein's avatar
William Stein committed
2699
        actual_nargs = len(self.args)
2700 2701 2702
        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
2703
        # Coerce arguments
2704
        for i in range(min(max_nargs, actual_nargs)):
William Stein's avatar
William Stein committed
2705 2706
            formal_type = func_type.args[i].type
            self.args[i] = self.args[i].coerce_to(formal_type, env)
2707
        for i in range(max_nargs, actual_nargs):
William Stein's avatar
William Stein committed
2708 2709 2710 2711
            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
2712
        if isinstance(self.function, NewExprNode):
2713
            self.type = PyrexTypes.CPtrType(self.function.class_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2714 2715
        else:
            self.type = func_type.return_type
Stefan Behnel's avatar
Stefan Behnel committed
2716 2717 2718 2719 2720 2721
        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
Robert Bradshaw's avatar
Robert Bradshaw committed
2722 2723 2724 2725 2726
        # C++ exception handler
        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
2727 2728 2729 2730 2731
    def calculate_result_code(self):
        return self.c_call_code()
    
    def c_call_code(self):
        func_type = self.function_type()
2732
        if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
William Stein's avatar
William Stein committed
2733 2734 2735
            return "<error>"
        formal_args = func_type.args
        arg_list_code = []
2736 2737 2738 2739 2740
        args = zip(formal_args, self.args)
        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
2741 2742
                arg_code = actual_arg.result_as(formal_arg.type)
                arg_list_code.append(arg_code)
2743
                
2744 2745 2746
        if func_type.is_overridable:
            arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
                
2747
        if func_type.optional_arg_count:
2748
            if expected_nargs == actual_nargs:
2749
                optional_args = 'NULL'
2750
            else:
2751
                optional_args = "&%s" % self.opt_arg_struct
2752
            arg_list_code.append(optional_args)
2753
            
William Stein's avatar
William Stein committed
2754
        for actual_arg in self.args[len(formal_args):]:
2755 2756
            arg_list_code.append(actual_arg.result())
        result = "%s(%s)" % (self.function.result(),
Stefan Behnel's avatar
Stefan Behnel committed
2757
            ', '.join(arg_list_code))
William Stein's avatar
William Stein committed
2758 2759 2760 2761 2762
        return result
    
    def generate_result_code(self, code):
        func_type = self.function_type()
        if func_type.is_pyobject:
2763
            arg_code = self.arg_tuple.py_result()
William Stein's avatar
William Stein committed
2764
            code.putln(
2765
                "%s = PyObject_Call(%s, %s, NULL); %s" % (
2766
                    self.result(),
William Stein's avatar
William Stein committed
2767
                    self.function.py_result(),
2768
                    arg_code,
2769
                    code.error_goto_if_null(self.result(), self.pos)))
2770
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2771
        elif func_type.is_cfunction:
2772 2773 2774
            if self.has_optional_args:
                actual_nargs = len(self.args)
                expected_nargs = len(func_type.args) - func_type.optional_arg_count
2775 2776
                self.opt_arg_struct = code.funcstate.allocate_temp(
                    func_type.op_arg_struct.base_type, manage_ref=True)
2777 2778 2779 2780 2781 2782 2783 2784
                code.putln("%s.%s = %s;" % (
                        self.opt_arg_struct,
                        Naming.pyrex_prefix + "n",
                        len(self.args) - expected_nargs))
                args = zip(func_type.args, self.args)
                for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
                    code.putln("%s.%s = %s;" % (
                            self.opt_arg_struct,
2785
                            func_type.opt_arg_cname(formal_arg.name),
2786
                            actual_arg.result_as(formal_arg.type)))
William Stein's avatar
William Stein committed
2787
            exc_checks = []
2788
            if self.type.is_pyobject and self.is_temp:
2789
                exc_checks.append("!%s" % self.result())
William Stein's avatar
William Stein committed
2790
            else:
2791 2792
                exc_val = func_type.exception_value
                exc_check = func_type.exception_check
William Stein's avatar
William Stein committed
2793
                if exc_val is not None:
2794
                    exc_checks.append("%s == %s" % (self.result(), exc_val))
William Stein's avatar
William Stein committed
2795 2796 2797 2798
                if exc_check:
                    exc_checks.append("PyErr_Occurred()")
            if self.is_temp or exc_checks:
                rhs = self.c_call_code()
2799 2800
                if self.result():
                    lhs = "%s = " % self.result()
William Stein's avatar
William Stein committed
2801 2802 2803
                    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
2804
                        #    "from", return_type, "to pyobject" ###
William Stein's avatar
William Stein committed
2805 2806 2807
                        rhs = typecast(py_object_type, self.type, rhs)
                else:
                    lhs = ""
Felix Wu's avatar
Felix Wu committed
2808
                if func_type.exception_check == '+':
Robert Bradshaw's avatar
Robert Bradshaw committed
2809 2810 2811
                    if func_type.exception_value is None:
                        raise_py_exception = "__Pyx_CppExn2PyErr()"
                    elif func_type.exception_value.type.is_pyobject:
2812 2813 2814
                        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
2815 2816
                    else:
                        raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
Felix Wu's avatar
Felix Wu committed
2817
                    code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2818
                    "try {%s%s;} catch(...) {%s; %s}" % (
Felix Wu's avatar
Felix Wu committed
2819 2820
                        lhs,
                        rhs,
Robert Bradshaw's avatar
Robert Bradshaw committed
2821
                        raise_py_exception,
Felix Wu's avatar
Felix Wu committed
2822
                        code.error_goto(self.pos)))
2823 2824 2825 2826 2827 2828
                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))
2829
                if self.type.is_pyobject and self.result():
2830
                    code.put_gotref(self.py_result())
2831 2832
            if self.has_optional_args:
                code.funcstate.release_temp(self.opt_arg_struct)
2833 2834 2835 2836


class PythonCapiFunctionNode(ExprNode):
    subexprs = []
2837
    def __init__(self, pos, py_name, cname, func_type, utility_code = None):
2838
        self.pos = pos
2839 2840
        self.name = py_name
        self.cname = cname
2841 2842 2843
        self.type = func_type
        self.utility_code = utility_code

2844 2845 2846
    def analyse_types(self, env):
        pass

2847 2848 2849 2850 2851
    def generate_result_code(self, code):
        if self.utility_code:
            code.globalstate.use_utility_code(self.utility_code)

    def calculate_result_code(self):
2852
        return self.cname
2853 2854 2855 2856 2857

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

    def __init__(self, pos, function_name, func_type,
2858
                 utility_code = None, py_name=None, **kwargs):
2859 2860 2861
        self.type = func_type.return_type
        self.result_ctype = self.type
        self.function = PythonCapiFunctionNode(
2862
            pos, py_name, function_name, func_type,
2863 2864 2865 2866 2867
            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
2868

2869
class GeneralCallNode(CallNode):
William Stein's avatar
William Stein committed
2870 2871 2872 2873 2874 2875 2876 2877
    #  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
    
2878 2879
    type = py_object_type
    
William Stein's avatar
William Stein committed
2880 2881
    subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']

2882
    nogil_check = Node.gil_error
2883

2884 2885 2886 2887 2888 2889 2890 2891 2892 2893
    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)
2894 2895 2896 2897 2898 2899
            
    def explicit_args_kwds(self):
        if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
            raise PostParseError(self.pos,
                'Compile-time keyword arguments must be explicit.')
        return self.positional_args.args, self.keyword_args
2900

William Stein's avatar
William Stein committed
2901
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2902 2903
        if self.analyse_as_type_constructor(env):
            return
William Stein's avatar
William Stein committed
2904 2905 2906 2907 2908 2909
        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)
2910
        if not self.function.type.is_pyobject:
2911 2912
            if self.function.type.is_error:
                self.type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
2913
                return
2914
            if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2915
                error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2916 2917
            else:
                self.function = self.function.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
2918 2919 2920 2921 2922
        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
2923
        function = self.function
2924 2925 2926 2927 2928 2929 2930
        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
        else:
            self.type = py_object_type
William Stein's avatar
William Stein committed
2931 2932 2933
        self.is_temp = 1
        
    def generate_result_code(self, code):
2934
        if self.type.is_error: return
2935
        kwargs_call_function = "PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
2936
        if self.keyword_args and self.starstar_arg:
Robert Bradshaw's avatar
Robert Bradshaw committed
2937 2938
            code.put_error_if_neg(self.pos, 
                "PyDict_Update(%s, %s)" % (
William Stein's avatar
William Stein committed
2939
                    self.keyword_args.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
2940
                    self.starstar_arg.py_result()))
William Stein's avatar
William Stein committed
2941 2942 2943 2944 2945
            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()
2946 2947
            if self.starstar_arg.type is not Builtin.dict_type:
                # CPython supports calling functions with non-dicts, so do we
2948 2949
                code.globalstate.use_utility_code(kwargs_call_utility_code)
                kwargs_call_function = "__Pyx_PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
2950 2951 2952
        else:
            keyword_code = None
        if not keyword_code:
2953
            call_code = "PyObject_Call(%s, %s, NULL)" % (
William Stein's avatar
William Stein committed
2954 2955 2956
                self.function.py_result(),
                self.positional_args.py_result())
        else:
2957 2958
            call_code = "%s(%s, %s, %s)" % (
                kwargs_call_function,
William Stein's avatar
William Stein committed
2959 2960 2961 2962
                self.function.py_result(),
                self.positional_args.py_result(),
                keyword_code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2963
            "%s = %s; %s" % (
2964
                self.result(),
William Stein's avatar
William Stein committed
2965
                call_code,
2966
                code.error_goto_if_null(self.result(), self.pos)))
2967
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2968 2969


2970
class AsTupleNode(ExprNode):
William Stein's avatar
William Stein committed
2971 2972 2973 2974 2975 2976
    #  Convert argument to tuple. Used for normalising
    #  the * argument of a function call.
    #
    #  arg    ExprNode
    
    subexprs = ['arg']
2977 2978 2979

    def calculate_constant_result(self):
        self.constant_result = tuple(self.base.constant_result)
William Stein's avatar
William Stein committed
2980
    
2981 2982 2983 2984 2985 2986 2987
    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
2988 2989 2990
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
2991
        self.type = tuple_type
William Stein's avatar
William Stein committed
2992
        self.is_temp = 1
2993

2994 2995 2996
    def may_be_none(self):
        return False

2997
    nogil_check = Node.gil_error
2998 2999
    gil_message = "Constructing Python tuple"

William Stein's avatar
William Stein committed
3000 3001
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3002
            "%s = PySequence_Tuple(%s); %s" % (
3003
                self.result(),
William Stein's avatar
William Stein committed
3004
                self.arg.py_result(),
3005
                code.error_goto_if_null(self.result(), self.pos)))
3006
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3007 3008
    

3009
class AttributeNode(ExprNode):
William Stein's avatar
William Stein committed
3010 3011 3012 3013
    #  obj.attribute
    #
    #  obj          ExprNode
    #  attribute    string
3014
    #  needs_none_check boolean        Used if obj is an extension type.
3015
    #                                  If set to True, it is known that the type is not None.
William Stein's avatar
William Stein committed
3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029
    #
    #  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
3030
    needs_none_check = True
William Stein's avatar
William Stein committed
3031

3032
    def as_cython_attribute(self):
3033 3034
        if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
            return self.attribute
3035 3036 3037
        cy = self.obj.as_cython_attribute()
        if cy:
            return "%s.%s" % (cy, self.attribute)
3038

3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049
    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
3050
        return ExprNode.coerce_to(self, dst_type, env)
3051 3052 3053

    def calculate_constant_result(self):
        attr = self.attribute
3054
        if attr.startswith("__") and attr.endswith("__"):
3055 3056 3057
            return
        self.constant_result = getattr(self.obj.constant_result, attr)

3058 3059
    def compile_time_value(self, denv):
        attr = self.attribute
3060
        if attr.startswith("__") and attr.endswith("__"):
Stefan Behnel's avatar
Stefan Behnel committed
3061 3062
            error(self.pos,
                  "Invalid attribute name '%s' in compile-time expression" % attr)
3063
            return None
3064
        obj = self.obj.compile_time_value(denv)
3065 3066 3067 3068
        try:
            return getattr(obj, attr)
        except Exception, e:
            self.compile_time_value_error(e)
3069
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3070 3071 3072
    def type_dependencies(self, env):
        return self.obj.type_dependencies(env)
    
3073 3074 3075 3076 3077 3078
    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
3079
            self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
3080
            return self.type
3081

William Stein's avatar
William Stein committed
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125
    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
3126
                ubcm_entry.is_unbound_cmethod = 1
William Stein's avatar
William Stein committed
3127 3128 3129
                self.mutate_into_name_node(env, ubcm_entry, None)
                return 1
        return 0
3130 3131 3132 3133
        
    def analyse_as_type(self, env):
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
3134
            return module_scope.lookup_type(self.attribute)
Robert Bradshaw's avatar
Robert Bradshaw committed
3135 3136 3137 3138
        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)
3139
        return None
William Stein's avatar
William Stein committed
3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171
    
    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:
3172
            NameNode.analyse_rvalue_entry(self, env)
William Stein's avatar
William Stein committed
3173 3174 3175 3176 3177
    
    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:
3178 3179
#            error(self.pos, "C method can only be called")
            pass
3180 3181
        ## Reference to C array turns into pointer to first element.
        #while self.type.is_array:
Robert Bradshaw's avatar
Robert Bradshaw committed
3182
        #    self.type = self.type.element_ptr_type()
William Stein's avatar
William Stein committed
3183 3184 3185 3186 3187
        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
3188
    def analyse_attribute(self, env, obj_type = None):
William Stein's avatar
William Stein committed
3189 3190 3191
        # 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
3192 3193 3194 3195 3196 3197 3198
        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
3199
        if obj_type.is_ptr or obj_type.is_array:
William Stein's avatar
William Stein committed
3200 3201 3202 3203 3204 3205 3206 3207 3208 3209
            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
3210 3211
                if entry and entry.is_member:
                    entry = None
William Stein's avatar
William Stein committed
3212 3213 3214 3215
            else:
                error(self.pos, 
                    "Cannot select attribute of incomplete type '%s'" 
                    % obj_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3216 3217
                self.type = PyrexTypes.error_type
                return
William Stein's avatar
William Stein committed
3218 3219
            self.entry = entry
            if entry:
3220 3221
                if obj_type.is_extension_type and entry.name == "__weakref__":
                    error(self.pos, "Illegal use of special attribute __weakref__")
3222 3223
                # methods need the normal attribute lookup
                # because they do not have struct entries
3224 3225 3226 3227
                if entry.is_variable or entry.is_cmethod:
                    self.type = entry.type
                    self.member = entry.cname
                    return
William Stein's avatar
William Stein committed
3228 3229 3230 3231 3232 3233 3234 3235 3236
                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
3237
        self.analyse_as_python_attribute(env, obj_type)
Stefan Behnel's avatar
Stefan Behnel committed
3238

Robert Bradshaw's avatar
Robert Bradshaw committed
3239 3240 3241
    def analyse_as_python_attribute(self, env, obj_type = None):
        if obj_type is None:
            obj_type = self.obj.type
3242
        self.member = self.attribute
3243 3244
        self.type = py_object_type
        self.is_py_attr = 1
3245
        if not obj_type.is_pyobject and not obj_type.is_error:
3246
            if obj_type.can_coerce_to_pyobject(env):
3247 3248 3249 3250 3251
                self.obj = self.obj.coerce_to_pyobject(env)
            else:
                error(self.pos,
                      "Object of type '%s' has no attribute '%s'" %
                      (obj_type, self.attribute))
3252

3253
    def nogil_check(self, env):
3254
        if self.is_py_attr:
3255
            self.gil_error()
3256

3257 3258
    gil_message = "Accessing Python attribute"

William Stein's avatar
William Stein committed
3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278
    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 ###
3279
        #print "...obj node =", self.obj, "code", self.obj.result() ###
William Stein's avatar
William Stein committed
3280 3281 3282 3283 3284
        #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
3285 3286 3287 3288 3289 3290
            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
3291
        elif obj.type.is_complex:
3292
            return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
William Stein's avatar
William Stein committed
3293 3294 3295 3296
        else:
            return "%s%s%s" % (obj_code, self.op, self.member)
    
    def generate_result_code(self, code):
3297
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3298
        if self.is_py_attr:
3299 3300
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
3301
                    self.result(),
3302
                    self.obj.py_result(),
3303
                    interned_attr_cname,
3304
                    code.error_goto_if_null(self.result(), self.pos)))
3305
            code.put_gotref(self.py_result())
3306 3307 3308
        else:
            # result_code contains what is needed, but we may need to insert
            # a check and raise an exception
3309 3310 3311 3312
            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
3313 3314
    
    def generate_assignment_code(self, rhs, code):
3315
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3316 3317
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
3318 3319 3320
            code.put_error_if_neg(self.pos, 
                'PyObject_SetAttr(%s, %s, %s)' % (
                    self.obj.py_result(),
3321
                    interned_attr_cname,
3322
                    rhs.py_result()))
William Stein's avatar
William Stein committed
3323
            rhs.generate_disposal_code(code)
3324
            rhs.free_temps(code)
3325 3326 3327 3328 3329
        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
3330
        else:
3331 3332 3333 3334 3335
            if (self.obj.type.is_extension_type
                  and self.needs_none_check
                  and code.globalstate.directives['nonecheck']):
                self.put_nonecheck(code)

3336
            select_code = self.result()
3337
            if self.type.is_pyobject and self.use_managed_ref:
William Stein's avatar
William Stein committed
3338
                rhs.make_owned_reference(code)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3339
                code.put_giveref(rhs.py_result())
3340
                code.put_gotref(select_code)
William Stein's avatar
William Stein committed
3341 3342 3343 3344
                code.put_decref(select_code, self.ctype())
            code.putln(
                "%s = %s;" % (
                    select_code,
3345
                    rhs.result_as(self.ctype())))
3346
                    #rhs.result()))
William Stein's avatar
William Stein committed
3347
            rhs.generate_post_assignment_code(code)
3348
            rhs.free_temps(code)
William Stein's avatar
William Stein committed
3349
        self.obj.generate_disposal_code(code)
3350
        self.obj.free_temps(code)
William Stein's avatar
William Stein committed
3351 3352
    
    def generate_deletion_code(self, code):
3353
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3354 3355
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
3356 3357 3358
            code.put_error_if_neg(self.pos,
                'PyObject_DelAttr(%s, %s)' % (
                    self.obj.py_result(),
3359
                    interned_attr_cname))
William Stein's avatar
William Stein committed
3360 3361 3362
        else:
            error(self.pos, "Cannot delete C attribute of extension type")
        self.obj.generate_disposal_code(code)
3363
        self.obj.free_temps(code)
3364 3365 3366 3367 3368 3369
        
    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
3370

3371 3372 3373
    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
3374
        code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3375 3376 3377 3378
        code.putln(code.error_goto(self.pos))
        code.putln("}")


William Stein's avatar
William Stein committed
3379 3380 3381 3382 3383 3384
#-------------------------------------------------------------------
#
#  Constructor nodes
#
#-------------------------------------------------------------------

3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399
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
3400
    is_temp = 1
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428

    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


3429
class SequenceNode(ExprNode):
William Stein's avatar
William Stein committed
3430 3431 3432 3433
    #  Base class for list and tuple constructor nodes.
    #  Contains common code for performing sequence unpacking.
    #
    #  args                    [ExprNode]
3434
    #  iterator                ExprNode
William Stein's avatar
William Stein committed
3435 3436 3437 3438 3439 3440 3441
    #  unpacked_items          [ExprNode] or None
    #  coerced_unpacked_items  [ExprNode] or None
    
    subexprs = ['args']
    
    is_sequence_constructor = 1
    unpacked_items = None
3442

3443 3444 3445
    def compile_time_value_list(self, denv):
        return [arg.compile_time_value(denv) for arg in self.args]

3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459
    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
3460
    def analyse_target_declaration(self, env):
3461
        self.replace_starred_target_node()
William Stein's avatar
William Stein committed
3462 3463 3464
        for arg in self.args:
            arg.analyse_target_declaration(env)

3465
    def analyse_types(self, env, skip_children=False):
William Stein's avatar
William Stein committed
3466 3467
        for i in range(len(self.args)):
            arg = self.args[i]
3468
            if not skip_children: arg.analyse_types(env)
William Stein's avatar
William Stein committed
3469 3470 3471
            self.args[i] = arg.coerce_to_pyobject(env)
        self.type = py_object_type
        self.is_temp = 1
3472

3473 3474 3475
    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
3476
    def analyse_target_types(self, env):
3477 3478
        self.iterator = PyTempNode(self.pos, env)
        self.unpacked_items = []
William Stein's avatar
William Stein committed
3479 3480 3481
        self.coerced_unpacked_items = []
        for arg in self.args:
            arg.analyse_target_types(env)
3482 3483 3484 3485 3486 3487
            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
3488 3489 3490 3491 3492
            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
3493

William Stein's avatar
William Stein committed
3494 3495 3496 3497
    def generate_result_code(self, code):
        self.generate_operation_code(code)
    
    def generate_assignment_code(self, rhs, code):
3498 3499 3500
        if self.starred_assignment:
            self.generate_starred_assignment_code(rhs, code)
        else:
3501
            self.generate_parallel_assignment_code(rhs, code)
3502 3503 3504 3505 3506

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

3507
    def generate_parallel_assignment_code(self, rhs, code):
3508 3509 3510 3511
        # 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.

3512 3513 3514 3515
        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
3516
        code.putln(
3517 3518
            "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
                tuple_check % rhs.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
3519 3520
                rhs.py_result(), 
                len(self.args)))
Stefan Behnel's avatar
Stefan Behnel committed
3521
        code.putln("PyObject* tuple = %s;" % rhs.py_result())
3522 3523
        for item in self.unpacked_items:
            item.allocate(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3524 3525
        for i in range(len(self.args)):
            item = self.unpacked_items[i]
3526 3527
            code.put(
                "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3528
                    item.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3529
                    i))
3530
            code.put_incref(item.result(), item.ctype())
3531 3532
            value_node = self.coerced_unpacked_items[i]
            value_node.generate_evaluation_code(code)
3533
        rhs.generate_disposal_code(code)
3534

3535 3536 3537 3538
        for i in range(len(self.args)):
            self.args[i].generate_assignment_code(
                self.coerced_unpacked_items[i], code)
                 
3539
        code.putln("} else {")
Robert Bradshaw's avatar
Robert Bradshaw committed
3540

3541
        if rhs.type is tuple_type:
3542 3543 3544 3545
            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))
3546
        else:
3547 3548
            code.globalstate.use_utility_code(unpacking_utility_code)

3549
            self.iterator.allocate(code)
3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576
            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)
            code.put_error_if_neg(self.pos, 
                "__Pyx_EndUnpack(%s)" % (
                    self.iterator.py_result()))
            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)
3577
            self.iterator.release(code)
3578 3579 3580 3581

            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
3582

3583
        code.putln("}")
3584 3585

    def generate_starred_assignment_code(self, rhs, code):
3586 3587
        code.globalstate.use_utility_code(unpacking_utility_code)

3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603
        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)

3604
        for item in self.unpacked_items:
3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639
            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
3640
                code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651
                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)

3652 3653 3654 3655 3656 3657 3658 3659
    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
3660 3661 3662 3663


class TupleNode(SequenceNode):
    #  Tuple constructor.
3664 3665
    
    type = tuple_type
3666 3667 3668

    gil_message = "Constructing Python tuple"

3669
    def analyse_types(self, env, skip_children=False):
Robert Bradshaw's avatar
Robert Bradshaw committed
3670 3671
        if len(self.args) == 0:
            self.is_temp = 0
3672
            self.is_literal = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3673
        else:
3674
            SequenceNode.analyse_types(self, env, skip_children)
Robert Bradshaw's avatar
Robert Bradshaw committed
3675 3676 3677
            
    def calculate_result_code(self):
        if len(self.args) > 0:
3678
            error(self.pos, "Positive length tuples must be constructed.")
Robert Bradshaw's avatar
Robert Bradshaw committed
3679 3680
        else:
            return Naming.empty_tuple
William Stein's avatar
William Stein committed
3681

3682 3683 3684 3685
    def calculate_constant_result(self):
        self.constant_result = tuple([
                arg.constant_result for arg in self.args])

3686 3687 3688 3689 3690 3691 3692
    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
3693
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3694 3695 3696
        if len(self.args) == 0:
            # result_code is Naming.empty_tuple
            return
William Stein's avatar
William Stein committed
3697
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3698
            "%s = PyTuple_New(%s); %s" % (
3699
                self.result(),
William Stein's avatar
William Stein committed
3700
                len(self.args),
3701
                code.error_goto_if_null(self.result(), self.pos)))
3702
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3703 3704 3705
        for i in range(len(self.args)):
            arg = self.args[i]
            if not arg.result_in_temp():
3706
                code.put_incref(arg.result(), arg.ctype())
William Stein's avatar
William Stein committed
3707 3708
            code.putln(
                "PyTuple_SET_ITEM(%s, %s, %s);" % (
3709
                    self.result(),
William Stein's avatar
William Stein committed
3710 3711
                    i,
                    arg.py_result()))
3712
            code.put_giveref(arg.py_result())
William Stein's avatar
William Stein committed
3713 3714 3715 3716 3717 3718
    
    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:
3719 3720 3721
            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
3722 3723 3724 3725


class ListNode(SequenceNode):
    #  List constructor.
3726 3727 3728
    
    # obj_conversion_errors    [PyrexError]   used internally
    # orignial_args            [ExprNode]     used internally
3729

3730 3731
    obj_conversion_errors = []

3732
    gil_message = "Constructing Python list"
3733
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3734
    def type_dependencies(self, env):
3735 3736 3737 3738 3739
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer non-object list arrays.
        return list_type
3740

3741
    def analyse_expressions(self, env):
3742
        SequenceNode.analyse_expressions(self, env)
3743 3744
        self.coerce_to_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
3745
    def analyse_types(self, env):
3746 3747 3748 3749 3750 3751
        hold_errors()
        self.original_args = list(self.args)
        SequenceNode.analyse_types(self, env)
        self.type = list_type
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
Robert Bradshaw's avatar
Robert Bradshaw committed
3752 3753 3754
        
    def coerce_to(self, dst_type, env):
        if dst_type.is_pyobject:
3755 3756 3757
            for err in self.obj_conversion_errors:
                report_error(err)
            self.obj_conversion_errors = []
Robert Bradshaw's avatar
Robert Bradshaw committed
3758 3759 3760 3761
            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
3762
            self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3763
            for i in range(len(self.original_args)):
Robert Bradshaw's avatar
Robert Bradshaw committed
3764
                arg = self.args[i]
3765 3766
                if isinstance(arg, CoerceToPyTypeNode):
                    arg = arg.arg
Robert Bradshaw's avatar
Robert Bradshaw committed
3767
                self.args[i] = arg.coerce_to(base_type, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3768 3769 3770 3771 3772 3773
        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)
3774 3775 3776
                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
3777 3778
                    self.args[i] = arg.coerce_to(member.type, env)
            self.type = dst_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3779 3780 3781 3782
        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
3783 3784 3785 3786 3787 3788 3789 3790
        
    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
3791

3792 3793 3794 3795
    def calculate_constant_result(self):
        self.constant_result = [
            arg.constant_result for arg in self.args]

3796 3797 3798
    def compile_time_value(self, denv):
        return self.compile_time_value_list(denv)

William Stein's avatar
William Stein committed
3799
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3800
        if self.type.is_pyobject:
3801 3802
            for err in self.obj_conversion_errors:
                report_error(err)
Robert Bradshaw's avatar
Robert Bradshaw committed
3803
            code.putln("%s = PyList_New(%s); %s" %
3804
                (self.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3805 3806
                len(self.args),
                code.error_goto_if_null(self.result(), self.pos)))
3807
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
3808 3809 3810 3811 3812 3813 3814 3815 3816
            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()))
3817
                code.put_giveref(arg.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
3818 3819 3820 3821 3822 3823
        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
3824
        elif self.type.is_struct:
Robert Bradshaw's avatar
Robert Bradshaw committed
3825 3826 3827 3828 3829
            for arg, member in zip(self.args, self.type.scope.var_entries):
                code.putln("%s.%s = %s;" % (
                        self.result(),
                        member.cname,
                        arg.result()))
3830 3831
        else:
            raise InternalError("List type never specified")
3832

William Stein's avatar
William Stein committed
3833 3834 3835 3836 3837
    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:
3838 3839 3840
            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
3841

Robert Bradshaw's avatar
Robert Bradshaw committed
3842

3843
class ComprehensionNode(ExprNode):
3844
    subexprs = ["target"]
3845 3846
    child_attrs = ["loop", "append"]

3847 3848
    def infer_type(self, env):
        return self.target.infer_type(env)
3849 3850 3851 3852 3853

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

3854 3855 3856
    def analyse_types(self, env):
        self.target.analyse_expressions(env)
        self.type = self.target.type
3857
        self.loop.analyse_expressions(env)
3858

3859 3860 3861
    def may_be_none(self):
        return False

3862 3863 3864 3865 3866
    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
3867

3868 3869 3870
    def generate_operation_code(self, code):
        self.loop.generate_execution_code(code)

3871 3872
    def annotate(self, code):
        self.loop.annotate(code)
3873 3874


3875
class ComprehensionAppendNode(ExprNode):
3876 3877
    # Need to be careful to avoid infinite recursion:
    # target must not be in child_attrs/subexprs
Robert Bradshaw's avatar
Robert Bradshaw committed
3878
    subexprs = ['expr']
3879 3880

    type = PyrexTypes.c_int_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3881 3882 3883
    
    def analyse_types(self, env):
        self.expr.analyse_types(env)
3884
        if not self.expr.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
3885 3886
            self.expr = self.expr.coerce_to_pyobject(env)
        self.is_temp = 1
3887 3888

    def generate_result_code(self, code):
3889 3890 3891 3892 3893 3894 3895 3896 3897
        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)
            
        code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3898
            (self.result(),
3899
             function,
3900 3901 3902 3903 3904 3905
             self.target.result(),
             self.expr.result(),
             code.error_goto_if(self.result(), self.pos)))

class DictComprehensionAppendNode(ComprehensionAppendNode):
    subexprs = ['key_expr', 'value_expr']
3906

3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924
    def analyse_types(self, env):
        self.key_expr.analyse_types(env)
        if not self.key_expr.type.is_pyobject:
            self.key_expr = self.key_expr.coerce_to_pyobject(env)
        self.value_expr.analyse_types(env)
        if not self.value_expr.type.is_pyobject:
            self.value_expr = self.value_expr.coerce_to_pyobject(env)
        self.is_temp = 1

    def generate_result_code(self, code):
        code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
            (self.result(),
             self.target.result(),
             self.key_expr.result(),
             self.value_expr.result(),
             code.error_goto_if(self.result(), self.pos)))


3925
class SetNode(ExprNode):
3926 3927
    #  Set constructor.

3928 3929
    type = set_type

3930 3931 3932
    subexprs = ['args']

    gil_message = "Constructing Python set"
3933
    
3934 3935 3936 3937 3938 3939 3940 3941
    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

3942 3943 3944
    def may_be_none(self):
        return False

3945 3946 3947 3948
    def calculate_constant_result(self):
        self.constant_result = set([
                arg.constant_result for arg in self.args])

3949 3950 3951 3952 3953 3954 3955 3956
    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):
3957
        code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3958 3959 3960 3961 3962
        self.allocate_temp_result(code)
        code.putln(
            "%s = PySet_New(0); %s" % (
                self.result(),
                code.error_goto_if_null(self.result(), self.pos)))
3963
        code.put_gotref(self.py_result())
3964 3965 3966 3967 3968 3969 3970 3971
        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
3972

William Stein's avatar
William Stein committed
3973

3974
class DictNode(ExprNode):
William Stein's avatar
William Stein committed
3975 3976
    #  Dictionary constructor.
    #
3977
    #  key_value_pairs  [DictItemNode]
3978 3979
    #
    # obj_conversion_errors    [PyrexError]   used internally
3980 3981
    
    subexprs = ['key_value_pairs']
3982 3983
    is_temp = 1
    type = dict_type
3984

3985 3986
    obj_conversion_errors = []

3987 3988 3989
    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
3990
    
3991
    def compile_time_value(self, denv):
Robert Bradshaw's avatar
Robert Bradshaw committed
3992 3993
        pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
            for item in self.key_value_pairs]
3994 3995 3996 3997 3998
        try:
            return dict(pairs)
        except Exception, e:
            self.compile_time_value_error(e)
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3999
    def type_dependencies(self, env):
4000 4001 4002 4003 4004 4005
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer struct constructors.
        return dict_type

William Stein's avatar
William Stein committed
4006
    def analyse_types(self, env):
4007
        hold_errors()
Robert Bradshaw's avatar
Robert Bradshaw committed
4008 4009
        for item in self.key_value_pairs:
            item.analyse_types(env)
4010 4011
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
4012 4013 4014

    def may_be_none(self):
        return False
4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029
        
    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
4030
                if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
4031
                    error(item.key.pos, "Invalid struct field identifier")
4032
                    item.key = StringNode(item.key.pos, value="<error>")
4033
                else:
Stefan Behnel's avatar
Stefan Behnel committed
4034 4035
                    key = str(item.key.value) # converts string literals to unicode in Py3
                    member = dst_type.scope.lookup_here(key)
4036
                    if not member:
Stefan Behnel's avatar
Stefan Behnel committed
4037
                        error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051
                    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 = []
4052 4053 4054

    gil_message = "Constructing Python dict"

William Stein's avatar
William Stein committed
4055 4056 4057
    def generate_evaluation_code(self, code):
        #  Custom method used here because key-value
        #  pairs are evaluated and used one at a time.
4058 4059
        code.mark_pos(self.pos)
        self.allocate_temp_result(code)
4060 4061 4062 4063 4064 4065
        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)))
4066
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
4067 4068
        for item in self.key_value_pairs:
            item.generate_evaluation_code(code)
4069 4070 4071 4072 4073 4074 4075 4076 4077
            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(),
4078
                        item.key.value,
4079
                        item.value.result()))
Robert Bradshaw's avatar
Robert Bradshaw committed
4080
            item.generate_disposal_code(code)
4081
            item.free_temps(code)
4082 4083
            
    def annotate(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4084 4085 4086
        for item in self.key_value_pairs:
            item.annotate(code)
            
4087
class DictItemNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
4088 4089 4090 4091 4092
    # Represents a single item in a DictNode
    #
    # key          ExprNode
    # value        ExprNode
    subexprs = ['key', 'value']
4093

4094
    nogil_check = None # Parent DictNode takes care of it
4095

4096 4097 4098
    def calculate_constant_result(self):
        self.constant_result = (
            self.key.constant_result, self.value.constant_result)
Robert Bradshaw's avatar
Robert Bradshaw committed
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108
            
    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
4109

4110 4111 4112
    def generate_disposal_code(self, code):
        self.key.generate_disposal_code(code)
        self.value.generate_disposal_code(code)
4113 4114 4115 4116

    def free_temps(self, code):
        self.key.free_temps(code)
        self.value.free_temps(code)
4117 4118 4119
        
    def __iter__(self):
        return iter([self.key, self.value])
William Stein's avatar
William Stein committed
4120

Stefan Behnel's avatar
Stefan Behnel committed
4121

4122
class ClassNode(ExprNode):
William Stein's avatar
William Stein committed
4123 4124 4125 4126
    #  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
4127
    #  name         EncodedString      Name of the class
William Stein's avatar
William Stein committed
4128 4129 4130 4131 4132
    #  bases        ExprNode           Base class tuple
    #  dict         ExprNode           Class dict (not owned by this node)
    #  doc          ExprNode or None   Doc string
    #  module_name  string             Name of defining module
    
4133 4134
    subexprs = ['bases', 'doc']

William Stein's avatar
William Stein committed
4135 4136 4137 4138 4139 4140 4141 4142 4143
    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.module_name = env.global_scope().qualified_name
        self.type = py_object_type
        self.is_temp = 1
        env.use_utility_code(create_class_utility_code);
4144

4145 4146 4147
    def may_be_none(self):
        return False

4148 4149
    gil_message = "Constructing Python class"

William Stein's avatar
William Stein committed
4150
    def generate_result_code(self, code):
4151
        cname = code.intern_identifier(self.name)
William Stein's avatar
William Stein committed
4152
        if self.doc:
Robert Bradshaw's avatar
Robert Bradshaw committed
4153 4154
            code.put_error_if_neg(self.pos, 
                'PyDict_SetItemString(%s, "__doc__", %s)' % (
William Stein's avatar
William Stein committed
4155
                    self.dict.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
4156
                    self.doc.py_result()))
William Stein's avatar
William Stein committed
4157
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4158
            '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
4159
                self.result(),
William Stein's avatar
William Stein committed
4160 4161
                self.bases.py_result(),
                self.dict.py_result(),
4162
                cname,
William Stein's avatar
William Stein committed
4163
                self.module_name,
4164
                code.error_goto_if_null(self.result(), self.pos)))
4165
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4166 4167


4168
class UnboundMethodNode(ExprNode):
William Stein's avatar
William Stein committed
4169 4170 4171 4172 4173 4174
    #  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
    
4175 4176 4177
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4178 4179 4180 4181
    subexprs = ['function']
    
    def analyse_types(self, env):
        self.function.analyse_types(env)
4182

4183 4184 4185
    def may_be_none(self):
        return False

4186 4187
    gil_message = "Constructing an unbound method"

William Stein's avatar
William Stein committed
4188
    def generate_result_code(self, code):
4189
        class_cname = code.pyclass_stack[-1].classobj.result()
William Stein's avatar
William Stein committed
4190
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4191
            "%s = PyMethod_New(%s, 0, %s); %s" % (
4192
                self.result(),
William Stein's avatar
William Stein committed
4193
                self.function.py_result(),
4194
                class_cname,
4195
                code.error_goto_if_null(self.result(), self.pos)))
4196
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4197

Robert Bradshaw's avatar
Robert Bradshaw committed
4198

4199
class PyCFunctionNode(AtomicExprNode):
William Stein's avatar
William Stein committed
4200 4201 4202 4203 4204 4205
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs a PyCFunction object
    #  from a PyMethodDef struct.
    #
    #  pymethdef_cname   string   PyMethodDef structure
    
4206 4207 4208
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4209
    def analyse_types(self, env):
4210
        pass
4211 4212 4213

    def may_be_none(self):
        return False
4214
    
4215 4216
    gil_message = "Constructing Python function"

William Stein's avatar
William Stein committed
4217 4218
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4219
            "%s = PyCFunction_New(&%s, 0); %s" % (
4220
                self.result(),
William Stein's avatar
William Stein committed
4221
                self.pymethdef_cname,
4222
                code.error_goto_if_null(self.result(), self.pos)))
4223
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4224 4225 4226 4227 4228 4229 4230

#-------------------------------------------------------------------
#
#  Unary operator nodes
#
#-------------------------------------------------------------------

4231 4232 4233 4234 4235 4236 4237
compile_time_unary_operators = {
    'not': operator.not_,
    '~': operator.inv,
    '-': operator.neg,
    '+': operator.pos,
}

4238
class UnopNode(ExprNode):
William Stein's avatar
William Stein committed
4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250
    #  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
4251
    infix = True
4252 4253 4254 4255

    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
4256
    
4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267
    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)
4268 4269 4270
    
    def infer_type(self, env):
        return self.operand.infer_type(env)
4271

William Stein's avatar
William Stein committed
4272 4273 4274 4275 4276 4277
    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
4278 4279
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
4280 4281 4282 4283
        else:
            self.analyse_c_operation(env)
    
    def check_const(self):
4284
        return self.operand.check_const()
William Stein's avatar
William Stein committed
4285 4286 4287
    
    def is_py_operation(self):
        return self.operand.type.is_pyobject
4288

4289
    def nogil_check(self, env):
4290
        if self.is_py_operation():
4291
            self.gil_error()
4292

Danilo Freitas's avatar
Danilo Freitas committed
4293
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4294
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
4295
        return type.is_cpp_class
William Stein's avatar
William Stein committed
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306
    
    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
4307
            "%s = %s(%s); %s" % (
4308
                self.result(), 
William Stein's avatar
William Stein committed
4309 4310
                function, 
                self.operand.py_result(),
4311
                code.error_goto_if_null(self.result(), self.pos)))
4312
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4313 4314 4315 4316 4317 4318 4319
        
    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
4320
    def analyse_cpp_operation(self, env):
4321
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
4322
        if type.is_ptr:
Danilo Freitas's avatar
Danilo Freitas committed
4323
            type = type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4324
        function = type.scope.lookup("operator%s" % self.operator)
Danilo Freitas's avatar
Danilo Freitas committed
4325 4326
        if not function:
            error(self.pos, "'%s' operator not defined for %s"
4327
                % (self.operator, type))
Danilo Freitas's avatar
Danilo Freitas committed
4328 4329
            self.type_error()
            return
4330 4331 4332 4333
        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
4334

William Stein's avatar
William Stein committed
4335

4336
class NotNode(ExprNode):
William Stein's avatar
William Stein committed
4337 4338 4339
    #  'not' operator
    #
    #  operand   ExprNode
4340 4341
    
    type = PyrexTypes.c_bint_type
4342

4343 4344
    subexprs = ['operand']
    
4345 4346 4347
    def calculate_constant_result(self):
        self.constant_result = not self.operand.constant_result

4348 4349 4350 4351 4352 4353 4354
    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)

4355 4356
    def infer_type(self, env):
        return PyrexTypes.c_bint_type
William Stein's avatar
William Stein committed
4357 4358 4359 4360 4361 4362
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
        self.operand = self.operand.coerce_to_boolean(env)
    
    def calculate_result_code(self):
4363
        return "(!%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380
    
    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):
4381 4382 4383 4384
        if self.is_cpp_operation():
            return "(+%s)" % self.operand.result()
        else:
            return self.operand.result()
William Stein's avatar
William Stein committed
4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396


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
4397
        if self.type.is_complex:
4398
            self.infix = False
William Stein's avatar
William Stein committed
4399 4400 4401 4402 4403
    
    def py_operation_function(self):
        return "PyNumber_Negative"
    
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4404 4405 4406 4407
        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
4408

4409 4410 4411 4412 4413
    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
4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426
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):
4427
        return "(~%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4428 4429


4430 4431
class CUnopNode(UnopNode):

Robert Bradshaw's avatar
Robert Bradshaw committed
4432 4433 4434
    def is_py_operation(self):
        return False

4435 4436
class DereferenceNode(CUnopNode):
    #  unary * operator
4437 4438

    operator = '*'
4439
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4440 4441 4442 4443 4444 4445 4446 4447
    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
4448 4449


4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468
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)


4469
class AmpersandNode(ExprNode):
William Stein's avatar
William Stein committed
4470 4471 4472 4473 4474
    #  The C address-of operator.
    #
    #  operand  ExprNode
    
    subexprs = ['operand']
4475 4476 4477
    
    def infer_type(self, env):
        return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
William Stein's avatar
William Stein committed
4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490

    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):
4491
        return self.operand.check_const_addr()
William Stein's avatar
William Stein committed
4492 4493 4494 4495 4496 4497 4498
    
    def error(self, mess):
        error(self.pos, mess)
        self.type = PyrexTypes.error_type
        self.result_code = "<error>"
    
    def calculate_result_code(self):
4499
        return "(&%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513

    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.
4514
    if isinstance(operand, IntNode) and operator == '-':
4515
        return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
Robert Bradshaw's avatar
Robert Bradshaw committed
4516 4517
    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
4518 4519 4520 4521 4522
    return unop_node_classes[operator](pos, 
        operator = operator, 
        operand = operand)


4523
class TypecastNode(ExprNode):
William Stein's avatar
William Stein committed
4524 4525
    #  C type cast
    #
4526
    #  operand      ExprNode
William Stein's avatar
William Stein committed
4527 4528
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
4529 4530 4531
    #
    #  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
4532 4533
    
    subexprs = ['operand']
4534
    base_type = declarator = type = None
William Stein's avatar
William Stein committed
4535
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4536
    def type_dependencies(self, env):
4537 4538
        return ()
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4539
    def infer_type(self, env):
4540 4541 4542 4543 4544
        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
4545
    def analyse_types(self, env):
4546 4547 4548
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
4549 4550 4551 4552
        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
4553 4554 4555
        self.operand.analyse_types(env)
        to_py = self.type.is_pyobject
        from_py = self.operand.type.is_pyobject
4556 4557
        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
4558
        if to_py and not from_py:
4559 4560 4561 4562 4563 4564
            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
4565
                self.result_ctype = py_object_type
4566
                self.operand = self.operand.coerce_to_pyobject(env)
4567
            else:
4568 4569 4570 4571 4572
                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? 
4573
                    warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4574
                self.operand = self.operand.coerce_to_simple(env)
4575
        elif from_py and not to_py:
4576
            if self.type.create_from_py_utility_code(env):
4577
                self.operand = self.operand.coerce_to(self.type, env)
4578 4579 4580
            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")
4581 4582
            else:
                warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4583 4584
        elif from_py and to_py:
            if self.typecheck and self.type.is_extension_type:
4585
                self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4586 4587
        elif self.type.is_complex and self.operand.type.is_complex:
            self.operand = self.operand.coerce_to_simple(env)
4588

4589 4590 4591
    def nogil_check(self, env):
        if self.type and self.type.is_pyobject and self.is_temp:
            self.gil_error()
4592

William Stein's avatar
William Stein committed
4593
    def check_const(self):
4594
        return self.operand.check_const()
Stefan Behnel's avatar
Stefan Behnel committed
4595 4596

    def calculate_constant_result(self):
4597 4598 4599
        # we usually do not know the result of a type cast at code
        # generation time
        pass
William Stein's avatar
William Stein committed
4600 4601
    
    def calculate_result_code(self):
4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615
        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
4616
    
4617 4618 4619 4620 4621
    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
4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632
    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;" % (
4633 4634 4635
                    self.result(),
                    self.operand.result()))
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
4636 4637


4638
class SizeofNode(ExprNode):
William Stein's avatar
William Stein committed
4639
    #  Abstract base class for sizeof(x) expression nodes.
4640
    
4641
    type = PyrexTypes.c_size_t_type
William Stein's avatar
William Stein committed
4642 4643

    def check_const(self):
4644
        return True
William Stein's avatar
William Stein committed
4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656

    def generate_result_code(self, code):
        pass


class SizeofTypeNode(SizeofNode):
    #  C sizeof function applied to a type
    #
    #  base_type   CBaseTypeNode
    #  declarator  CDeclaratorNode
    
    subexprs = []
4657
    arg_type = None
William Stein's avatar
William Stein committed
4658 4659
    
    def analyse_types(self, env):
4660 4661
        # 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
4662
        if 0 and self.base_type.module_path:
4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673
            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
4674 4675 4676 4677
        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
4678 4679 4680 4681
        self.check_type()
        
    def check_type(self):
        arg_type = self.arg_type
4682
        if arg_type.is_pyobject and not arg_type.is_extension_type:
William Stein's avatar
William Stein committed
4683 4684 4685 4686 4687 4688 4689
            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):
4690 4691 4692 4693 4694 4695
        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
4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706
        return "(sizeof(%s))" % arg_code
    

class SizeofVarNode(SizeofNode):
    #  C sizeof function applied to a variable
    #
    #  operand   ExprNode
    
    subexprs = ['operand']
    
    def analyse_types(self, env):
4707 4708 4709 4710 4711 4712 4713 4714 4715
        # 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
4716 4717
    
    def calculate_result_code(self):
4718
        return "(sizeof(%s))" % self.operand.result()
William Stein's avatar
William Stein committed
4719 4720 4721 4722
    
    def generate_result_code(self, code):
        pass

Robert Bradshaw's avatar
Robert Bradshaw committed
4723
class TypeofNode(ExprNode):
4724 4725 4726
    #  Compile-time type of an expression, as a string.
    #
    #  operand   ExprNode
Robert Bradshaw's avatar
Robert Bradshaw committed
4727
    #  literal   StringNode # internal
4728
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4729 4730 4731
    literal = None
    type = py_object_type
    
Stefan Behnel's avatar
Stefan Behnel committed
4732
    subexprs = ['literal'] # 'operand' will be ignored after type analysis!
4733 4734 4735
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
4736 4737
        self.literal = StringNode(
            self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
Robert Bradshaw's avatar
Robert Bradshaw committed
4738 4739
        self.literal.analyse_types(env)
        self.literal = self.literal.coerce_to_pyobject(env)
4740 4741 4742 4743

    def may_be_none(self):
        return False

4744
    def generate_evaluation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4745 4746 4747 4748
        self.literal.generate_evaluation_code(code)
    
    def calculate_result_code(self):
        return self.literal.calculate_result_code()
William Stein's avatar
William Stein committed
4749 4750 4751 4752 4753 4754 4755

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

Stefan Behnel's avatar
Stefan Behnel committed
4756 4757 4758
def _not_in(x, seq):
    return x not in seq

4759 4760 4761
compile_time_binary_operators = {
    '<': operator.lt,
    '<=': operator.le,
4762
    '==': operator.eq,
4763 4764 4765 4766 4767 4768 4769
    '!=': operator.ne,
    '>=': operator.ge,
    '>': operator.gt,
    'is': operator.is_,
    'is_not': operator.is_not,
    '+': operator.add,
    '&': operator.and_,
4770
    '/': operator.truediv,
4771 4772 4773 4774 4775 4776 4777 4778 4779
    '//': 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
4780 4781
    'in': operator.contains,
    'not_in': _not_in,
4782 4783 4784 4785 4786 4787 4788
}

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"
4789
                % node.operator)
4790 4791
    return func

4792
class BinopNode(ExprNode):
William Stein's avatar
William Stein committed
4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805
    #  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']
4806 4807 4808 4809 4810 4811 4812

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

4813 4814 4815 4816 4817 4818 4819 4820
    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)
4821 4822 4823
    
    def infer_type(self, env):
        return self.result_type(self.operand1.infer_type(env),
Robert Bradshaw's avatar
Robert Bradshaw committed
4824 4825
                                self.operand2.infer_type(env))
    
William Stein's avatar
William Stein committed
4826 4827 4828 4829 4830
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
        if self.is_py_operation():
            self.coerce_operands_to_pyobjects(env)
4831 4832 4833
            self.type = self.result_type(self.operand1.type,
                                         self.operand2.type)
            assert self.type.is_pyobject
William Stein's avatar
William Stein committed
4834
            self.is_temp = 1
DaniloFreitas's avatar
DaniloFreitas committed
4835 4836
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
4837 4838 4839 4840
        else:
            self.analyse_c_operation(env)
    
    def is_py_operation(self):
4841 4842 4843 4844 4845
        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
4846
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4847 4848
        return (self.operand1.type.is_cpp_class
            or self.operand2.type.is_cpp_class)
DaniloFreitas's avatar
DaniloFreitas committed
4849
    
4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866
    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
    
4867 4868
    def result_type(self, type1, type2):
        if self.is_py_operation_types(type1, type2):
4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886
            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
4887
                    if type2.is_int:
4888
                        return type1
4889 4890 4891 4892
            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
4893 4894 4895
            return py_object_type
        else:
            return self.compute_c_result_type(type1, type2)
4896

4897
    def nogil_check(self, env):
4898
        if self.is_py_operation():
4899
            self.gil_error()
4900
        
William Stein's avatar
William Stein committed
4901 4902 4903 4904 4905
    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):
4906
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
4907 4908 4909 4910 4911 4912 4913 4914 4915 4916
    
    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()
            if function == "PyNumber_Power":
                extra_args = ", Py_None"
            else:
                extra_args = ""
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4917
                "%s = %s(%s, %s%s); %s" % (
4918
                    self.result(), 
William Stein's avatar
William Stein committed
4919 4920 4921 4922
                    function, 
                    self.operand1.py_result(),
                    self.operand2.py_result(),
                    extra_args,
4923
                    code.error_goto_if_null(self.result(), self.pos)))
4924
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937
    
    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


class NumBinopNode(BinopNode):
    #  Binary operation taking numeric arguments.
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4938 4939
    infix = True
    
William Stein's avatar
William Stein committed
4940 4941 4942 4943 4944 4945
    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()
4946
            return
4947
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
4948
            self.infix = False
4949 4950 4951
        if not self.infix:
            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
4952 4953 4954 4955 4956 4957
    
    def compute_c_result_type(self, type1, type2):
        if self.c_types_okay(type1, type2):
            return PyrexTypes.widest_numeric_type(type1, type2)
        else:
            return None
4958 4959 4960 4961 4962 4963 4964 4965

    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
4966 4967
    
    def c_types_okay(self, type1, type2):
4968 4969 4970
        #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
4971 4972

    def calculate_result_code(self):
4973 4974 4975 4976 4977 4978
        if self.infix:
            return "(%s %s %s)" % (
                self.operand1.result(), 
                self.operator, 
                self.operand2.result())
        else:
4979 4980 4981
            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))
4982
            return "%s(%s, %s)" % (
4983
                func,
4984 4985
                self.operand1.result(),
                self.operand2.result())
William Stein's avatar
William Stein committed
4986 4987 4988 4989 4990
    
    def py_operation_function(self):
        return self.py_functions[self.operator]

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
4991 4992 4993
        "|":        "PyNumber_Or",
        "^":        "PyNumber_Xor",
        "&":        "PyNumber_And",
4994 4995
        "<<":       "PyNumber_Lshift",
        ">>":       "PyNumber_Rshift",
Robert Bradshaw's avatar
Robert Bradshaw committed
4996 4997 4998 4999
        "+":        "PyNumber_Add",
        "-":        "PyNumber_Subtract",
        "*":        "PyNumber_Multiply",
        "/":        "__Pyx_PyNumber_Divide",
5000
        "//":       "PyNumber_FloorDivide",
Robert Bradshaw's avatar
Robert Bradshaw committed
5001
        "%":        "PyNumber_Remainder",
5002
        "**":       "PyNumber_Power"
William Stein's avatar
William Stein committed
5003 5004 5005 5006 5007 5008 5009
    }


class IntBinopNode(NumBinopNode):
    #  Binary operation taking integer arguments.
    
    def c_types_okay(self, type1, type2):
5010 5011 5012
        #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
5013 5014 5015 5016 5017

    
class AddNode(NumBinopNode):
    #  '+' operator.
    
5018 5019 5020
    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
5021
        else:
5022
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5023 5024

    def compute_c_result_type(self, type1, type2):
5025 5026
        #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
5027
            return type1
5028
        elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
William Stein's avatar
William Stein committed
5029 5030 5031 5032 5033 5034 5035 5036 5037 5038
            return type2
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class SubNode(NumBinopNode):
    #  '-' operator.
    
    def compute_c_result_type(self, type1, type2):
5039
        if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
William Stein's avatar
William Stein committed
5040
            return type1
5041
        elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
William Stein's avatar
William Stein committed
5042 5043 5044 5045 5046 5047 5048 5049 5050
            return PyrexTypes.c_int_type
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class MulNode(NumBinopNode):
    #  '*' operator.
    
5051
    def is_py_operation_types(self, type1, type2):
William Stein's avatar
William Stein committed
5052 5053 5054 5055
        if (type1.is_string and type2.is_int) \
            or (type2.is_string and type1.is_int):
                return 1
        else:
5056
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5057 5058


5059 5060 5061
class DivNode(NumBinopNode):
    #  '/' or '//' operator.
    
5062
    cdivision = None
5063 5064
    truedivision = None   # == "unknown" if operator == '/'
    ctruedivision = False
Robert Bradshaw's avatar
Robert Bradshaw committed
5065
    cdivision_warnings = False
5066
    zerodivision_check = None
5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093

    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)

5094
    def analyse_types(self, env):
5095 5096 5097 5098
        if self.cdivision or env.directives['cdivision']:
            self.ctruedivision = False
        else:
            self.ctruedivision = self.truedivision
5099
        NumBinopNode.analyse_types(self, env)
5100 5101
        if self.is_cpp_operation():
            self.cdivision = True
5102
        if not self.type.is_pyobject:
5103 5104
            self.zerodivision_check = (
                self.cdivision is None and not env.directives['cdivision']
5105
                and (not self.operand2.has_constant_result() or
5106
                     self.operand2.constant_result == 0))
5107 5108 5109 5110
            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)
5111 5112
                if env.nogil:
                    error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
5113 5114 5115 5116 5117 5118 5119 5120 5121

    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)

5122 5123 5124 5125 5126
    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
5127

5128
    def generate_evaluation_code(self, code):
5129
        if not self.type.is_pyobject and not self.type.is_complex:
5130 5131 5132 5133 5134
            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:
5135
                code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
5136
        NumBinopNode.generate_evaluation_code(self, code)
5137
        self.generate_div_warning_code(code)
5138 5139
    
    def generate_div_warning_code(self, code):
5140 5141
        if not self.type.is_pyobject:
            if self.zerodivision_check:
5142 5143 5144 5145 5146
                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)
5147 5148 5149
                code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
                code.putln(code.error_goto(self.pos))
                code.putln("}")
5150 5151 5152 5153 5154 5155 5156 5157 5158
                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
5159
            if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
5160 5161 5162 5163 5164 5165 5166 5167
                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
5168 5169
    
    def calculate_result_code(self):
5170 5171 5172
        if self.type.is_complex:
            return NumBinopNode.calculate_result_code(self)
        elif self.type.is_float and self.operator == '//':
5173
            return "floor(%s / %s)" % (
5174
                self.operand1.result(),
5175
                self.operand2.result())
5176 5177 5178 5179 5180 5181 5182 5183 5184
        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)
5185 5186
        else:
            return "__Pyx_div_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5187
                    self.type.specialization_name(),
5188 5189
                    self.operand1.result(), 
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
5190 5191


Robert Bradshaw's avatar
Robert Bradshaw committed
5192
class ModNode(DivNode):
William Stein's avatar
William Stein committed
5193
    #  '%' operator.
5194

5195 5196 5197 5198
    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
5199

5200 5201 5202 5203 5204 5205
    def zero_division_message(self):
        if self.type.is_int:
            return "integer division or modulo by zero"
        else:
            return "float divmod()"
    
5206
    def generate_evaluation_code(self, code):
5207 5208 5209 5210 5211
        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:
5212
                    code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
5213
                else:
5214 5215
                    code.globalstate.use_utility_code(
                        mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
5216
        NumBinopNode.generate_evaluation_code(self, code)
5217
        self.generate_div_warning_code(code)
5218
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5219
    def calculate_result_code(self):
5220 5221 5222 5223 5224 5225 5226 5227 5228 5229
        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
5230
        else:
5231
            return "__Pyx_mod_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5232
                    self.type.specialization_name(),
5233 5234
                    self.operand1.result(), 
                    self.operand2.result())
William Stein's avatar
William Stein committed
5235 5236 5237

class PowNode(NumBinopNode):
    #  '**' operator.
Robert Bradshaw's avatar
Robert Bradshaw committed
5238 5239 5240
    
    def analyse_c_operation(self, env):
        NumBinopNode.analyse_c_operation(self, env)
5241 5242 5243 5244
        if self.type.is_complex:
            error(self.pos, "complex powers not yet supported")
            self.pow_func = "<error>"
        elif self.type.is_float:
Robert Bradshaw's avatar
Robert Bradshaw committed
5245
            self.pow_func = "pow"
William Stein's avatar
William Stein committed
5246
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
5247 5248 5249 5250
            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('')))
5251

William Stein's avatar
William Stein committed
5252
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5253 5254 5255 5256
        return "%s(%s, %s)" % (
            self.pow_func, 
            self.operand1.result(), 
            self.operand2.result())
5257

William Stein's avatar
William Stein committed
5258

5259 5260 5261 5262 5263 5264 5265
# Note: This class is temporary "shut down" into an ineffective mode temp
# allocation mode.
#
# 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).
5266
class BoolBinopNode(ExprNode):
William Stein's avatar
William Stein committed
5267 5268 5269 5270 5271 5272
    #  Short-circuiting boolean operation.
    #
    #  operator     string
    #  operand1     ExprNode
    #  operand2     ExprNode
    
5273
    subexprs = ['operand1', 'operand2']
5274 5275
    
    def infer_type(self, env):
5276 5277 5278
        type1 = self.operand1.infer_type(env)
        type2 = self.operand2.infer_type(env)
        return PyrexTypes.spanning_type(type1, type2)
5279 5280 5281 5282 5283 5284 5285 5286 5287 5288

    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
5289
    
5290 5291 5292 5293 5294 5295 5296
    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)
5297 5298 5299 5300 5301 5302
    
    def coerce_to_boolean(self, env):
        self.operand1 = self.operand1.coerce_to_boolean(env)
        self.operand2 = self.operand2.coerce_to_boolean(env)
        self.type = PyrexTypes.c_bint_type
        return self
5303

William Stein's avatar
William Stein committed
5304 5305 5306
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
5307
        self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
5308 5309 5310 5311 5312 5313 5314 5315
        if self.type.is_numeric and self.type is not PyrexTypes.c_bint_type:
            # special case: if one of the results is a bint and the other
            # is another C integer, we must prevent returning a numeric
            # type so that we do not loose the ability to coerce to a
            # Python bool
            if self.operand1.type is PyrexTypes.c_bint_type or \
                   self.operand2.type is PyrexTypes.c_bint_type:
                self.type = py_object_type
5316 5317
        self.operand1 = self.operand1.coerce_to(self.type, env)
        self.operand2 = self.operand2.coerce_to(self.type, env)
5318
        
William Stein's avatar
William Stein committed
5319 5320
        # For what we're about to do, it's vital that
        # both operands be temp nodes.
5321 5322
        self.operand1 = self.operand1.coerce_to_simple(env)
        self.operand2 = self.operand2.coerce_to_simple(env)
William Stein's avatar
William Stein committed
5323
        self.is_temp = 1
5324 5325 5326

    gil_message = "Truth-testing Python object"

William Stein's avatar
William Stein committed
5327
    def check_const(self):
5328
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
5329 5330
    
    def generate_evaluation_code(self, code):
5331
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
5332
        self.operand1.generate_evaluation_code(code)
5333
        test_result, uses_temp = self.generate_operand1_test(code)
William Stein's avatar
William Stein committed
5334 5335 5336 5337 5338 5339 5340 5341
        if self.operator == 'and':
            sense = ""
        else:
            sense = "!"
        code.putln(
            "if (%s%s) {" % (
                sense,
                test_result))
5342 5343
        if uses_temp:
            code.funcstate.release_temp(test_result)
5344
        self.operand1.generate_disposal_code(code)
William Stein's avatar
William Stein committed
5345
        self.operand2.generate_evaluation_code(code)
5346
        self.allocate_temp_result(code)
5347
        self.operand2.make_owned_reference(code)
5348
        code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5349 5350
        self.operand2.generate_post_assignment_code(code)
        self.operand2.free_temps(code)
5351
        code.putln("} else {")
5352
        self.operand1.make_owned_reference(code)
5353
        code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5354 5355
        self.operand1.generate_post_assignment_code(code)
        self.operand1.free_temps(code)
5356
        code.putln("}")
William Stein's avatar
William Stein committed
5357 5358 5359 5360
    
    def generate_operand1_test(self, code):
        #  Generate code to test the truth of the first operand.
        if self.type.is_pyobject:
5361 5362
            test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
                                                       manage_ref=False)
William Stein's avatar
William Stein committed
5363
            code.putln(
5364
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
William Stein's avatar
William Stein committed
5365 5366
                    test_result,
                    self.operand1.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
5367
                    code.error_goto_if_neg(test_result, self.pos)))
William Stein's avatar
William Stein committed
5368
        else:
5369
            test_result = self.operand1.result()
5370
        return (test_result, self.type.is_pyobject)
William Stein's avatar
William Stein committed
5371 5372


5373
class CondExprNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
5374 5375 5376 5377 5378 5379
    #  Short-circuiting conditional expression.
    #
    #  test        ExprNode
    #  true_val    ExprNode
    #  false_val   ExprNode
    
5380 5381
    true_val = None
    false_val = None
Robert Bradshaw's avatar
Robert Bradshaw committed
5382 5383
    
    subexprs = ['test', 'true_val', 'false_val']
5384
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5385 5386
    def type_dependencies(self, env):
        return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5387
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5388 5389 5390
    def infer_type(self, env):
        return self.compute_result_type(self.true_val.infer_type(env),
                                        self.false_val.infer_type(env))
5391 5392 5393 5394 5395 5396 5397

    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
5398 5399 5400 5401 5402 5403
    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)
        self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5404 5405 5406 5407 5408
        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
5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419
            self.type_error()
        
    def compute_result_type(self, type1, type2):
        if type1 == type2:
            return type1
        elif type1.is_numeric and type2.is_numeric:
            return PyrexTypes.widest_numeric_type(type1, type2)
        elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
            return type2
        elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
            return type1
5420 5421
        elif type1.is_pyobject or type2.is_pyobject:
            return py_object_type
5422 5423 5424 5425
        elif type1.assignable_from(type2):
            return type1
        elif type2.assignable_from(type1):
            return type2
Robert Bradshaw's avatar
Robert Bradshaw committed
5426
        else:
5427
            return PyrexTypes.error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
5428 5429 5430 5431 5432 5433
        
    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
5434
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5435
    def check_const(self):
5436 5437 5438
        return (self.test.check_const() 
            and self.true_val.check_const()
            and self.false_val.check_const())
Robert Bradshaw's avatar
Robert Bradshaw committed
5439 5440
    
    def generate_evaluation_code(self, code):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5441 5442 5443 5444
        # 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)
5445
        self.allocate_temp_result(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
5446
        self.test.generate_evaluation_code(code)
5447
        code.putln("if (%s) {" % self.test.result() )
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5448
        self.eval_and_get(code, self.true_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
5449
        code.putln("} else {")
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5450
        self.eval_and_get(code, self.false_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
5451 5452
        code.putln("}")
        self.test.generate_disposal_code(code)
5453
        self.test.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
5454

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5455 5456 5457 5458 5459 5460 5461
    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)

5462 5463 5464 5465 5466 5467 5468 5469 5470 5471
richcmp_constants = {
    "<" : "Py_LT",
    "<=": "Py_LE",
    "==": "Py_EQ",
    "!=": "Py_NE",
    "<>": "Py_NE",
    ">" : "Py_GT",
    ">=": "Py_GE",
}

5472
class CmpNode(object):
William Stein's avatar
William Stein committed
5473 5474
    #  Mixin class containing code common to PrimaryCmpNodes
    #  and CascadedCmpNodes.
5475 5476 5477 5478
    
    def infer_types(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type
5479 5480 5481 5482 5483

    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)
5484 5485 5486 5487 5488 5489 5490
        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

5491 5492
    def cascaded_compile_time_value(self, operand1, denv):
        func = get_compile_time_binop(self)
5493
        operand2 = self.operand2.compile_time_value(denv)
5494 5495 5496 5497
        try:
            result = func(operand1, operand2)
        except Exception, e:
            self.compile_time_value_error(e)
5498
            result = None
5499 5500 5501
        if result:
            cascade = self.cascade
            if cascade:
5502
                # FIXME: I bet this must call cascaded_compile_time_value()
5503
                result = result and cascade.cascaded_compile_time_value(operand2, denv)
5504 5505
        return result

5506
    def is_cpp_comparison(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5507
        return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
5508

5509
    def find_common_int_type(self, env, op, operand1, operand2):
5510 5511 5512 5513 5514 5515
        # 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

5516
        if isinstance(operand1, (StringNode, BytesNode, UnicodeNode)) \
5517 5518
               and operand1.can_coerce_to_char_literal():
            type1_can_be_int = True
5519
        if isinstance(operand2, (StringNode, BytesNode, UnicodeNode)) \
5520 5521 5522 5523 5524
                 and operand2.can_coerce_to_char_literal():
            type2_can_be_int = True

        if type1.is_int:
            if type2_can_be_int:
5525
                return type1
5526 5527
        elif type2.is_int:
            if type1_can_be_int:
5528
                return type2
5529 5530
        elif type1_can_be_int:
            if type2_can_be_int:
5531
                return PyrexTypes.c_uchar_type
5532

5533
        return None
5534

5535
    def find_common_type(self, env, op, operand1, common_type=None):
5536 5537 5538 5539
        operand2 = self.operand2
        type1 = operand1.type
        type2 = operand2.type

5540 5541
        new_common_type = None

Stefan Behnel's avatar
Stefan Behnel committed
5542
        # catch general errors
5543 5544 5545
        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")
5546
            new_common_type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
5547 5548

        # try to use numeric comparisons where possible
5549
        elif type1.is_complex or type2.is_complex:
5550
            if op not in ('==', '!='):
5551 5552 5553 5554 5555 5556
                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
5557
            else:
5558
                new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5559 5560
        elif type1.is_numeric and type2.is_numeric:
            new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5561
        elif common_type is None or not common_type.is_pyobject:
5562
            new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5563 5564

        if new_common_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
5565
            # fall back to generic type compatibility tests
5566
            if type1 == type2:
5567 5568 5569 5570 5571 5572
                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
5573
                        new_common_type = py_object_type
5574 5575 5576 5577
                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
5578 5579 5580
                        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
5581 5582 5583 5584
                else:
                    # one Python type and one non-Python type, not assignable
                    self.invalid_types_error(operand1, op, operand2)
                    new_common_type = error_type
5585 5586 5587 5588
            elif type1.assignable_from(type2):
                new_common_type = type1
            elif type2.assignable_from(type1):
                new_common_type = type2
5589 5590 5591 5592
            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
5593

Stefan Behnel's avatar
Stefan Behnel committed
5594
        # recursively merge types
5595
        if common_type is None or new_common_type.is_error:
5596 5597
            common_type = new_common_type
        else:
5598 5599 5600
            # 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
5601
            common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5602 5603

        if self.cascade:
5604
            common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5605

5606 5607
        return common_type

5608 5609 5610 5611
    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
5612
    def is_python_comparison(self):
5613 5614 5615 5616
        return 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
5617

5618 5619 5620 5621 5622 5623
    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)
5624

5625
    def is_python_result(self):
5626
        return ((self.has_python_operands() and
5627 5628
                 self.operator not in ('is', 'is_not', 'in', 'not_in') and
                 not self.is_c_string_contains())
5629 5630
            or (self.cascade and self.cascade.is_python_result()))

5631 5632
    def is_c_string_contains(self):
        return self.operator in ('in', 'not_in') and \
5633 5634
               ((self.operand1.type.is_int
                 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
5635 5636 5637
                (self.operand1.type is PyrexTypes.c_py_unicode_type
                 and self.operand2.type is unicode_type))

William Stein's avatar
William Stein committed
5638 5639
    def generate_operation_code(self, code, result_code, 
            operand1, op , operand2):
5640
        if self.type.is_pyobject:
5641 5642 5643
            coerce_result = "__Pyx_PyBool_FromLong"
        else:
            coerce_result = ""
5644 5645 5646 5647
        if 'not' in op: 
            negation = "!"
        else: 
            negation = ""
William Stein's avatar
William Stein committed
5648
        if op == 'in' or op == 'not_in':
Stefan Behnel's avatar
typo  
Stefan Behnel committed
5649
            code.globalstate.use_utility_code(contains_utility_code)
5650
            if self.type.is_pyobject:
5651
                coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5652
            if op == 'not_in':
5653
                negation = "__Pyx_NegateNonNeg"
5654 5655 5656 5657 5658 5659 5660
            if operand2.type is dict_type:
                code.globalstate.use_utility_code(
                    raise_none_iter_error_utility_code)
                code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
                code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
                           code.error_goto(self.pos))
                code.putln("} else {")
5661
                method = "PyDict_Contains"
5662
            else:
5663
                method = "PySequence_Contains"
5664
            if self.type.is_pyobject:
5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681
                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)))
            if operand2.type is dict_type:
                code.putln("}")
5682
                    
William Stein's avatar
William Stein committed
5683 5684
        elif (operand1.type.is_pyobject
            and op not in ('is', 'is_not')):
5685 5686
                code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
                        result_code, 
William Stein's avatar
William Stein committed
5687 5688
                        operand1.py_result(), 
                        operand2.py_result(), 
5689 5690
                        richcmp_constants[op],
                        code.error_goto_if_null(result_code, self.pos)))
5691
                code.put_gotref(result_code)
5692 5693 5694 5695 5696
        elif operand1.type.is_complex:
            if op == "!=": 
                negation = "!"
            else: 
                negation = ""
5697 5698 5699 5700 5701 5702 5703
            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
5704
        else:
5705 5706 5707 5708 5709
            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
5710 5711
            elif type1.is_numeric:
                common_type = PyrexTypes.widest_numeric_type(type1, type2)
5712
            else:
5713 5714 5715
                common_type = type1
            code1 = operand1.result_as(common_type)
            code2 = operand2.result_as(common_type)
5716
            code.putln("%s = %s(%s %s %s);" % (
William Stein's avatar
William Stein committed
5717
                result_code, 
5718
                coerce_result, 
5719
                code1, 
William Stein's avatar
William Stein committed
5720
                self.c_operator(op), 
5721 5722
                code2))

William Stein's avatar
William Stein committed
5723 5724 5725 5726 5727 5728 5729 5730
    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
5731
contains_utility_code = UtilityCode(
5732
proto="""
5733 5734
static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5735 5736 5737 5738
    return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
}
""")

5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770
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;
}
""")

William Stein's avatar
William Stein committed
5771

5772
class PrimaryCmpNode(ExprNode, CmpNode):
William Stein's avatar
William Stein committed
5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785
    #  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
5786 5787
    child_attrs = ['operand1', 'operand2', 'cascade']
    
William Stein's avatar
William Stein committed
5788
    cascade = None
5789

Robert Bradshaw's avatar
Robert Bradshaw committed
5790 5791 5792 5793 5794 5795 5796
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

5797
    def calculate_constant_result(self):
5798
        self.calculate_cascaded_constant_result(self.operand1.constant_result)
William Stein's avatar
William Stein committed
5799
    
5800
    def compile_time_value(self, denv):
5801
        operand1 = self.operand1.compile_time_value(denv)
5802 5803
        return self.cascaded_compile_time_value(operand1, denv)

William Stein's avatar
William Stein committed
5804 5805 5806
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
5807 5808
        if self.is_cpp_comparison():
            self.analyse_cpp_comparison(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
5809 5810 5811
            if self.cascade:
                error(self.pos, "Cascading comparison not yet supported for cpp types.")
            return
William Stein's avatar
William Stein committed
5812
        if self.cascade:
5813 5814
            self.cascade.analyse_types(env)

5815
        if self.operator in ('in', 'not_in'):
5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829
            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
5830 5831
                self.operand2 = self.operand2.as_none_safe_node(
                    "argument of type 'NoneType' is not iterable")
5832 5833 5834
            else:
                common_type = py_object_type
                self.is_pycmp = True
5835 5836 5837 5838
        else:
            common_type = self.find_common_type(env, self.operator, self.operand1)
            self.is_pycmp = common_type.is_pyobject

5839
        if common_type is not None and not common_type.is_error:
5840 5841 5842
            if self.operand1.type != common_type:
                self.operand1 = self.operand1.coerce_to(common_type, env)
            self.coerce_operands_to(common_type, env)
5843

William Stein's avatar
William Stein committed
5844 5845 5846
        if self.cascade:
            self.operand2 = self.operand2.coerce_to_simple(env)
            self.cascade.coerce_cascaded_operands_to_temp(env)
5847 5848 5849 5850 5851 5852 5853 5854
        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
5855 5856 5857
        if self.is_pycmp or self.cascade:
            self.is_temp = 1
    
5858 5859 5860
    def analyse_cpp_comparison(self, env):
        type1 = self.operand1.type
        type2 = self.operand2.type
5861 5862
        entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
        if entry is None:
5863 5864
            error(self.pos, "Invalid types for '%s' (%s, %s)" %
                (self.operator, type1, type2))
5865 5866 5867
            self.type = PyrexTypes.error_type
            self.result_code = "<error>"
            return
5868 5869 5870 5871 5872
        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)
5873
        else:
5874 5875 5876
            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
5877
    
William Stein's avatar
William Stein committed
5878 5879 5880
    def has_python_operands(self):
        return (self.operand1.type.is_pyobject
            or self.operand2.type.is_pyobject)
5881
    
William Stein's avatar
William Stein committed
5882 5883 5884
    def check_const(self):
        if self.cascade:
            self.not_const()
5885 5886 5887
            return False
        else:
            return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
5888 5889

    def calculate_result_code(self):
5890 5891 5892 5893 5894 5895 5896 5897 5898 5899
        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())
5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913
        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())
5914 5915 5916 5917 5918
        else:
            return "(%s %s %s)" % (
                self.operand1.result(),
                self.c_operator(self.operator),
                self.operand2.result())
5919

William Stein's avatar
William Stein committed
5920 5921 5922 5923
    def generate_evaluation_code(self, code):
        self.operand1.generate_evaluation_code(code)
        self.operand2.generate_evaluation_code(code)
        if self.is_temp:
5924
            self.allocate_temp_result(code)
5925
            self.generate_operation_code(code, self.result(), 
William Stein's avatar
William Stein committed
5926 5927 5928
                self.operand1, self.operator, self.operand2)
            if self.cascade:
                self.cascade.generate_evaluation_code(code,
5929
                    self.result(), self.operand2)
William Stein's avatar
William Stein committed
5930
            self.operand1.generate_disposal_code(code)
5931
            self.operand1.free_temps(code)
William Stein's avatar
William Stein committed
5932
            self.operand2.generate_disposal_code(code)
5933
            self.operand2.free_temps(code)
5934

William Stein's avatar
William Stein committed
5935 5936 5937 5938 5939
    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)
5940
        
5941 5942 5943 5944 5945 5946
    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)
        
5947 5948 5949 5950 5951
    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
5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963


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
5964 5965
    child_attrs = ['operand2', 'cascade']

William Stein's avatar
William Stein committed
5966
    cascade = None
5967 5968
    constant_result = constant_value_not_set # FIXME: where to calculate this?

Robert Bradshaw's avatar
Robert Bradshaw committed
5969 5970 5971 5972 5973 5974 5975
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

5976 5977 5978 5979
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

5980
    def analyse_types(self, env):
William Stein's avatar
William Stein committed
5981 5982
        self.operand2.analyse_types(env)
        if self.cascade:
5983
            self.cascade.analyse_types(env)
5984

William Stein's avatar
William Stein committed
5985 5986
    def has_python_operands(self):
        return self.operand2.type.is_pyobject
5987
        
William Stein's avatar
William Stein committed
5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999
    def coerce_operands_to_pyobjects(self, env):
        self.operand2 = self.operand2.coerce_to_pyobject(env)
        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):
6000 6001
        if self.type.is_pyobject:
            code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
6002
            code.put_decref(result, self.type)
6003 6004
        else:
            code.putln("if (%s) {" % result)
William Stein's avatar
William Stein committed
6005 6006 6007 6008 6009 6010 6011 6012
        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)
6013
        self.operand2.free_temps(code)
William Stein's avatar
William Stein committed
6014 6015
        code.putln("}")

6016 6017 6018 6019 6020
    def annotate(self, code):
        self.operand2.annotate(code)
        if self.cascade:
            self.cascade.annotate(code)

William Stein's avatar
William Stein committed
6021 6022

binop_node_classes = {
6023 6024
    "or":       BoolBinopNode,
    "and":      BoolBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6025 6026 6027
    "|":        IntBinopNode,
    "^":        IntBinopNode,
    "&":        IntBinopNode,
6028 6029
    "<<":       IntBinopNode,
    ">>":       IntBinopNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6030 6031 6032
    "+":        AddNode,
    "-":        SubNode,
    "*":        MulNode,
6033 6034
    "/":        DivNode,
    "//":       DivNode,
Robert Bradshaw's avatar
Robert Bradshaw committed
6035
    "%":        ModNode,
6036
    "**":       PowNode
William Stein's avatar
William Stein committed
6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057
}

def binop_node(pos, operator, operand1, operand2):
    # Construct binop node of appropriate class for 
    # given operator.
    return binop_node_classes[operator](pos, 
        operator = operator, 
        operand1 = operand1, 
        operand2 = operand2)

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

6058
class CoercionNode(ExprNode):
William Stein's avatar
William Stein committed
6059 6060 6061 6062 6063
    #  Abstract base class for coercion nodes.
    #
    #  arg       ExprNode       node being coerced
    
    subexprs = ['arg']
6064
    constant_result = not_a_constant
William Stein's avatar
William Stein committed
6065 6066 6067 6068 6069
    
    def __init__(self, arg):
        self.pos = arg.pos
        self.arg = arg
        if debug_coercion:
Stefan Behnel's avatar
Stefan Behnel committed
6070
            print("%s Coercing %s" % (self, self.arg))
6071 6072

    def calculate_constant_result(self):
6073 6074
        # constant folding can break type coercion, so this is disabled
        pass
6075 6076 6077 6078 6079 6080
            
    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
6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101


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

6102
    def __init__(self, arg, dst_type, env, notnone=False):
William Stein's avatar
William Stein committed
6103 6104
        #  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
6105
        assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
William Stein's avatar
William Stein committed
6106 6107 6108
        CoercionNode.__init__(self, arg)
        self.type = dst_type
        self.result_ctype = arg.ctype()
6109
        self.notnone = notnone
6110

6111
    nogil_check = Node.gil_error
6112
    gil_message = "Python type test"
William Stein's avatar
William Stein committed
6113
    
6114 6115 6116
    def analyse_types(self, env):
        pass
    
William Stein's avatar
William Stein committed
6117 6118 6119 6120 6121
    def result_in_temp(self):
        return self.arg.result_in_temp()
    
    def is_ephemeral(self):
        return self.arg.is_ephemeral()
6122 6123 6124 6125 6126

    def calculate_constant_result(self):
        # FIXME
        pass

William Stein's avatar
William Stein committed
6127
    def calculate_result_code(self):
6128
        return self.arg.result()
William Stein's avatar
William Stein committed
6129 6130 6131
    
    def generate_result_code(self, code):
        if self.type.typeobj_is_available():
6132
            if not self.type.is_builtin_type:
6133
                code.globalstate.use_utility_code(type_test_utility_code)
William Stein's avatar
William Stein committed
6134
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
6135
                "if (!(%s)) %s" % (
6136
                    self.type.type_test_code(self.arg.py_result(), self.notnone),
William Stein's avatar
William Stein committed
6137 6138 6139 6140 6141 6142 6143
                    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)
6144 6145 6146

    def free_temps(self, code):
        self.arg.free_temps(code)
6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163


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

6164 6165 6166
    def may_be_none(self):
        return False

6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177
    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
6178 6179
            StringEncoding.escape_byte_string(
                self.exception_message.encode('UTF-8')),
6180 6181 6182 6183 6184 6185 6186 6187 6188
            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)

6189

William Stein's avatar
William Stein committed
6190 6191 6192
class CoerceToPyTypeNode(CoercionNode):
    #  This node is used to convert a C data type
    #  to a Python object.
6193 6194
    
    type = py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
6195
    is_temp = 1
William Stein's avatar
William Stein committed
6196

6197
    def __init__(self, arg, env, type=py_object_type):
William Stein's avatar
William Stein committed
6198
        CoercionNode.__init__(self, arg)
6199
        if not arg.type.create_to_py_utility_code(env):
William Stein's avatar
William Stein committed
6200
            error(arg.pos,
6201
                  "Cannot convert '%s' to Python object" % arg.type)
6202 6203 6204 6205
        if type is not py_object_type:
            self.type = py_object_type
        elif arg.type.is_string:
            self.type = Builtin.bytes_type
6206

6207
    gil_message = "Converting to Python object"
6208

6209 6210 6211 6212
    def may_be_none(self):
        # FIXME: is this always safe?
        return False

6213
    def coerce_to_boolean(self, env):
6214
        return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
6215 6216 6217 6218 6219 6220 6221
    
    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)
6222

6223 6224 6225 6226
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
6227 6228
    def generate_result_code(self, code):
        function = self.arg.type.to_py_function
Robert Bradshaw's avatar
Robert Bradshaw committed
6229
        code.putln('%s = %s(%s); %s' % (
6230
            self.result(), 
William Stein's avatar
William Stein committed
6231
            function, 
6232 6233
            self.arg.result(), 
            code.error_goto_if_null(self.result(), self.pos)))
6234
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
6235 6236


6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262
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('}')
6263 6264 6265 6266 6267 6268
        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' % (
6269 6270 6271
            self.result(),
            arg_result,
            code.error_goto_if_null(self.result(), self.pos)))
6272 6273
        if temp is not None:
            code.funcstate.release_temp(temp)
6274 6275 6276
        code.put_gotref(self.py_result())


William Stein's avatar
William Stein committed
6277 6278 6279 6280 6281 6282 6283 6284
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
6285
        if not result_type.create_from_py_utility_code(env):
William Stein's avatar
William Stein committed
6286
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
6287
                  "Cannot convert Python object to '%s'" % result_type)
William Stein's avatar
William Stein committed
6288 6289
        if self.type.is_string and self.arg.is_ephemeral():
            error(arg.pos,
Craig Citro's avatar
Craig Citro committed
6290
                  "Obtaining char * from temporary Python value")
William Stein's avatar
William Stein committed
6291
    
6292 6293 6294 6295
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
6296 6297
    def generate_result_code(self, code):
        function = self.type.from_py_function
6298 6299 6300 6301
        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
6302
        code.putln('%s = %s; %s' % (
6303
            self.result(), 
6304
            rhs,
6305
            code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
6306
        if self.type.is_pyobject:
6307
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
6308 6309 6310 6311 6312 6313


class CoerceToBooleanNode(CoercionNode):
    #  This node is used when a result needs to be used
    #  in a boolean context.
    
6314
    type = PyrexTypes.c_bint_type
6315 6316 6317 6318

    _special_builtins = {
        Builtin.list_type    : 'PyList_GET_SIZE',
        Builtin.tuple_type   : 'PyTuple_GET_SIZE',
6319
        Builtin.bytes_type   : 'PyBytes_GET_SIZE',
6320 6321 6322
        Builtin.unicode_type : 'PyUnicode_GET_SIZE',
        }

William Stein's avatar
William Stein committed
6323 6324 6325 6326
    def __init__(self, arg, env):
        CoercionNode.__init__(self, arg)
        if arg.type.is_pyobject:
            self.is_temp = 1
6327

6328
    def nogil_check(self, env):
6329
        if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
6330
            self.gil_error()
6331

6332
    gil_message = "Truth-testing Python object"
William Stein's avatar
William Stein committed
6333 6334 6335 6336
    
    def check_const(self):
        if self.is_temp:
            self.not_const()
6337 6338
            return False
        return self.arg.check_const()
William Stein's avatar
William Stein committed
6339 6340
    
    def calculate_result_code(self):
6341
        return "(%s != 0)" % self.arg.result()
William Stein's avatar
William Stein committed
6342 6343

    def generate_result_code(self, code):
6344 6345 6346 6347
        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
6348
            code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
6349 6350 6351 6352 6353
                       self.result(),
                       self.arg.py_result(),
                       test_func,
                       self.arg.py_result()))
        else:
William Stein's avatar
William Stein committed
6354
            code.putln(
6355
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
6356
                    self.result(), 
William Stein's avatar
William Stein committed
6357
                    self.arg.py_result(), 
6358
                    code.error_goto_if_neg(self.result(), self.pos)))
William Stein's avatar
William Stein committed
6359

6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370
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:
6371 6372
            real_part = "__Pyx_CREAL(%s)" % self.arg.result()
            imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
6373 6374 6375 6376 6377 6378 6379 6380 6381 6382
        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
6383 6384 6385 6386 6387 6388 6389 6390 6391

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
6392
        self.constant_result = self.arg.constant_result
William Stein's avatar
William Stein committed
6393 6394 6395
        self.is_temp = 1
        if self.type.is_pyobject:
            self.result_ctype = py_object_type
6396 6397 6398

    gil_message = "Creating temporary Python reference"

6399 6400 6401
    def analyse_types(self, env):
        # The arg is always already analysed
        pass
6402 6403 6404
        
    def coerce_to_boolean(self, env):
        self.arg = self.arg.coerce_to_boolean(env)
6405 6406
        if self.arg.is_simple():
            return self.arg
6407 6408 6409
        self.type = self.arg.type
        self.result_ctype = self.type
        return self
6410

William Stein's avatar
William Stein committed
6411 6412 6413 6414
    def generate_result_code(self, code):
        #self.arg.generate_evaluation_code(code) # Already done
        # by generic generate_subexpr_evaluation_code!
        code.putln("%s = %s;" % (
6415
            self.result(), self.arg.result_as(self.ctype())))
6416
        if self.type.is_pyobject and self.use_managed_ref:
6417
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428


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
6429
    nogil_check = None
William Stein's avatar
William Stein committed
6430 6431 6432
    
    def __init__(self, arg):
        CoercionNode.__init__(self, arg)
6433 6434 6435 6436 6437
        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
6438
            
6439
    def result(self):
6440
        return self.arg.result()
6441
    
Robert Bradshaw's avatar
Robert Bradshaw committed
6442 6443
    def type_dependencies(self, env):
        return self.arg.type_dependencies(env)
6444 6445 6446
    
    def infer_type(self, env):
        return self.arg.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
6447

Robert Bradshaw's avatar
Robert Bradshaw committed
6448 6449 6450 6451
    def analyse_types(self, env):
        self.type = self.arg.type
        self.result_ctype = self.arg.result_ctype
        self.is_temp = 1
6452 6453
        if hasattr(self.arg, 'entry'):
            self.entry = self.arg.entry
William Stein's avatar
William Stein committed
6454 6455 6456 6457 6458 6459
    
    def generate_evaluation_code(self, code):
        pass

    def generate_result_code(self, code):
        pass
6460
        
6461
    def generate_disposal_code(self, code):
6462 6463
        pass
                
6464 6465
    def free_temps(self, code):
        pass
6466

6467

6468 6469 6470 6471 6472 6473 6474 6475 6476 6477
class ModuleRefNode(ExprNode):
    # Simple returns the module object
    
    type = py_object_type
    is_temp = False
    subexprs = []
    
    def analyse_types(self, env):
        pass

6478 6479 6480
    def may_be_none(self):
        return False

6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508
    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):
        code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
                   (self.result(), self.body.result()))
        code.put_gotref(self.result())



William Stein's avatar
William Stein committed
6509 6510 6511 6512 6513 6514
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

6515 6516
get_name_interned_utility_code = UtilityCode(
proto = """
6517
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
6518 6519
""",
impl = """
William Stein's avatar
William Stein committed
6520 6521 6522 6523 6524 6525 6526
static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
    PyObject *result;
    result = PyObject_GetAttr(dict, name);
    if (!result)
        PyErr_SetObject(PyExc_NameError, name);
    return result;
}
6527
""")
William Stein's avatar
William Stein committed
6528 6529 6530

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

6531 6532
import_utility_code = UtilityCode(
proto = """
6533
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
6534 6535
""",
impl = """
William Stein's avatar
William Stein committed
6536
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
6537
    PyObject *py_import = 0;
William Stein's avatar
William Stein committed
6538 6539 6540 6541 6542
    PyObject *empty_list = 0;
    PyObject *module = 0;
    PyObject *global_dict = 0;
    PyObject *empty_dict = 0;
    PyObject *list;
6543 6544
    py_import = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
    if (!py_import)
William Stein's avatar
William Stein committed
6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559
        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;
6560
    module = PyObject_CallFunctionObjArgs(py_import,
6561
        name, global_dict, empty_dict, list, NULL);
William Stein's avatar
William Stein committed
6562 6563
bad:
    Py_XDECREF(empty_list);
6564
    Py_XDECREF(py_import);
William Stein's avatar
William Stein committed
6565 6566 6567 6568 6569 6570
    Py_XDECREF(empty_dict);
    return module;
}
""" % {
    "BUILTINS": Naming.builtins_cname,
    "GLOBALS":  Naming.module_cname,
6571
})
William Stein's avatar
William Stein committed
6572 6573 6574

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

6575 6576
get_exception_utility_code = UtilityCode(
proto = """
6577
static PyObject *__Pyx_GetExcValue(void); /*proto*/
6578 6579
""",
impl = """
William Stein's avatar
William Stein committed
6580 6581
static PyObject *__Pyx_GetExcValue(void) {
    PyObject *type = 0, *value = 0, *tb = 0;
6582
    PyObject *tmp_type, *tmp_value, *tmp_tb;
William Stein's avatar
William Stein committed
6583 6584 6585 6586 6587 6588 6589 6590 6591 6592
    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);
    }
6593 6594 6595
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
William Stein's avatar
William Stein committed
6596 6597 6598
    tstate->exc_type = type;
    tstate->exc_value = value;
    tstate->exc_traceback = tb;
6599 6600 6601 6602 6603
    /* 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
6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614
    result = value;
    Py_XINCREF(result);
    type = 0;
    value = 0;
    tb = 0;
bad:
    Py_XDECREF(type);
    Py_XDECREF(value);
    Py_XDECREF(tb);
    return result;
}
6615
""")
William Stein's avatar
William Stein committed
6616 6617 6618

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

6619 6620
type_test_utility_code = UtilityCode(
proto = """
6621
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6622 6623
""",
impl = """
6624
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6625
    if (unlikely(!type)) {
William Stein's avatar
William Stein committed
6626 6627 6628
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
6629
    if (likely(PyObject_TypeCheck(obj, type)))
William Stein's avatar
William Stein committed
6630
        return 1;
6631 6632
    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
                 Py_TYPE(obj)->tp_name, type->tp_name);
William Stein's avatar
William Stein committed
6633 6634
    return 0;
}
6635
""")
William Stein's avatar
William Stein committed
6636 6637 6638

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

6639 6640
create_class_utility_code = UtilityCode(
proto = """
6641
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6642 6643
""",
impl = """
William Stein's avatar
William Stein committed
6644
static PyObject *__Pyx_CreateClass(
6645
    PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
William Stein's avatar
William Stein committed
6646 6647 6648
{
    PyObject *py_modname;
    PyObject *result = 0;
6649

6650
    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
6651
    py_modname = PyString_FromString(modname);
6652 6653 6654
    #else
    py_modname = PyUnicode_FromString(modname);
    #endif
William Stein's avatar
William Stein committed
6655 6656 6657 6658
    if (!py_modname)
        goto bad;
    if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
        goto bad;
6659
    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
6660
    result = PyClass_New(bases, dict, name);
6661 6662 6663
    #else
    result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
    #endif
William Stein's avatar
William Stein committed
6664 6665 6666 6667
bad:
    Py_XDECREF(py_modname);
    return result;
}
6668
""")
William Stein's avatar
William Stein committed
6669 6670

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

6672 6673
cpp_exception_utility_code = UtilityCode(
proto = """
6674 6675
#ifndef __Pyx_CppExn2PyErr
static void __Pyx_CppExn2PyErr() {
Robert Bradshaw's avatar
Robert Bradshaw committed
6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691
  try {
    if (PyErr_Occurred())
      ; // let the latest Python exn pass through and ignore the current one
    else
      throw;
  } catch (const std::out_of_range& exn) {
    // catch out_of_range explicitly so the proper Python exn may be raised
    PyErr_SetString(PyExc_IndexError, exn.what());
  } catch (const std::exception& exn) {
    PyErr_SetString(PyExc_RuntimeError, exn.what());
  }
  catch (...)
  {
    PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
  }
}
6692
#endif
6693 6694 6695
""",
impl = ""
)
Robert Bradshaw's avatar
Robert Bradshaw committed
6696 6697

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

6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733
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 = """

6734
#if PY_MAJOR_VERSION >= 3
6735
static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
6736
    PyObject *value;
6737
    if (unlikely(d == Py_None)) {
6738 6739 6740
        __Pyx_RaiseNoneIndexingError();
        return NULL;
    }
6741 6742 6743
    value = PyDict_GetItemWithError(d, key);
    if (unlikely(!value)) {
        if (!PyErr_Occurred())
6744
            PyErr_SetObject(PyExc_KeyError, key);
6745
        return NULL;
6746
    }
6747 6748
    Py_INCREF(value);
    return value;
6749
}
6750 6751 6752
#else
    #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
#endif
6753 6754 6755 6756
""", 
requires = [raise_noneindex_error_utility_code])

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

6758 6759
getitem_int_utility_code = UtilityCode(
proto = """
6760

6761
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6762
    PyObject *r;
6763
    if (!j) return NULL;
6764 6765 6766 6767
    r = PyObject_GetItem(o, j);
    Py_DECREF(j);
    return r;
}
6768

6769 6770
""" + ''.join([
"""
6771 6772
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
6773 6774
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

6775
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
6776 6777 6778 6779 6780 6781
    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;
        }
6782 6783
        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);
6784 6785 6786
            Py_INCREF(r);
            return r;
        }
6787
    }
6788
    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
6789
}
6790 6791
""" % {'type' : type_name} for type_name in ('List', 'Tuple')
]) + """
6792

6793 6794
#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_Fast(o, i) : \\
6795 6796
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

6797
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6798
    PyObject *r;
Robert Bradshaw's avatar
Robert Bradshaw committed
6799
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6800 6801 6802
        r = PyList_GET_ITEM(o, i);
        Py_INCREF(r);
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
6803
    else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6804 6805 6806
        r = PyTuple_GET_ITEM(o, i);
        Py_INCREF(r);
    }
6807
    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
6808
        r = PySequence_GetItem(o, i);
6809
    }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6810
    else {
6811
        r = __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6812 6813 6814 6815
    }
    return r;
}
""",
6816 6817
impl = """
""")
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6818

6819 6820


Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6821 6822
#------------------------------------------------------------------------------------

6823 6824
setitem_int_utility_code = UtilityCode(
proto = """
6825 6826
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_SetItemInt_Fast(o, i, v) : \\
6827 6828
                                                    __Pyx_SetItemInt_Generic(o, to_py_func(i), v))

6829
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6830
    int r;
6831 6832 6833 6834 6835 6836
    if (!j) return -1;
    r = PyObject_SetItem(o, j, v);
    Py_DECREF(j);
    return r;
}

6837
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
Stefan Behnel's avatar
Stefan Behnel committed
6838
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6839
        Py_INCREF(v);
6840
        Py_DECREF(PyList_GET_ITEM(o, i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6841 6842 6843
        PyList_SET_ITEM(o, i, v);
        return 1;
    }
6844 6845
    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
6846
    else {
6847
        PyObject *j = PyInt_FromSsize_t(i);
6848
        return __Pyx_SetItemInt_Generic(o, j, v);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6849 6850 6851
    }
}
""",
6852 6853 6854
impl = """
""")

6855 6856
#------------------------------------------------------------------------------------

6857 6858
delitem_int_utility_code = UtilityCode(
proto = """
6859 6860
#define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_DelItemInt_Fast(o, i) : \\
6861 6862
                                                    __Pyx_DelItem_Generic(o, to_py_func(i)))

6863
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6864
    int r;
6865 6866 6867 6868 6869 6870
    if (!j) return -1;
    r = PyObject_DelItem(o, j);
    Py_DECREF(j);
    return r;
}

6871
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
6872 6873
    if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
        return PySequence_DelItem(o, i);
6874
    else {
6875
        PyObject *j = PyInt_FromSsize_t(i);
6876
        return __Pyx_DelItem_Generic(o, j);
6877 6878 6879 6880 6881 6882 6883 6884
    }
}
""",
impl = """
""")

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

6885 6886
raise_too_many_values_to_unpack = UtilityCode(
proto = """
6887
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void);
6888 6889
""",
impl = '''
6890
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) {
6891 6892 6893 6894 6895 6896
    PyErr_SetString(PyExc_ValueError, "too many values to unpack");
}
''')

raise_need_more_values_to_unpack = UtilityCode(
proto = """
6897
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6898 6899
""",
impl = '''
6900
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912
    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");
}
''')

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

6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932
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 {
      __Pyx_RaiseTooManyValuesError();
    }
}
""", 
requires = [raise_none_iter_error_utility_code,
            raise_need_more_values_to_unpack,
            raise_too_many_values_to_unpack]
)

6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964
unpacking_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
static int __Pyx_EndUnpack(PyObject *); /*proto*/
""",
impl = """
static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
    PyObject *item;
    if (!(item = PyIter_Next(iter))) {
        if (!PyErr_Occurred()) {
            __Pyx_RaiseNeedMoreValuesError(index);
        }
    }
    return item;
}

static int __Pyx_EndUnpack(PyObject *iter) {
    PyObject *item;
    if ((item = PyIter_Next(iter))) {
        Py_DECREF(item);
        __Pyx_RaiseTooManyValuesError();
        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
6965

6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977
#------------------------------------------------------------------------------------

# 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;
6978
    if (likely(PyDict_Check(kwargs))) {
6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992
        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
6993 6994 6995 6996 6997

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

int_pow_utility_code = UtilityCode(
proto="""
6998
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
6999 7000
""",
impl="""
7001
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
Robert Bradshaw's avatar
Robert Bradshaw committed
7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022
    %(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;
}
""")
7023 7024 7025

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

7026 7027
div_int_utility_code = UtilityCode(
proto="""
7028
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
7029 7030
""",
impl="""
7031
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
7032 7033 7034 7035 7036
    %(type)s q = a / b;
    %(type)s r = a - q*b;
    q -= ((r != 0) & ((r ^ b) < 0));
    return q;
}
7037 7038
""")

7039
mod_int_utility_code = UtilityCode(
7040
proto="""
7041
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7042 7043
""",
impl="""
7044
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7045 7046 7047
    %(type)s r = a %% b;
    r += ((r != 0) & ((r ^ b) < 0)) * b;
    return r;
7048 7049 7050
}
""")

7051
mod_float_utility_code = UtilityCode(
7052
proto="""
7053
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7054 7055
""",
impl="""
7056
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7057 7058 7059
    %(type)s r = fmod%(math_h_modifier)s(a, b);
    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
    return r;
7060 7061
}
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
7062

7063
cdivision_warning_utility_code = UtilityCode(
Robert Bradshaw's avatar
Robert Bradshaw committed
7064
proto="""
7065
static int __Pyx_cdivision_warning(void); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
7066 7067
""",
impl="""
7068 7069 7070 7071 7072
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,
7073
                              __Pyx_MODULE_NAME,
7074
                              NULL);
Robert Bradshaw's avatar
Robert Bradshaw committed
7075
}
7076 7077 7078 7079
""" % {
    'FILENAME': Naming.filename_cname,
    'LINENO':  Naming.lineno_cname,
})
7080 7081 7082 7083 7084 7085 7086

# from intobject.c
division_overflow_test_code = UtilityCode(
proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x)	\
	(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""")