ExprNodes.py 255 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 843 844 845
        strval = self.value
        assert isinstance(strval, (str, unicode))
        cmpval = repr(float(strval))
        if cmpval == 'nan':
846
            return "(Py_HUGE_VAL * 0)"
847
        elif cmpval == 'inf':
848
            return "Py_HUGE_VAL"
849
        elif cmpval == '-inf':
850
            return "(-Py_HUGE_VAL)"
Stefan Behnel's avatar
Stefan Behnel committed
851 852
        else:
            return strval
853

William Stein's avatar
William Stein committed
854

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

William Stein's avatar
William Stein committed
860
    type = PyrexTypes.c_char_ptr_type
861 862

    def compile_time_value(self, denv):
863
        return self.value
864

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

877 878 879
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

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

895 896 897 898 899 900 901 902
        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)

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

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

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

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

935

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

941
    type = unicode_type
942

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

959 960 961
    def can_coerce_to_char_literal(self):
        return len(self.value) == 1

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

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


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

979
    type = str_type
980
    is_identifier = None
981

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

        # this will be a unicode string in Py3, so make sure we can decode it
992 993
        if self.value.encoding:
            encoding = self.value.encoding
994 995 996 997
            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)
998

999
        return self
1000

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

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

1008
    def get_constant_c_result_code(self):
1009 1010
        return None

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


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


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

1029 1030
    type = py_object_type

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

1040 1041 1042
    def may_be_none(self):
        return False

1043 1044
    gil_message = "Constructing Python long int"

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


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

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

1070 1071 1072
    def may_be_none(self):
        return False

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

    gil_message = "Constructing complex number"

1087 1088 1089 1090 1091 1092
    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))

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

Danilo Freitas's avatar
Danilo Freitas committed
1103
class NewExprNode(AtomicExprNode):
1104 1105 1106

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

    def may_be_none(self):
        return False

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

William Stein's avatar
William Stein committed
1142

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

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

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

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

    gil_message = "Accessing Python global or builtin"

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

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

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

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

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

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

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

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

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

    gil_message = "Backquote expression"

1554 1555 1556
    def calculate_constant_result(self):
        self.constant_result = repr(self.arg.constant_result)

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


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

    gil_message = "Python import"

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


1604
class IteratorNode(ExprNode):
William Stein's avatar
William Stein committed
1605
    #  Used as part of for statement implementation.
1606 1607 1608 1609
    #
    #  allocate_counter_temp/release_counter_temp needs to be called
    #  by parent (ForInStatNode)
    #
William Stein's avatar
William Stein committed
1610 1611 1612 1613
    #  Implements result = iter(sequence)
    #
    #  sequence   ExprNode
    
1614 1615
    type = py_object_type
    
William Stein's avatar
William Stein committed
1616 1617 1618 1619
    subexprs = ['sequence']
    
    def analyse_types(self, env):
        self.sequence.analyse_types(env)
1620 1621 1622 1623 1624 1625 1626
        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
1627
        self.is_temp = 1
1628 1629 1630

    gil_message = "Iterating over Python object"

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


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

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

William Stein's avatar
William Stein committed
1735

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

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

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

1755 1756 1757
    def analyse_types(self, env):
        pass

William Stein's avatar
William Stein committed
1758

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

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

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

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

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

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

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

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

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

1859 1860 1861 1862 1863 1864 1865 1866
    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
1867 1868 1869 1870 1871
    def is_ephemeral(self):
        return self.base.is_ephemeral()
    
    def analyse_target_declaration(self, env):
        pass
1872 1873 1874 1875
        
    def analyse_as_type(self, env):
        base_type = self.base.analyse_as_type(env)
        if base_type and not base_type.is_pyobject:
1876
            if base_type.is_cpp_class:
1877
                if isinstance(self.index, TupleNode):
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888
                    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)))
1889
        return None
William Stein's avatar
William Stein committed
1890
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1891 1892
    def type_dependencies(self, env):
        return self.base.type_dependencies(env)
1893 1894
    
    def infer_type(self, env):
1895
        if isinstance(self.base, StringNode): # FIXME: BytesNode?
1896 1897 1898 1899
            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
1900 1901 1902 1903
        elif base_type is Builtin.unicode_type:
            # Py_UNICODE will automatically coerce to a unicode string
            # if required, so this is safe
            return PyrexTypes.c_py_unicode_type
1904 1905 1906 1907
        else:
            # TODO: Handle buffers (hopefully without too much redundancy).
            return py_object_type
    
William Stein's avatar
William Stein committed
1908
    def analyse_types(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
1909 1910 1911 1912
        self.analyse_base_and_index_types(env, getting = 1)
    
    def analyse_target_types(self, env):
        self.analyse_base_and_index_types(env, setting = 1)
1913

Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
1914
    def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1915 1916 1917
        # Note: This might be cleaned up by having IndexNode
        # parsed in a saner way and only construct the tuple if
        # needed.
1918 1919 1920 1921

        # 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.
1922 1923
        self.is_buffer_access = False

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

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

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

1957 1958
        if buffer_access:
            self.indices = indices
1959
            self.index = None
1960 1961
            self.type = self.base.type.dtype
            self.is_buffer_access = True
1962
            self.buffer_type = self.base.entry.type
1963 1964

            if getting and self.type.is_pyobject:
1965
                self.is_temp = True
1966 1967 1968 1969 1970
            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
1971
        else:
1972
            base_type = self.base.type
1973 1974 1975 1976
            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)
1977
            self.original_index_type = self.index.type
1978
            if base_type.is_pyobject:
1979
                if self.index.type.is_int:
1980
                    if (not setting
1981
                        and (base_type in (list_type, tuple_type, unicode_type))
1982 1983 1984 1985 1986
                        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
1987 1988 1989
                    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)
1990
                    self.is_temp = 1
1991 1992 1993 1994 1995 1996
                if base_type is unicode_type:
                    # Py_UNICODE will automatically coerce to a unicode string
                    # if required, so this is safe
                    self.type = PyrexTypes.c_py_unicode_type
                else:
                    self.type = py_object_type
William Stein's avatar
William Stein committed
1997
            else:
1998 1999
                if base_type.is_ptr or base_type.is_array:
                    self.type = base_type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2000 2001 2002 2003 2004 2005 2006
                    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)
2007
                elif base_type.is_cpp_class:
2008
                    function = env.lookup_operator("[]", [self.base, self.index])
Robert Bradshaw's avatar
Robert Bradshaw committed
2009
                    if function is None:
2010
                        error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
2011 2012 2013 2014 2015 2016 2017 2018 2019
                        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
2020
                        error(self.pos, "Can't set non-reference result '%s'" % self.type)
2021 2022 2023
                else:
                    error(self.pos,
                        "Attempting to index non-array type '%s'" %
2024
                            base_type)
2025
                    self.type = PyrexTypes.error_type
Stefan Behnel's avatar
Stefan Behnel committed
2026

2027 2028
    gil_message = "Indexing Python object"

2029 2030
    def nogil_check(self, env):
        if self.is_buffer_access:
2031 2032 2033 2034 2035 2036
            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
2037
        super(IndexNode, self).nogil_check(env)
2038 2039


William Stein's avatar
William Stein committed
2040
    def check_const_addr(self):
2041
        return self.base.check_const_addr() and self.index.check_const()
William Stein's avatar
William Stein committed
2042 2043 2044
    
    def is_lvalue(self):
        return 1
Dag Sverre Seljebotn's avatar
merge  
Dag Sverre Seljebotn committed
2045

William Stein's avatar
William Stein committed
2046
    def calculate_result_code(self):
2047
        if self.is_buffer_access:
2048
            return "(*%s)" % self.buffer_ptr_code
2049 2050 2051 2052
        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())
2053 2054
        elif self.base.type is unicode_type and self.type is PyrexTypes.c_py_unicode_type:
            return "PyUnicode_AS_UNICODE(%s)[%s]" % (self.base.result(), self.index.result())
2055 2056
        else:
            return "(%s[%s])" % (
2057
                self.base.result(), self.index.result())
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2058
            
2059
    def extra_index_params(self):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2060 2061
        if self.index.type.is_int:
            if self.original_index_type.signed:
2062
                size_adjustment = ""
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2063
            else:
2064 2065
                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
2066 2067
        else:
            return ""
2068 2069 2070

    def generate_subexpr_evaluation_code(self, code):
        self.base.generate_evaluation_code(code)
2071
        if not self.indices:
2072 2073
            self.index.generate_evaluation_code(code)
        else:
2074 2075
            for i in self.indices:
                i.generate_evaluation_code(code)
2076
        
2077 2078
    def generate_subexpr_disposal_code(self, code):
        self.base.generate_disposal_code(code)
2079
        if not self.indices:
2080 2081
            self.index.generate_disposal_code(code)
        else:
2082 2083
            for i in self.indices:
                i.generate_disposal_code(code)
2084

2085 2086 2087 2088 2089 2090 2091 2092
    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
2093
    def generate_result_code(self, code):
2094
        if self.is_buffer_access:
2095 2096
            if code.globalstate.directives['nonecheck']:
                self.put_nonecheck(code)
2097 2098 2099 2100
            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
2101
                code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112
        elif self.is_temp:
            if self.type.is_pyobject:
                if self.index.type.is_int:
                    index_code = self.index.result()
                    if self.base.type is list_type:
                        function = "__Pyx_GetItemInt_List"
                    elif self.base.type is tuple_type:
                        function = "__Pyx_GetItemInt_Tuple"
                    else:
                        function = "__Pyx_GetItemInt"
                    code.globalstate.use_utility_code(getitem_int_utility_code)
2113
                else:
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
                    index_code = self.index.py_result()
                    if self.base.type is dict_type:
                        function = "__Pyx_PyDict_GetItem"
                        code.globalstate.use_utility_code(getitem_dict_utility_code)
                    else:
                        function = "PyObject_GetItem"
                code.putln(
                    "%s = %s(%s, %s%s); if (!%s) %s" % (
                        self.result(),
                        function,
                        self.base.py_result(),
                        index_code,
                        self.extra_index_params(),
                        self.result(),
                        code.error_goto(self.pos)))
                code.put_gotref(self.py_result())
            elif self.type is PyrexTypes.c_py_unicode_type and self.base.type is unicode_type:
                code.globalstate.use_utility_code(getitem_int_pyunicode_utility_code)
                if self.index.type.is_int:
                    index_code = self.index.result()
                    function = "__Pyx_GetItemInt_Unicode"
2135
                else:
2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
                    index_code = self.index.py_result()
                    function = "__Pyx_GetItemInt_Unicode_Generic"
                code.putln(
                    "%s = %s(%s, %s%s); if (unlikely(%s == (Py_UNICODE)-1)) %s;" % (
                        self.result(),
                        function,
                        self.base.py_result(),
                        index_code,
                        self.extra_index_params(),
                        self.result(),
                        code.error_goto(self.pos)))
2147
            
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2148 2149 2150
    def generate_setitem_code(self, value_code, code):
        if self.index.type.is_int:
            function = "__Pyx_SetItemInt"
2151
            index_code = self.index.result()
2152
            code.globalstate.use_utility_code(setitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2153 2154
        else:
            index_code = self.index.py_result()
2155 2156
            if self.base.type is dict_type:
                function = "PyDict_SetItem"
Craig Citro's avatar
Craig Citro committed
2157
            # It would seem that we could specialized lists/tuples, but that
2158 2159 2160 2161 2162 2163
            # 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). 
2164 2165
            else:
                function = "PyObject_SetItem"
2166
        code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2167 2168
            "if (%s(%s, %s, %s%s) < 0) %s" % (
                function,
2169
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2170 2171
                index_code,
                value_code,
2172
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2173
                code.error_goto(self.pos)))
2174 2175 2176

    def generate_buffer_setitem_code(self, rhs, code, op=""):
        # Used from generate_assignment_code and InPlaceAssignmentNode
2177 2178
        if code.globalstate.directives['nonecheck']:
            self.put_nonecheck(code)
2179 2180 2181 2182
        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.
2183
            ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2184
            rhs_code = rhs.result()
2185
            code.putln("%s = %s;" % (ptr, ptrexpr))
2186
            code.put_gotref("*%s" % ptr)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2187
            code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2188 2189 2190
                ptr, rhs_code
                ))
            code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2191
            code.put_giveref("*%s" % ptr)
2192 2193 2194
            code.funcstate.release_temp(ptr)
        else: 
            # Simple case
2195
            code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2196

William Stein's avatar
William Stein committed
2197 2198
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2199
        if self.is_buffer_access:
2200
            self.generate_buffer_setitem_code(rhs, code)
2201
        elif self.type.is_pyobject:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2202
            self.generate_setitem_code(rhs.py_result(), code)
William Stein's avatar
William Stein committed
2203 2204 2205
        else:
            code.putln(
                "%s = %s;" % (
2206
                    self.result(), rhs.result()))
2207
        self.generate_subexpr_disposal_code(code)
2208
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2209
        rhs.generate_disposal_code(code)
2210
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2211 2212 2213
    
    def generate_deletion_code(self, code):
        self.generate_subexpr_evaluation_code(code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2214 2215
        #if self.type.is_pyobject:
        if self.index.type.is_int:
2216
            function = "__Pyx_DelItemInt"
2217
            index_code = self.index.result()
2218
            code.globalstate.use_utility_code(delitem_int_utility_code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2219 2220
        else:
            index_code = self.index.py_result()
2221 2222 2223 2224
            if self.base.type is dict_type:
                function = "PyDict_DelItem"
            else:
                function = "PyObject_DelItem"
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2225
        code.putln(
2226
            "if (%s(%s, %s%s) < 0) %s" % (
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2227
                function,
William Stein's avatar
William Stein committed
2228
                self.base.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2229
                index_code,
2230
                self.extra_index_params(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2231
                code.error_goto(self.pos)))
William Stein's avatar
William Stein committed
2232
        self.generate_subexpr_disposal_code(code)
2233
        self.free_subexpr_temps(code)
2234

2235
    def buffer_lookup_code(self, code):
2236
        # Assign indices to temps
2237
        index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2238
        for temp, index in zip(index_temps, self.indices):
2239
            code.putln("%s = %s;" % (temp, index.result()))
2240 2241
        # Generate buffer access code using these temps
        import Buffer
2242 2243
        # The above could happen because child_attrs is wrong somewhere so that
        # options are not propagated.
2244 2245 2246
        return Buffer.put_buffer_lookup_code(entry=self.base.entry,
                                             index_signeds=[i.type.signed for i in self.indices],
                                             index_cnames=index_temps,
2247
                                             directives=code.globalstate.directives,
2248
                                             pos=self.pos, code=code)
William Stein's avatar
William Stein committed
2249

2250 2251 2252 2253 2254 2255 2256
    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("}")

2257
class SliceIndexNode(ExprNode):
William Stein's avatar
William Stein committed
2258 2259 2260 2261 2262 2263 2264
    #  2-element slice indexing
    #
    #  base      ExprNode
    #  start     ExprNode or None
    #  stop      ExprNode or None
    
    subexprs = ['base', 'start', 'stop']
2265

2266 2267 2268 2269 2270 2271 2272 2273 2274
    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

2275 2276 2277 2278
    def calculate_constant_result(self):
        self.constant_result = self.base.constant_result[
            self.start.constant_result : self.stop.constant_result]

2279 2280
    def compile_time_value(self, denv):
        base = self.base.compile_time_value(denv)
2281 2282 2283 2284 2285 2286 2287 2288
        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)
2289 2290 2291 2292 2293
        try:
            return base[start:stop]
        except Exception, e:
            self.compile_time_value_error(e)
    
William Stein's avatar
William Stein committed
2294 2295
    def analyse_target_declaration(self, env):
        pass
2296 2297 2298 2299
    
    def analyse_target_types(self, env):
        self.analyse_types(env)
        # when assigning, we must accept any Python type
2300 2301
        if self.type.is_pyobject:
            self.type = py_object_type
William Stein's avatar
William Stein committed
2302 2303 2304 2305 2306 2307 2308

    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)
2309 2310 2311 2312
        base_type = self.base.type
        if base_type.is_string:
            self.type = bytes_type
        elif base_type.is_array or base_type.is_ptr:
2313 2314 2315
            # we need a ptr type here instead of an array type, as
            # array types can result in invalid type casts in the C
            # code
2316
            self.type = PyrexTypes.CPtrType(base_type.base_type)
2317 2318 2319
        else:
            self.base = self.base.coerce_to_pyobject(env)
            self.type = py_object_type
2320 2321 2322
        if base_type.is_builtin_type:
            # slicing builtin types returns something of the same type
            self.type = base_type
2323
        c_int = PyrexTypes.c_py_ssize_t_type
William Stein's avatar
William Stein committed
2324 2325 2326 2327 2328
        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
2329

2330
    nogil_check = Node.gil_error
2331 2332
    gil_message = "Slicing Python object"

William Stein's avatar
William Stein committed
2333
    def generate_result_code(self, code):
2334 2335 2336 2337
        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
2338 2339 2340
        if self.base.type.is_string:
            if self.stop is None:
                code.putln(
2341
                    "%s = PyBytes_FromString(%s + %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2342 2343 2344 2345 2346 2347
                        self.result(),
                        self.base.result(),
                        self.start_code(),
                        code.error_goto_if_null(self.result(), self.pos)))
            else:
                code.putln(
2348
                    "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
Robert Bradshaw's avatar
Robert Bradshaw committed
2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
                        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)))
2363
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2364 2365 2366
    
    def generate_assignment_code(self, rhs, code):
        self.generate_subexpr_evaluation_code(code)
2367 2368 2369 2370 2371 2372
        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
2373
                    rhs.py_result()))
2374 2375 2376 2377 2378 2379 2380 2381
        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
2382 2383
            if rhs.type.is_array:
                array_length = rhs.type.size
2384
                self.generate_slice_guard_code(code, array_length)
Stefan Behnel's avatar
Stefan Behnel committed
2385
            else:
Stefan Behnel's avatar
Stefan Behnel committed
2386 2387
                error(self.pos,
                      "Slice assignments from pointers are not yet supported.")
Stefan Behnel's avatar
Stefan Behnel committed
2388 2389
                # FIXME: fix the array size according to start/stop
                array_length = self.base.type.size
2390 2391 2392 2393
            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
2394
        self.generate_subexpr_disposal_code(code)
2395
        self.free_subexpr_temps(code)
William Stein's avatar
William Stein committed
2396
        rhs.generate_disposal_code(code)
2397
        rhs.free_temps(code)
William Stein's avatar
William Stein committed
2398 2399

    def generate_deletion_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2400
        if not self.base.type.is_pyobject:
2401 2402 2403
            error(self.pos,
                  "Deleting slices is only supported for Python types, not '%s'." % self.type)
            return
William Stein's avatar
William Stein committed
2404
        self.generate_subexpr_evaluation_code(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2405 2406
        code.put_error_if_neg(self.pos,
            "PySequence_DelSlice(%s, %s, %s)" % (
William Stein's avatar
William Stein committed
2407 2408
                self.base.py_result(),
                self.start_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
2409
                self.stop_code()))
William Stein's avatar
William Stein committed
2410
        self.generate_subexpr_disposal_code(code)
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420

    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
2421
                if stop < 0:
2422
                    slice_size = self.base.type.size + stop
Stefan Behnel's avatar
Stefan Behnel committed
2423 2424
                else:
                    slice_size = stop
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454
                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))
2455
            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));' % (
2456 2457 2458
                        target_size, check))
            code.putln(code.error_goto(self.pos))
            code.putln("}")
William Stein's avatar
William Stein committed
2459 2460 2461
    
    def start_code(self):
        if self.start:
2462
            return self.start.result()
William Stein's avatar
William Stein committed
2463 2464 2465 2466 2467
        else:
            return "0"
    
    def stop_code(self):
        if self.stop:
2468
            return self.stop.result()
2469 2470
        elif self.base.type.is_array:
            return self.base.type.size
William Stein's avatar
William Stein committed
2471
        else:
2472
            return "PY_SSIZE_T_MAX"
William Stein's avatar
William Stein committed
2473 2474
    
    def calculate_result_code(self):
2475
        # self.result() is not used, but this method must exist
William Stein's avatar
William Stein committed
2476 2477 2478
        return "<unused>"
    

2479
class SliceNode(ExprNode):
William Stein's avatar
William Stein committed
2480 2481 2482 2483 2484
    #  start:stop:step in subscript list
    #
    #  start     ExprNode
    #  stop      ExprNode
    #  step      ExprNode
2485 2486 2487
    
    type = py_object_type
    is_temp = 1
2488 2489 2490 2491 2492 2493 2494

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

2495 2496
    def compile_time_value(self, denv):
        start = self.start.compile_time_value(denv)
2497 2498 2499 2500 2501 2502 2503 2504
        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)
2505 2506 2507 2508 2509
        try:
            return slice(start, stop, step)
        except Exception, e:
            self.compile_time_value_error(e)

William Stein's avatar
William Stein committed
2510 2511 2512 2513 2514 2515 2516 2517 2518
    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)
2519 2520 2521

    gil_message = "Constructing Python slice object"

William Stein's avatar
William Stein committed
2522 2523
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2524
            "%s = PySlice_New(%s, %s, %s); %s" % (
2525
                self.result(),
William Stein's avatar
William Stein committed
2526 2527 2528
                self.start.py_result(), 
                self.stop.py_result(), 
                self.step.py_result(),
2529
                code.error_goto_if_null(self.result(), self.pos)))
2530
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2531

2532

2533
class CallNode(ExprNode):
2534

Robert Bradshaw's avatar
Robert Bradshaw committed
2535 2536 2537 2538 2539 2540
    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):
2541
                items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
Robert Bradshaw's avatar
Robert Bradshaw committed
2542 2543 2544 2545 2546 2547 2548
            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
2549 2550 2551 2552 2553 2554 2555 2556 2557
        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
2558 2559 2560
    
    def is_lvalue(self):
        return self.type.is_reference
2561

2562
    def nogil_check(self, env):
2563 2564
        func_type = self.function_type()
        if func_type.is_pyobject:
2565
            self.gil_error()
2566
        elif not getattr(func_type, 'nogil', False):
2567
            self.gil_error()
2568 2569 2570

    gil_message = "Calling gil-requiring function"

2571 2572

class SimpleCallNode(CallNode):
William Stein's avatar
William Stein committed
2573 2574 2575 2576 2577 2578 2579
    #  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
2580
    #  wrapper_call   bool                 used internally
2581
    #  has_optional_args   bool            used internally
William Stein's avatar
William Stein committed
2582 2583 2584 2585 2586 2587
    
    subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
    
    self = None
    coerced_self = None
    arg_tuple = None
2588
    wrapper_call = False
2589
    has_optional_args = False
William Stein's avatar
William Stein committed
2590
    
2591 2592 2593 2594 2595 2596 2597
    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)
2598
            
Robert Bradshaw's avatar
Robert Bradshaw committed
2599
    def type_dependencies(self, env):
2600 2601
        # TODO: Update when Danilo's C++ code merged in to handle the
        # the case of function overloading.
Robert Bradshaw's avatar
Robert Bradshaw committed
2602
        return self.function.type_dependencies(env)
2603 2604
    
    def infer_type(self, env):
2605 2606
        function = self.function
        func_type = function.infer_type(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
2607 2608
        if isinstance(self.function, NewExprNode):
            return PyrexTypes.CPtrType(self.function.class_type)
2609 2610 2611 2612
        if func_type.is_ptr:
            func_type = func_type.base_type
        if func_type.is_cfunction:
            return func_type.return_type
2613 2614 2615 2616 2617 2618
        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:
2619 2620 2621
                    if function.entry.name == 'float':
                        return PyrexTypes.c_double_type
                    elif function.entry.name in Builtin.types_that_construct_their_instance:
2622 2623 2624
                        return result_type
        return py_object_type

2625
    def analyse_as_type(self, env):
2626
        attr = self.function.as_cython_attribute()
2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638
        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
2639

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


class PythonCapiFunctionNode(ExprNode):
    subexprs = []
2868
    def __init__(self, pos, py_name, cname, func_type, utility_code = None):
2869
        self.pos = pos
2870 2871
        self.name = py_name
        self.cname = cname
2872 2873 2874
        self.type = func_type
        self.utility_code = utility_code

2875 2876 2877
    def analyse_types(self, env):
        pass

2878 2879 2880 2881 2882
    def generate_result_code(self, code):
        if self.utility_code:
            code.globalstate.use_utility_code(self.utility_code)

    def calculate_result_code(self):
2883
        return self.cname
2884 2885 2886 2887 2888

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

    def __init__(self, pos, function_name, func_type,
2889
                 utility_code = None, py_name=None, **kwargs):
2890 2891 2892
        self.type = func_type.return_type
        self.result_ctype = self.type
        self.function = PythonCapiFunctionNode(
2893
            pos, py_name, function_name, func_type,
2894 2895 2896 2897 2898
            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
2899

2900
class GeneralCallNode(CallNode):
William Stein's avatar
William Stein committed
2901 2902 2903 2904 2905 2906 2907 2908
    #  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
    
2909 2910
    type = py_object_type
    
William Stein's avatar
William Stein committed
2911 2912
    subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']

2913
    nogil_check = Node.gil_error
2914

2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
    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)
2925 2926 2927 2928 2929 2930
            
    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
2931

William Stein's avatar
William Stein committed
2932
    def analyse_types(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2933 2934
        if self.analyse_as_type_constructor(env):
            return
William Stein's avatar
William Stein committed
2935 2936 2937 2938 2939 2940
        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)
2941
        if not self.function.type.is_pyobject:
2942 2943
            if self.function.type.is_error:
                self.type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
2944
                return
2945
            if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2946
                error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2947 2948
            else:
                self.function = self.function.coerce_to_pyobject(env)
William Stein's avatar
William Stein committed
2949 2950 2951 2952 2953
        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
2954
        function = self.function
2955 2956 2957 2958 2959 2960 2961
        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
2962 2963 2964
        self.is_temp = 1
        
    def generate_result_code(self, code):
2965
        if self.type.is_error: return
2966
        kwargs_call_function = "PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
2967
        if self.keyword_args and self.starstar_arg:
Robert Bradshaw's avatar
Robert Bradshaw committed
2968 2969
            code.put_error_if_neg(self.pos, 
                "PyDict_Update(%s, %s)" % (
William Stein's avatar
William Stein committed
2970
                    self.keyword_args.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
2971
                    self.starstar_arg.py_result()))
William Stein's avatar
William Stein committed
2972 2973 2974 2975 2976
            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()
2977 2978
            if self.starstar_arg.type is not Builtin.dict_type:
                # CPython supports calling functions with non-dicts, so do we
2979 2980
                code.globalstate.use_utility_code(kwargs_call_utility_code)
                kwargs_call_function = "__Pyx_PyEval_CallObjectWithKeywords"
William Stein's avatar
William Stein committed
2981 2982 2983
        else:
            keyword_code = None
        if not keyword_code:
2984
            call_code = "PyObject_Call(%s, %s, NULL)" % (
William Stein's avatar
William Stein committed
2985 2986 2987
                self.function.py_result(),
                self.positional_args.py_result())
        else:
2988 2989
            call_code = "%s(%s, %s, %s)" % (
                kwargs_call_function,
William Stein's avatar
William Stein committed
2990 2991 2992 2993
                self.function.py_result(),
                self.positional_args.py_result(),
                keyword_code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2994
            "%s = %s; %s" % (
2995
                self.result(),
William Stein's avatar
William Stein committed
2996
                call_code,
2997
                code.error_goto_if_null(self.result(), self.pos)))
2998
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
2999 3000


3001
class AsTupleNode(ExprNode):
William Stein's avatar
William Stein committed
3002 3003 3004 3005 3006 3007
    #  Convert argument to tuple. Used for normalising
    #  the * argument of a function call.
    #
    #  arg    ExprNode
    
    subexprs = ['arg']
3008 3009 3010

    def calculate_constant_result(self):
        self.constant_result = tuple(self.base.constant_result)
William Stein's avatar
William Stein committed
3011
    
3012 3013 3014 3015 3016 3017 3018
    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
3019 3020 3021
    def analyse_types(self, env):
        self.arg.analyse_types(env)
        self.arg = self.arg.coerce_to_pyobject(env)
3022
        self.type = tuple_type
William Stein's avatar
William Stein committed
3023
        self.is_temp = 1
3024

3025 3026 3027
    def may_be_none(self):
        return False

3028
    nogil_check = Node.gil_error
3029 3030
    gil_message = "Constructing Python tuple"

William Stein's avatar
William Stein committed
3031 3032
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3033
            "%s = PySequence_Tuple(%s); %s" % (
3034
                self.result(),
William Stein's avatar
William Stein committed
3035
                self.arg.py_result(),
3036
                code.error_goto_if_null(self.result(), self.pos)))
3037
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3038 3039
    

3040
class AttributeNode(ExprNode):
William Stein's avatar
William Stein committed
3041 3042 3043 3044
    #  obj.attribute
    #
    #  obj          ExprNode
    #  attribute    string
3045
    #  needs_none_check boolean        Used if obj is an extension type.
3046
    #                                  If set to True, it is known that the type is not None.
William Stein's avatar
William Stein committed
3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
    #
    #  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
3061
    needs_none_check = True
William Stein's avatar
William Stein committed
3062

3063
    def as_cython_attribute(self):
3064 3065
        if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
            return self.attribute
3066 3067 3068
        cy = self.obj.as_cython_attribute()
        if cy:
            return "%s.%s" % (cy, self.attribute)
3069

3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080
    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
3081
        return ExprNode.coerce_to(self, dst_type, env)
3082 3083 3084

    def calculate_constant_result(self):
        attr = self.attribute
3085
        if attr.startswith("__") and attr.endswith("__"):
3086 3087 3088
            return
        self.constant_result = getattr(self.obj.constant_result, attr)

3089 3090
    def compile_time_value(self, denv):
        attr = self.attribute
3091
        if attr.startswith("__") and attr.endswith("__"):
Stefan Behnel's avatar
Stefan Behnel committed
3092 3093
            error(self.pos,
                  "Invalid attribute name '%s' in compile-time expression" % attr)
3094
            return None
3095
        obj = self.obj.compile_time_value(denv)
3096 3097 3098 3099
        try:
            return getattr(obj, attr)
        except Exception, e:
            self.compile_time_value_error(e)
3100
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3101 3102 3103
    def type_dependencies(self, env):
        return self.obj.type_dependencies(env)
    
3104 3105 3106 3107 3108 3109
    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
3110
            self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
3111
            return self.type
3112

William Stein's avatar
William Stein committed
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156
    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
3157
                ubcm_entry.is_unbound_cmethod = 1
William Stein's avatar
William Stein committed
3158 3159 3160
                self.mutate_into_name_node(env, ubcm_entry, None)
                return 1
        return 0
3161 3162 3163 3164
        
    def analyse_as_type(self, env):
        module_scope = self.obj.analyse_as_module(env)
        if module_scope:
3165
            return module_scope.lookup_type(self.attribute)
Robert Bradshaw's avatar
Robert Bradshaw committed
3166 3167 3168 3169
        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)
3170
        return None
William Stein's avatar
William Stein committed
3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202
    
    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:
3203
            NameNode.analyse_rvalue_entry(self, env)
William Stein's avatar
William Stein committed
3204 3205 3206 3207 3208
    
    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:
3209 3210
#            error(self.pos, "C method can only be called")
            pass
3211 3212
        ## Reference to C array turns into pointer to first element.
        #while self.type.is_array:
Robert Bradshaw's avatar
Robert Bradshaw committed
3213
        #    self.type = self.type.element_ptr_type()
William Stein's avatar
William Stein committed
3214 3215 3216 3217 3218
        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
3219
    def analyse_attribute(self, env, obj_type = None):
William Stein's avatar
William Stein committed
3220 3221 3222
        # 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
3223 3224 3225 3226 3227 3228 3229
        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
3230
        if obj_type.is_ptr or obj_type.is_array:
William Stein's avatar
William Stein committed
3231 3232 3233 3234 3235 3236 3237 3238 3239 3240
            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
3241 3242
                if entry and entry.is_member:
                    entry = None
William Stein's avatar
William Stein committed
3243 3244 3245 3246
            else:
                error(self.pos, 
                    "Cannot select attribute of incomplete type '%s'" 
                    % obj_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3247 3248
                self.type = PyrexTypes.error_type
                return
William Stein's avatar
William Stein committed
3249 3250
            self.entry = entry
            if entry:
3251 3252
                if obj_type.is_extension_type and entry.name == "__weakref__":
                    error(self.pos, "Illegal use of special attribute __weakref__")
3253 3254
                # methods need the normal attribute lookup
                # because they do not have struct entries
3255 3256 3257 3258
                if entry.is_variable or entry.is_cmethod:
                    self.type = entry.type
                    self.member = entry.cname
                    return
William Stein's avatar
William Stein committed
3259 3260 3261 3262 3263 3264 3265 3266 3267
                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
3268
        self.analyse_as_python_attribute(env, obj_type)
Stefan Behnel's avatar
Stefan Behnel committed
3269

Robert Bradshaw's avatar
Robert Bradshaw committed
3270 3271 3272
    def analyse_as_python_attribute(self, env, obj_type = None):
        if obj_type is None:
            obj_type = self.obj.type
3273
        self.member = self.attribute
3274 3275
        self.type = py_object_type
        self.is_py_attr = 1
3276
        if not obj_type.is_pyobject and not obj_type.is_error:
3277
            if obj_type.can_coerce_to_pyobject(env):
3278 3279 3280 3281 3282
                self.obj = self.obj.coerce_to_pyobject(env)
            else:
                error(self.pos,
                      "Object of type '%s' has no attribute '%s'" %
                      (obj_type, self.attribute))
3283

3284
    def nogil_check(self, env):
3285
        if self.is_py_attr:
3286
            self.gil_error()
3287

3288 3289
    gil_message = "Accessing Python attribute"

William Stein's avatar
William Stein committed
3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309
    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 ###
3310
        #print "...obj node =", self.obj, "code", self.obj.result() ###
William Stein's avatar
William Stein committed
3311 3312 3313 3314 3315
        #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
3316 3317 3318 3319 3320 3321
            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
3322
        elif obj.type.is_complex:
3323
            return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
William Stein's avatar
William Stein committed
3324 3325 3326 3327
        else:
            return "%s%s%s" % (obj_code, self.op, self.member)
    
    def generate_result_code(self, code):
3328
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3329
        if self.is_py_attr:
3330 3331
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
3332
                    self.result(),
3333
                    self.obj.py_result(),
3334
                    interned_attr_cname,
3335
                    code.error_goto_if_null(self.result(), self.pos)))
3336
            code.put_gotref(self.py_result())
3337 3338 3339
        else:
            # result_code contains what is needed, but we may need to insert
            # a check and raise an exception
3340 3341 3342 3343
            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
3344 3345
    
    def generate_assignment_code(self, rhs, code):
3346
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3347 3348
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
3349 3350 3351
            code.put_error_if_neg(self.pos, 
                'PyObject_SetAttr(%s, %s, %s)' % (
                    self.obj.py_result(),
3352
                    interned_attr_cname,
3353
                    rhs.py_result()))
William Stein's avatar
William Stein committed
3354
            rhs.generate_disposal_code(code)
3355
            rhs.free_temps(code)
3356 3357 3358 3359 3360
        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
3361
        else:
3362 3363 3364 3365 3366
            if (self.obj.type.is_extension_type
                  and self.needs_none_check
                  and code.globalstate.directives['nonecheck']):
                self.put_nonecheck(code)

3367
            select_code = self.result()
3368
            if self.type.is_pyobject and self.use_managed_ref:
William Stein's avatar
William Stein committed
3369
                rhs.make_owned_reference(code)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3370
                code.put_giveref(rhs.py_result())
3371
                code.put_gotref(select_code)
William Stein's avatar
William Stein committed
3372 3373 3374 3375
                code.put_decref(select_code, self.ctype())
            code.putln(
                "%s = %s;" % (
                    select_code,
3376
                    rhs.result_as(self.ctype())))
3377
                    #rhs.result()))
William Stein's avatar
William Stein committed
3378
            rhs.generate_post_assignment_code(code)
3379
            rhs.free_temps(code)
William Stein's avatar
William Stein committed
3380
        self.obj.generate_disposal_code(code)
3381
        self.obj.free_temps(code)
William Stein's avatar
William Stein committed
3382 3383
    
    def generate_deletion_code(self, code):
3384
        interned_attr_cname = code.intern_identifier(self.attribute)
William Stein's avatar
William Stein committed
3385 3386
        self.obj.generate_evaluation_code(code)
        if self.is_py_attr:
3387 3388 3389
            code.put_error_if_neg(self.pos,
                'PyObject_DelAttr(%s, %s)' % (
                    self.obj.py_result(),
3390
                    interned_attr_cname))
William Stein's avatar
William Stein committed
3391 3392 3393
        else:
            error(self.pos, "Cannot delete C attribute of extension type")
        self.obj.generate_disposal_code(code)
3394
        self.obj.free_temps(code)
3395 3396 3397 3398 3399 3400
        
    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
3401

3402 3403 3404
    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
3405
        code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3406 3407 3408 3409
        code.putln(code.error_goto(self.pos))
        code.putln("}")


William Stein's avatar
William Stein committed
3410 3411 3412 3413 3414 3415
#-------------------------------------------------------------------
#
#  Constructor nodes
#
#-------------------------------------------------------------------

3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430
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
3431
    is_temp = 1
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459

    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


3460
class SequenceNode(ExprNode):
William Stein's avatar
William Stein committed
3461 3462 3463 3464
    #  Base class for list and tuple constructor nodes.
    #  Contains common code for performing sequence unpacking.
    #
    #  args                    [ExprNode]
3465
    #  iterator                ExprNode
William Stein's avatar
William Stein committed
3466 3467 3468 3469 3470 3471 3472
    #  unpacked_items          [ExprNode] or None
    #  coerced_unpacked_items  [ExprNode] or None
    
    subexprs = ['args']
    
    is_sequence_constructor = 1
    unpacked_items = None
3473

3474 3475 3476
    def compile_time_value_list(self, denv):
        return [arg.compile_time_value(denv) for arg in self.args]

3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
    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
3491
    def analyse_target_declaration(self, env):
3492
        self.replace_starred_target_node()
William Stein's avatar
William Stein committed
3493 3494 3495
        for arg in self.args:
            arg.analyse_target_declaration(env)

3496
    def analyse_types(self, env, skip_children=False):
William Stein's avatar
William Stein committed
3497 3498
        for i in range(len(self.args)):
            arg = self.args[i]
3499
            if not skip_children: arg.analyse_types(env)
William Stein's avatar
William Stein committed
3500 3501 3502
            self.args[i] = arg.coerce_to_pyobject(env)
        self.type = py_object_type
        self.is_temp = 1
3503

3504 3505 3506
    def may_be_none(self):
        return False

William Stein's avatar
William Stein committed
3507
    def analyse_target_types(self, env):
3508 3509
        self.iterator = PyTempNode(self.pos, env)
        self.unpacked_items = []
William Stein's avatar
William Stein committed
3510 3511 3512
        self.coerced_unpacked_items = []
        for arg in self.args:
            arg.analyse_target_types(env)
3513 3514 3515 3516 3517 3518
            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
3519 3520 3521 3522 3523
            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
3524

William Stein's avatar
William Stein committed
3525 3526 3527 3528
    def generate_result_code(self, code):
        self.generate_operation_code(code)
    
    def generate_assignment_code(self, rhs, code):
3529 3530 3531
        if self.starred_assignment:
            self.generate_starred_assignment_code(rhs, code)
        else:
3532
            self.generate_parallel_assignment_code(rhs, code)
3533 3534 3535 3536 3537

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

3538
    def generate_parallel_assignment_code(self, rhs, code):
3539 3540 3541 3542
        # 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.

3543 3544 3545 3546
        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
3547
        code.putln(
3548 3549
            "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
                tuple_check % rhs.py_result(), 
Robert Bradshaw's avatar
Robert Bradshaw committed
3550 3551
                rhs.py_result(), 
                len(self.args)))
Stefan Behnel's avatar
Stefan Behnel committed
3552
        code.putln("PyObject* tuple = %s;" % rhs.py_result())
3553 3554
        for item in self.unpacked_items:
            item.allocate(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3555 3556
        for i in range(len(self.args)):
            item = self.unpacked_items[i]
3557 3558
            code.put(
                "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3559
                    item.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3560
                    i))
3561
            code.put_incref(item.result(), item.ctype())
3562 3563
            value_node = self.coerced_unpacked_items[i]
            value_node.generate_evaluation_code(code)
3564
        rhs.generate_disposal_code(code)
3565

3566 3567 3568 3569
        for i in range(len(self.args)):
            self.args[i].generate_assignment_code(
                self.coerced_unpacked_items[i], code)
                 
3570
        code.putln("} else {")
Robert Bradshaw's avatar
Robert Bradshaw committed
3571

3572
        if rhs.type is tuple_type:
3573 3574 3575 3576
            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))
3577
        else:
3578 3579
            code.globalstate.use_utility_code(unpacking_utility_code)

3580
            self.iterator.allocate(code)
3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607
            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)
3608
            self.iterator.release(code)
3609 3610 3611 3612

            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
3613

3614
        code.putln("}")
3615 3616

    def generate_starred_assignment_code(self, rhs, code):
3617 3618
        code.globalstate.use_utility_code(unpacking_utility_code)

3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634
        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)

3635
        for item in self.unpacked_items:
3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670
            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
3671
                code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682
                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)

3683 3684 3685 3686 3687 3688 3689 3690
    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
3691 3692 3693 3694


class TupleNode(SequenceNode):
    #  Tuple constructor.
3695 3696
    
    type = tuple_type
3697 3698 3699

    gil_message = "Constructing Python tuple"

3700
    def analyse_types(self, env, skip_children=False):
Robert Bradshaw's avatar
Robert Bradshaw committed
3701 3702
        if len(self.args) == 0:
            self.is_temp = 0
3703
            self.is_literal = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3704
        else:
3705
            SequenceNode.analyse_types(self, env, skip_children)
Robert Bradshaw's avatar
Robert Bradshaw committed
3706 3707 3708
            
    def calculate_result_code(self):
        if len(self.args) > 0:
3709
            error(self.pos, "Positive length tuples must be constructed.")
Robert Bradshaw's avatar
Robert Bradshaw committed
3710 3711
        else:
            return Naming.empty_tuple
William Stein's avatar
William Stein committed
3712

3713 3714 3715 3716
    def calculate_constant_result(self):
        self.constant_result = tuple([
                arg.constant_result for arg in self.args])

3717 3718 3719 3720 3721 3722 3723
    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
3724
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3725 3726 3727
        if len(self.args) == 0:
            # result_code is Naming.empty_tuple
            return
William Stein's avatar
William Stein committed
3728
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3729
            "%s = PyTuple_New(%s); %s" % (
3730
                self.result(),
William Stein's avatar
William Stein committed
3731
                len(self.args),
3732
                code.error_goto_if_null(self.result(), self.pos)))
3733
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
3734 3735 3736
        for i in range(len(self.args)):
            arg = self.args[i]
            if not arg.result_in_temp():
3737
                code.put_incref(arg.result(), arg.ctype())
William Stein's avatar
William Stein committed
3738 3739
            code.putln(
                "PyTuple_SET_ITEM(%s, %s, %s);" % (
3740
                    self.result(),
William Stein's avatar
William Stein committed
3741 3742
                    i,
                    arg.py_result()))
3743
            code.put_giveref(arg.py_result())
William Stein's avatar
William Stein committed
3744 3745 3746 3747 3748 3749
    
    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:
3750 3751 3752
            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
3753 3754 3755 3756


class ListNode(SequenceNode):
    #  List constructor.
3757 3758 3759
    
    # obj_conversion_errors    [PyrexError]   used internally
    # orignial_args            [ExprNode]     used internally
3760

3761 3762
    obj_conversion_errors = []

3763
    gil_message = "Constructing Python list"
3764
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3765
    def type_dependencies(self, env):
3766 3767 3768 3769 3770
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer non-object list arrays.
        return list_type
3771

3772
    def analyse_expressions(self, env):
3773
        SequenceNode.analyse_expressions(self, env)
3774 3775
        self.coerce_to_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
3776
    def analyse_types(self, env):
3777 3778 3779 3780 3781 3782
        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
3783 3784 3785
        
    def coerce_to(self, dst_type, env):
        if dst_type.is_pyobject:
3786 3787 3788
            for err in self.obj_conversion_errors:
                report_error(err)
            self.obj_conversion_errors = []
Robert Bradshaw's avatar
Robert Bradshaw committed
3789 3790 3791 3792
            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
3793
            self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3794
            for i in range(len(self.original_args)):
Robert Bradshaw's avatar
Robert Bradshaw committed
3795
                arg = self.args[i]
3796 3797
                if isinstance(arg, CoerceToPyTypeNode):
                    arg = arg.arg
Robert Bradshaw's avatar
Robert Bradshaw committed
3798
                self.args[i] = arg.coerce_to(base_type, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3799 3800 3801 3802 3803 3804
        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)
3805 3806 3807
                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
3808 3809
                    self.args[i] = arg.coerce_to(member.type, env)
            self.type = dst_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3810 3811 3812 3813
        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
3814 3815 3816 3817 3818 3819 3820 3821
        
    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
3822

3823 3824 3825 3826
    def calculate_constant_result(self):
        self.constant_result = [
            arg.constant_result for arg in self.args]

3827 3828 3829
    def compile_time_value(self, denv):
        return self.compile_time_value_list(denv)

William Stein's avatar
William Stein committed
3830
    def generate_operation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
3831
        if self.type.is_pyobject:
3832 3833
            for err in self.obj_conversion_errors:
                report_error(err)
Robert Bradshaw's avatar
Robert Bradshaw committed
3834
            code.putln("%s = PyList_New(%s); %s" %
3835
                (self.result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
3836 3837
                len(self.args),
                code.error_goto_if_null(self.result(), self.pos)))
3838
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
3839 3840 3841 3842 3843 3844 3845 3846 3847
            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()))
3848
                code.put_giveref(arg.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
3849 3850 3851 3852 3853 3854
        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
3855
        elif self.type.is_struct:
Robert Bradshaw's avatar
Robert Bradshaw committed
3856 3857 3858 3859 3860
            for arg, member in zip(self.args, self.type.scope.var_entries):
                code.putln("%s.%s = %s;" % (
                        self.result(),
                        member.cname,
                        arg.result()))
3861 3862
        else:
            raise InternalError("List type never specified")
3863

William Stein's avatar
William Stein committed
3864 3865 3866 3867 3868
    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:
3869 3870 3871
            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
3872

Robert Bradshaw's avatar
Robert Bradshaw committed
3873

3874
class ComprehensionNode(ExprNode):
3875
    subexprs = ["target"]
3876 3877
    child_attrs = ["loop", "append"]

3878 3879
    def infer_type(self, env):
        return self.target.infer_type(env)
3880 3881 3882 3883 3884

    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)

3885 3886 3887
    def analyse_types(self, env):
        self.target.analyse_expressions(env)
        self.type = self.target.type
3888
        self.loop.analyse_expressions(env)
3889

3890 3891 3892
    def may_be_none(self):
        return False

3893 3894 3895 3896 3897
    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
3898

3899 3900 3901
    def generate_operation_code(self, code):
        self.loop.generate_execution_code(code)

3902 3903
    def annotate(self, code):
        self.loop.annotate(code)
3904 3905


3906
class ComprehensionAppendNode(ExprNode):
3907 3908
    # Need to be careful to avoid infinite recursion:
    # target must not be in child_attrs/subexprs
Robert Bradshaw's avatar
Robert Bradshaw committed
3909
    subexprs = ['expr']
3910 3911

    type = PyrexTypes.c_int_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3912 3913 3914
    
    def analyse_types(self, env):
        self.expr.analyse_types(env)
3915
        if not self.expr.type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
3916 3917
            self.expr = self.expr.coerce_to_pyobject(env)
        self.is_temp = 1
3918 3919

    def generate_result_code(self, code):
3920 3921 3922 3923 3924 3925 3926 3927 3928
        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" %
3929
            (self.result(),
3930
             function,
3931 3932 3933 3934 3935 3936
             self.target.result(),
             self.expr.result(),
             code.error_goto_if(self.result(), self.pos)))

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

3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955
    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)))


3956
class SetNode(ExprNode):
3957 3958
    #  Set constructor.

3959 3960
    type = set_type

3961 3962 3963
    subexprs = ['args']

    gil_message = "Constructing Python set"
3964
    
3965 3966 3967 3968 3969 3970 3971 3972
    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

3973 3974 3975
    def may_be_none(self):
        return False

3976 3977 3978 3979
    def calculate_constant_result(self):
        self.constant_result = set([
                arg.constant_result for arg in self.args])

3980 3981 3982 3983 3984 3985 3986 3987
    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):
3988
        code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3989 3990 3991 3992 3993
        self.allocate_temp_result(code)
        code.putln(
            "%s = PySet_New(0); %s" % (
                self.result(),
                code.error_goto_if_null(self.result(), self.pos)))
3994
        code.put_gotref(self.py_result())
3995 3996 3997 3998 3999 4000 4001 4002
        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
4003

William Stein's avatar
William Stein committed
4004

4005
class DictNode(ExprNode):
William Stein's avatar
William Stein committed
4006 4007
    #  Dictionary constructor.
    #
4008
    #  key_value_pairs  [DictItemNode]
4009 4010
    #
    # obj_conversion_errors    [PyrexError]   used internally
4011 4012
    
    subexprs = ['key_value_pairs']
4013 4014
    is_temp = 1
    type = dict_type
4015

4016 4017
    obj_conversion_errors = []

4018 4019 4020
    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
4021
    
4022
    def compile_time_value(self, denv):
Robert Bradshaw's avatar
Robert Bradshaw committed
4023 4024
        pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
            for item in self.key_value_pairs]
4025 4026 4027 4028 4029
        try:
            return dict(pairs)
        except Exception, e:
            self.compile_time_value_error(e)
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4030
    def type_dependencies(self, env):
4031 4032 4033 4034 4035 4036
        return ()
    
    def infer_type(self, env):
        # TOOD: Infer struct constructors.
        return dict_type

William Stein's avatar
William Stein committed
4037
    def analyse_types(self, env):
4038
        hold_errors()
Robert Bradshaw's avatar
Robert Bradshaw committed
4039 4040
        for item in self.key_value_pairs:
            item.analyse_types(env)
4041 4042
        self.obj_conversion_errors = held_errors()
        release_errors(ignore=True)
4043 4044 4045

    def may_be_none(self):
        return False
4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060
        
    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
4061
                if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
4062
                    error(item.key.pos, "Invalid struct field identifier")
4063
                    item.key = StringNode(item.key.pos, value="<error>")
4064
                else:
Stefan Behnel's avatar
Stefan Behnel committed
4065 4066
                    key = str(item.key.value) # converts string literals to unicode in Py3
                    member = dst_type.scope.lookup_here(key)
4067
                    if not member:
Stefan Behnel's avatar
Stefan Behnel committed
4068
                        error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082
                    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 = []
4083 4084 4085

    gil_message = "Constructing Python dict"

William Stein's avatar
William Stein committed
4086 4087 4088
    def generate_evaluation_code(self, code):
        #  Custom method used here because key-value
        #  pairs are evaluated and used one at a time.
4089 4090
        code.mark_pos(self.pos)
        self.allocate_temp_result(code)
4091 4092 4093 4094 4095 4096
        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)))
4097
            code.put_gotref(self.py_result())
Robert Bradshaw's avatar
Robert Bradshaw committed
4098 4099
        for item in self.key_value_pairs:
            item.generate_evaluation_code(code)
4100 4101 4102 4103 4104 4105 4106 4107 4108
            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(),
4109
                        item.key.value,
4110
                        item.value.result()))
Robert Bradshaw's avatar
Robert Bradshaw committed
4111
            item.generate_disposal_code(code)
4112
            item.free_temps(code)
4113 4114
            
    def annotate(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4115 4116 4117
        for item in self.key_value_pairs:
            item.annotate(code)
            
4118
class DictItemNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
4119 4120 4121 4122 4123
    # Represents a single item in a DictNode
    #
    # key          ExprNode
    # value        ExprNode
    subexprs = ['key', 'value']
4124

4125
    nogil_check = None # Parent DictNode takes care of it
4126

4127 4128 4129
    def calculate_constant_result(self):
        self.constant_result = (
            self.key.constant_result, self.value.constant_result)
Robert Bradshaw's avatar
Robert Bradshaw committed
4130 4131 4132 4133 4134 4135 4136 4137 4138 4139
            
    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
4140

4141 4142 4143
    def generate_disposal_code(self, code):
        self.key.generate_disposal_code(code)
        self.value.generate_disposal_code(code)
4144 4145 4146 4147

    def free_temps(self, code):
        self.key.free_temps(code)
        self.value.free_temps(code)
4148 4149 4150
        
    def __iter__(self):
        return iter([self.key, self.value])
William Stein's avatar
William Stein committed
4151

Stefan Behnel's avatar
Stefan Behnel committed
4152

4153
class ClassNode(ExprNode):
William Stein's avatar
William Stein committed
4154 4155 4156 4157
    #  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
4158
    #  name         EncodedString      Name of the class
William Stein's avatar
William Stein committed
4159 4160 4161 4162 4163
    #  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
    
4164 4165
    subexprs = ['bases', 'doc']

William Stein's avatar
William Stein committed
4166 4167 4168 4169 4170 4171 4172 4173 4174
    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);
4175

4176 4177 4178
    def may_be_none(self):
        return False

4179 4180
    gil_message = "Constructing Python class"

William Stein's avatar
William Stein committed
4181
    def generate_result_code(self, code):
4182
        cname = code.intern_identifier(self.name)
William Stein's avatar
William Stein committed
4183
        if self.doc:
Robert Bradshaw's avatar
Robert Bradshaw committed
4184 4185
            code.put_error_if_neg(self.pos, 
                'PyDict_SetItemString(%s, "__doc__", %s)' % (
William Stein's avatar
William Stein committed
4186
                    self.dict.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
4187
                    self.doc.py_result()))
William Stein's avatar
William Stein committed
4188
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4189
            '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
4190
                self.result(),
William Stein's avatar
William Stein committed
4191 4192
                self.bases.py_result(),
                self.dict.py_result(),
4193
                cname,
William Stein's avatar
William Stein committed
4194
                self.module_name,
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 4198


4199
class UnboundMethodNode(ExprNode):
William Stein's avatar
William Stein committed
4200 4201 4202 4203 4204 4205
    #  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
    
4206 4207 4208
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4209 4210 4211 4212
    subexprs = ['function']
    
    def analyse_types(self, env):
        self.function.analyse_types(env)
4213

4214 4215 4216
    def may_be_none(self):
        return False

4217 4218
    gil_message = "Constructing an unbound method"

William Stein's avatar
William Stein committed
4219
    def generate_result_code(self, code):
4220
        class_cname = code.pyclass_stack[-1].classobj.result()
William Stein's avatar
William Stein committed
4221
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4222
            "%s = PyMethod_New(%s, 0, %s); %s" % (
4223
                self.result(),
William Stein's avatar
William Stein committed
4224
                self.function.py_result(),
4225
                class_cname,
4226
                code.error_goto_if_null(self.result(), self.pos)))
4227
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4228

Robert Bradshaw's avatar
Robert Bradshaw committed
4229

4230
class PyCFunctionNode(AtomicExprNode):
William Stein's avatar
William Stein committed
4231 4232 4233 4234 4235 4236
    #  Helper class used in the implementation of Python
    #  class definitions. Constructs a PyCFunction object
    #  from a PyMethodDef struct.
    #
    #  pymethdef_cname   string   PyMethodDef structure
    
4237 4238 4239
    type = py_object_type
    is_temp = 1
    
William Stein's avatar
William Stein committed
4240
    def analyse_types(self, env):
4241
        pass
4242 4243 4244

    def may_be_none(self):
        return False
4245
    
4246 4247
    gil_message = "Constructing Python function"

William Stein's avatar
William Stein committed
4248 4249
    def generate_result_code(self, code):
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4250
            "%s = PyCFunction_New(&%s, 0); %s" % (
4251
                self.result(),
William Stein's avatar
William Stein committed
4252
                self.pymethdef_cname,
4253
                code.error_goto_if_null(self.result(), self.pos)))
4254
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4255 4256 4257 4258 4259 4260 4261

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

4262 4263 4264 4265 4266 4267 4268
compile_time_unary_operators = {
    'not': operator.not_,
    '~': operator.inv,
    '-': operator.neg,
    '+': operator.pos,
}

4269
class UnopNode(ExprNode):
William Stein's avatar
William Stein committed
4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281
    #  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
4282
    infix = True
4283 4284 4285 4286

    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
4287
    
4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298
    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)
4299 4300 4301
    
    def infer_type(self, env):
        return self.operand.infer_type(env)
4302

William Stein's avatar
William Stein committed
4303 4304 4305 4306 4307 4308
    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
4309 4310
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
4311 4312 4313 4314
        else:
            self.analyse_c_operation(env)
    
    def check_const(self):
4315
        return self.operand.check_const()
William Stein's avatar
William Stein committed
4316 4317 4318
    
    def is_py_operation(self):
        return self.operand.type.is_pyobject
4319

4320
    def nogil_check(self, env):
4321
        if self.is_py_operation():
4322
            self.gil_error()
4323

Danilo Freitas's avatar
Danilo Freitas committed
4324
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4325
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
4326
        return type.is_cpp_class
William Stein's avatar
William Stein committed
4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337
    
    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
4338
            "%s = %s(%s); %s" % (
4339
                self.result(), 
William Stein's avatar
William Stein committed
4340 4341
                function, 
                self.operand.py_result(),
4342
                code.error_goto_if_null(self.result(), self.pos)))
4343
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4344 4345 4346 4347 4348 4349 4350
        
    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
4351
    def analyse_cpp_operation(self, env):
4352
        type = self.operand.type
Robert Bradshaw's avatar
Robert Bradshaw committed
4353
        if type.is_ptr:
Danilo Freitas's avatar
Danilo Freitas committed
4354
            type = type.base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4355
        function = type.scope.lookup("operator%s" % self.operator)
Danilo Freitas's avatar
Danilo Freitas committed
4356 4357
        if not function:
            error(self.pos, "'%s' operator not defined for %s"
4358
                % (self.operator, type))
Danilo Freitas's avatar
Danilo Freitas committed
4359 4360
            self.type_error()
            return
4361 4362 4363 4364
        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
4365

William Stein's avatar
William Stein committed
4366

4367
class NotNode(ExprNode):
William Stein's avatar
William Stein committed
4368 4369 4370
    #  'not' operator
    #
    #  operand   ExprNode
4371 4372
    
    type = PyrexTypes.c_bint_type
4373

4374 4375
    subexprs = ['operand']
    
4376 4377 4378
    def calculate_constant_result(self):
        self.constant_result = not self.operand.constant_result

4379 4380 4381 4382 4383 4384 4385
    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)

4386 4387
    def infer_type(self, env):
        return PyrexTypes.c_bint_type
William Stein's avatar
William Stein committed
4388 4389 4390 4391 4392 4393
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
        self.operand = self.operand.coerce_to_boolean(env)
    
    def calculate_result_code(self):
4394
        return "(!%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411
    
    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):
4412 4413 4414 4415
        if self.is_cpp_operation():
            return "(+%s)" % self.operand.result()
        else:
            return self.operand.result()
William Stein's avatar
William Stein committed
4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427


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
4428
        if self.type.is_complex:
4429
            self.infix = False
William Stein's avatar
William Stein committed
4430 4431 4432 4433 4434
    
    def py_operation_function(self):
        return "PyNumber_Negative"
    
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4435 4436 4437 4438
        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
4439

4440 4441 4442 4443 4444
    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
4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457
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):
4458
        return "(~%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4459 4460


4461 4462
class CUnopNode(UnopNode):

Robert Bradshaw's avatar
Robert Bradshaw committed
4463 4464 4465
    def is_py_operation(self):
        return False

4466 4467
class DereferenceNode(CUnopNode):
    #  unary * operator
4468 4469

    operator = '*'
4470
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4471 4472 4473 4474 4475 4476 4477 4478
    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
4479 4480


4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499
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)


4500
class AmpersandNode(ExprNode):
William Stein's avatar
William Stein committed
4501 4502 4503 4504 4505
    #  The C address-of operator.
    #
    #  operand  ExprNode
    
    subexprs = ['operand']
4506 4507 4508
    
    def infer_type(self, env):
        return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
William Stein's avatar
William Stein committed
4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521

    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):
4522
        return self.operand.check_const_addr()
William Stein's avatar
William Stein committed
4523 4524 4525 4526 4527 4528 4529
    
    def error(self, mess):
        error(self.pos, mess)
        self.type = PyrexTypes.error_type
        self.result_code = "<error>"
    
    def calculate_result_code(self):
4530
        return "(&%s)" % self.operand.result()
William Stein's avatar
William Stein committed
4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544

    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.
4545
    if isinstance(operand, IntNode) and operator == '-':
4546
        return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
Robert Bradshaw's avatar
Robert Bradshaw committed
4547 4548
    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
4549 4550 4551 4552 4553
    return unop_node_classes[operator](pos, 
        operator = operator, 
        operand = operand)


4554
class TypecastNode(ExprNode):
William Stein's avatar
William Stein committed
4555 4556
    #  C type cast
    #
4557
    #  operand      ExprNode
William Stein's avatar
William Stein committed
4558 4559
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
4560 4561 4562
    #
    #  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
4563 4564
    
    subexprs = ['operand']
4565
    base_type = declarator = type = None
William Stein's avatar
William Stein committed
4566
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4567
    def type_dependencies(self, env):
4568 4569
        return ()
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4570
    def infer_type(self, env):
4571 4572 4573 4574 4575
        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
4576
    def analyse_types(self, env):
4577 4578 4579
        if self.type is None:
            base_type = self.base_type.analyse(env)
            _, self.type = self.declarator.analyse(base_type, env)
4580 4581 4582 4583
        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
4584 4585 4586
        self.operand.analyse_types(env)
        to_py = self.type.is_pyobject
        from_py = self.operand.type.is_pyobject
4587 4588
        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
4589
        if to_py and not from_py:
4590 4591 4592 4593 4594 4595
            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
4596
                self.result_ctype = py_object_type
4597
                self.operand = self.operand.coerce_to_pyobject(env)
4598
            else:
4599 4600 4601 4602 4603
                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? 
4604
                    warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4605
                self.operand = self.operand.coerce_to_simple(env)
4606
        elif from_py and not to_py:
4607
            if self.type.create_from_py_utility_code(env):
4608
                self.operand = self.operand.coerce_to(self.type, env)
4609 4610 4611
            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")
4612 4613
            else:
                warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4614 4615
        elif from_py and to_py:
            if self.typecheck and self.type.is_extension_type:
4616
                self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4617 4618
        elif self.type.is_complex and self.operand.type.is_complex:
            self.operand = self.operand.coerce_to_simple(env)
4619

4620 4621 4622
    def nogil_check(self, env):
        if self.type and self.type.is_pyobject and self.is_temp:
            self.gil_error()
4623

William Stein's avatar
William Stein committed
4624
    def check_const(self):
4625
        return self.operand.check_const()
Stefan Behnel's avatar
Stefan Behnel committed
4626 4627

    def calculate_constant_result(self):
4628 4629 4630
        # we usually do not know the result of a type cast at code
        # generation time
        pass
William Stein's avatar
William Stein committed
4631 4632
    
    def calculate_result_code(self):
4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646
        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
4647
    
4648 4649 4650 4651 4652
    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
4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663
    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;" % (
4664 4665 4666
                    self.result(),
                    self.operand.result()))
            code.put_incref(self.result(), self.ctype())
William Stein's avatar
William Stein committed
4667 4668


4669
class SizeofNode(ExprNode):
William Stein's avatar
William Stein committed
4670
    #  Abstract base class for sizeof(x) expression nodes.
4671
    
4672
    type = PyrexTypes.c_size_t_type
William Stein's avatar
William Stein committed
4673 4674

    def check_const(self):
4675
        return True
William Stein's avatar
William Stein committed
4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687

    def generate_result_code(self, code):
        pass


class SizeofTypeNode(SizeofNode):
    #  C sizeof function applied to a type
    #
    #  base_type   CBaseTypeNode
    #  declarator  CDeclaratorNode
    
    subexprs = []
4688
    arg_type = None
William Stein's avatar
William Stein committed
4689 4690
    
    def analyse_types(self, env):
4691 4692
        # 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
4693
        if 0 and self.base_type.module_path:
4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704
            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
4705 4706 4707 4708
        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
4709 4710 4711 4712
        self.check_type()
        
    def check_type(self):
        arg_type = self.arg_type
4713
        if arg_type.is_pyobject and not arg_type.is_extension_type:
William Stein's avatar
William Stein committed
4714 4715 4716 4717 4718 4719 4720
            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):
4721 4722 4723 4724 4725 4726
        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
4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737
        return "(sizeof(%s))" % arg_code
    

class SizeofVarNode(SizeofNode):
    #  C sizeof function applied to a variable
    #
    #  operand   ExprNode
    
    subexprs = ['operand']
    
    def analyse_types(self, env):
4738 4739 4740 4741 4742 4743 4744 4745 4746
        # 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
4747 4748
    
    def calculate_result_code(self):
4749
        return "(sizeof(%s))" % self.operand.result()
William Stein's avatar
William Stein committed
4750 4751 4752 4753
    
    def generate_result_code(self, code):
        pass

Robert Bradshaw's avatar
Robert Bradshaw committed
4754
class TypeofNode(ExprNode):
4755 4756 4757
    #  Compile-time type of an expression, as a string.
    #
    #  operand   ExprNode
Robert Bradshaw's avatar
Robert Bradshaw committed
4758
    #  literal   StringNode # internal
4759
    
Robert Bradshaw's avatar
Robert Bradshaw committed
4760 4761 4762
    literal = None
    type = py_object_type
    
Stefan Behnel's avatar
Stefan Behnel committed
4763
    subexprs = ['literal'] # 'operand' will be ignored after type analysis!
4764 4765 4766
    
    def analyse_types(self, env):
        self.operand.analyse_types(env)
4767 4768
        self.literal = StringNode(
            self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
Robert Bradshaw's avatar
Robert Bradshaw committed
4769 4770
        self.literal.analyse_types(env)
        self.literal = self.literal.coerce_to_pyobject(env)
4771 4772 4773 4774

    def may_be_none(self):
        return False

4775
    def generate_evaluation_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
4776 4777 4778 4779
        self.literal.generate_evaluation_code(code)
    
    def calculate_result_code(self):
        return self.literal.calculate_result_code()
William Stein's avatar
William Stein committed
4780 4781 4782 4783 4784 4785 4786

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

Stefan Behnel's avatar
Stefan Behnel committed
4787 4788 4789
def _not_in(x, seq):
    return x not in seq

4790 4791 4792
compile_time_binary_operators = {
    '<': operator.lt,
    '<=': operator.le,
4793
    '==': operator.eq,
4794 4795 4796 4797 4798 4799 4800
    '!=': operator.ne,
    '>=': operator.ge,
    '>': operator.gt,
    'is': operator.is_,
    'is_not': operator.is_not,
    '+': operator.add,
    '&': operator.and_,
4801
    '/': operator.truediv,
4802 4803 4804 4805 4806 4807 4808 4809 4810
    '//': 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
4811 4812
    'in': operator.contains,
    'not_in': _not_in,
4813 4814 4815 4816 4817 4818 4819
}

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"
4820
                % node.operator)
4821 4822
    return func

4823
class BinopNode(ExprNode):
William Stein's avatar
William Stein committed
4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836
    #  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']
4837 4838 4839 4840 4841 4842 4843

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

4844 4845 4846 4847 4848 4849 4850 4851
    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)
4852 4853 4854
    
    def infer_type(self, env):
        return self.result_type(self.operand1.infer_type(env),
Robert Bradshaw's avatar
Robert Bradshaw committed
4855 4856
                                self.operand2.infer_type(env))
    
William Stein's avatar
William Stein committed
4857 4858 4859 4860 4861
    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)
4862 4863 4864
            self.type = self.result_type(self.operand1.type,
                                         self.operand2.type)
            assert self.type.is_pyobject
William Stein's avatar
William Stein committed
4865
            self.is_temp = 1
DaniloFreitas's avatar
DaniloFreitas committed
4866 4867
        elif self.is_cpp_operation():
            self.analyse_cpp_operation(env)
William Stein's avatar
William Stein committed
4868 4869 4870 4871
        else:
            self.analyse_c_operation(env)
    
    def is_py_operation(self):
4872 4873 4874 4875 4876
        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
4877
    def is_cpp_operation(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
4878 4879
        return (self.operand1.type.is_cpp_class
            or self.operand2.type.is_cpp_class)
DaniloFreitas's avatar
DaniloFreitas committed
4880
    
4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897
    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
    
4898 4899
    def result_type(self, type1, type2):
        if self.is_py_operation_types(type1, type2):
4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917
            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
4918
                    if type2.is_int:
4919
                        return type1
4920 4921 4922 4923
            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
4924 4925 4926
            return py_object_type
        else:
            return self.compute_c_result_type(type1, type2)
4927

4928
    def nogil_check(self, env):
4929
        if self.is_py_operation():
4930
            self.gil_error()
4931
        
William Stein's avatar
William Stein committed
4932 4933 4934 4935 4936
    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):
4937
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
4938 4939 4940 4941 4942 4943 4944 4945 4946 4947
    
    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
4948
                "%s = %s(%s, %s%s); %s" % (
4949
                    self.result(), 
William Stein's avatar
William Stein committed
4950 4951 4952 4953
                    function, 
                    self.operand1.py_result(),
                    self.operand2.py_result(),
                    extra_args,
4954
                    code.error_goto_if_null(self.result(), self.pos)))
4955
            code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968
    
    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
4969 4970
    infix = True
    
William Stein's avatar
William Stein committed
4971 4972 4973 4974 4975 4976
    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()
4977
            return
4978
        if self.type.is_complex:
Robert Bradshaw's avatar
Robert Bradshaw committed
4979
            self.infix = False
4980 4981 4982
        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
4983 4984 4985 4986 4987 4988
    
    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
4989 4990 4991 4992 4993 4994 4995 4996

    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
4997 4998
    
    def c_types_okay(self, type1, type2):
4999 5000 5001
        #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
5002 5003

    def calculate_result_code(self):
5004 5005 5006 5007 5008 5009
        if self.infix:
            return "(%s %s %s)" % (
                self.operand1.result(), 
                self.operator, 
                self.operand2.result())
        else:
5010 5011 5012
            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))
5013
            return "%s(%s, %s)" % (
5014
                func,
5015 5016
                self.operand1.result(),
                self.operand2.result())
William Stein's avatar
William Stein committed
5017 5018 5019 5020 5021
    
    def py_operation_function(self):
        return self.py_functions[self.operator]

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
5022 5023 5024
        "|":        "PyNumber_Or",
        "^":        "PyNumber_Xor",
        "&":        "PyNumber_And",
5025 5026
        "<<":       "PyNumber_Lshift",
        ">>":       "PyNumber_Rshift",
Robert Bradshaw's avatar
Robert Bradshaw committed
5027 5028 5029 5030
        "+":        "PyNumber_Add",
        "-":        "PyNumber_Subtract",
        "*":        "PyNumber_Multiply",
        "/":        "__Pyx_PyNumber_Divide",
5031
        "//":       "PyNumber_FloorDivide",
Robert Bradshaw's avatar
Robert Bradshaw committed
5032
        "%":        "PyNumber_Remainder",
5033
        "**":       "PyNumber_Power"
William Stein's avatar
William Stein committed
5034 5035 5036 5037 5038 5039 5040
    }


class IntBinopNode(NumBinopNode):
    #  Binary operation taking integer arguments.
    
    def c_types_okay(self, type1, type2):
5041 5042 5043
        #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
5044 5045 5046 5047 5048

    
class AddNode(NumBinopNode):
    #  '+' operator.
    
5049 5050 5051
    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
5052
        else:
5053
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5054 5055

    def compute_c_result_type(self, type1, type2):
5056 5057
        #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
5058
            return type1
5059
        elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
William Stein's avatar
William Stein committed
5060 5061 5062 5063 5064 5065 5066 5067 5068 5069
            return type2
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class SubNode(NumBinopNode):
    #  '-' operator.
    
    def compute_c_result_type(self, type1, type2):
5070
        if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
William Stein's avatar
William Stein committed
5071
            return type1
5072
        elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
William Stein's avatar
William Stein committed
5073 5074 5075 5076 5077 5078 5079 5080 5081
            return PyrexTypes.c_int_type
        else:
            return NumBinopNode.compute_c_result_type(
                self, type1, type2)


class MulNode(NumBinopNode):
    #  '*' operator.
    
5082
    def is_py_operation_types(self, type1, type2):
William Stein's avatar
William Stein committed
5083 5084 5085 5086
        if (type1.is_string and type2.is_int) \
            or (type2.is_string and type1.is_int):
                return 1
        else:
5087
            return NumBinopNode.is_py_operation_types(self, type1, type2)
William Stein's avatar
William Stein committed
5088 5089


5090 5091 5092
class DivNode(NumBinopNode):
    #  '/' or '//' operator.
    
5093
    cdivision = None
5094 5095
    truedivision = None   # == "unknown" if operator == '/'
    ctruedivision = False
Robert Bradshaw's avatar
Robert Bradshaw committed
5096
    cdivision_warnings = False
5097
    zerodivision_check = None
5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124

    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)

5125
    def analyse_types(self, env):
5126 5127 5128 5129
        if self.cdivision or env.directives['cdivision']:
            self.ctruedivision = False
        else:
            self.ctruedivision = self.truedivision
5130
        NumBinopNode.analyse_types(self, env)
5131 5132
        if self.is_cpp_operation():
            self.cdivision = True
5133
        if not self.type.is_pyobject:
5134 5135
            self.zerodivision_check = (
                self.cdivision is None and not env.directives['cdivision']
5136
                and (not self.operand2.has_constant_result() or
5137
                     self.operand2.constant_result == 0))
5138 5139 5140 5141
            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)
5142 5143
                if env.nogil:
                    error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
5144 5145 5146 5147 5148 5149 5150 5151 5152

    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)

5153 5154 5155 5156 5157
    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
5158

5159
    def generate_evaluation_code(self, code):
5160
        if not self.type.is_pyobject and not self.type.is_complex:
5161 5162 5163 5164 5165
            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:
5166
                code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
5167
        NumBinopNode.generate_evaluation_code(self, code)
5168
        self.generate_div_warning_code(code)
5169 5170
    
    def generate_div_warning_code(self, code):
5171 5172
        if not self.type.is_pyobject:
            if self.zerodivision_check:
5173 5174 5175 5176 5177
                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)
5178 5179 5180
                code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
                code.putln(code.error_goto(self.pos))
                code.putln("}")
5181 5182 5183 5184 5185 5186 5187 5188 5189
                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
5190
            if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
5191 5192 5193 5194 5195 5196 5197 5198
                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
5199 5200
    
    def calculate_result_code(self):
5201 5202 5203
        if self.type.is_complex:
            return NumBinopNode.calculate_result_code(self)
        elif self.type.is_float and self.operator == '//':
5204
            return "floor(%s / %s)" % (
5205
                self.operand1.result(),
5206
                self.operand2.result())
5207 5208 5209 5210 5211 5212 5213 5214 5215
        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)
5216 5217
        else:
            return "__Pyx_div_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5218
                    self.type.specialization_name(),
5219 5220
                    self.operand1.result(), 
                    self.operand2.result())
Robert Bradshaw's avatar
Robert Bradshaw committed
5221 5222


Robert Bradshaw's avatar
Robert Bradshaw committed
5223
class ModNode(DivNode):
William Stein's avatar
William Stein committed
5224
    #  '%' operator.
5225

5226 5227 5228 5229
    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
5230

5231 5232 5233 5234 5235 5236
    def zero_division_message(self):
        if self.type.is_int:
            return "integer division or modulo by zero"
        else:
            return "float divmod()"
    
5237
    def generate_evaluation_code(self, code):
5238 5239 5240 5241 5242
        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:
5243
                    code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
5244
                else:
5245 5246
                    code.globalstate.use_utility_code(
                        mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
5247
        NumBinopNode.generate_evaluation_code(self, code)
5248
        self.generate_div_warning_code(code)
5249
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5250
    def calculate_result_code(self):
5251 5252 5253 5254 5255 5256 5257 5258 5259 5260
        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
5261
        else:
5262
            return "__Pyx_mod_%s(%s, %s)" % (
Craig Citro's avatar
Craig Citro committed
5263
                    self.type.specialization_name(),
5264 5265
                    self.operand1.result(), 
                    self.operand2.result())
William Stein's avatar
William Stein committed
5266 5267 5268

class PowNode(NumBinopNode):
    #  '**' operator.
Robert Bradshaw's avatar
Robert Bradshaw committed
5269 5270 5271
    
    def analyse_c_operation(self, env):
        NumBinopNode.analyse_c_operation(self, env)
5272 5273 5274 5275
        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
5276
            self.pow_func = "pow"
William Stein's avatar
William Stein committed
5277
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
5278 5279 5280 5281
            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('')))
5282

William Stein's avatar
William Stein committed
5283
    def calculate_result_code(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5284 5285 5286 5287
        return "%s(%s, %s)" % (
            self.pow_func, 
            self.operand1.result(), 
            self.operand2.result())
5288

William Stein's avatar
William Stein committed
5289

5290 5291 5292 5293 5294 5295 5296
# 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).
5297
class BoolBinopNode(ExprNode):
William Stein's avatar
William Stein committed
5298 5299 5300 5301 5302 5303
    #  Short-circuiting boolean operation.
    #
    #  operator     string
    #  operand1     ExprNode
    #  operand2     ExprNode
    
5304
    subexprs = ['operand1', 'operand2']
5305 5306
    
    def infer_type(self, env):
5307 5308
        type1 = self.operand1.infer_type(env)
        type2 = self.operand2.infer_type(env)
5309
        return PyrexTypes.independent_spanning_type(type1, type2)
5310 5311 5312 5313 5314 5315 5316 5317 5318 5319

    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
5320
    
5321 5322 5323 5324 5325 5326 5327
    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)
5328 5329 5330 5331 5332 5333
    
    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
5334

William Stein's avatar
William Stein committed
5335 5336 5337
    def analyse_types(self, env):
        self.operand1.analyse_types(env)
        self.operand2.analyse_types(env)
5338
        self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
5339 5340
        self.operand1 = self.operand1.coerce_to(self.type, env)
        self.operand2 = self.operand2.coerce_to(self.type, env)
5341
        
William Stein's avatar
William Stein committed
5342 5343
        # For what we're about to do, it's vital that
        # both operands be temp nodes.
5344 5345
        self.operand1 = self.operand1.coerce_to_simple(env)
        self.operand2 = self.operand2.coerce_to_simple(env)
William Stein's avatar
William Stein committed
5346
        self.is_temp = 1
5347 5348 5349

    gil_message = "Truth-testing Python object"

William Stein's avatar
William Stein committed
5350
    def check_const(self):
5351
        return self.operand1.check_const() and self.operand2.check_const()
William Stein's avatar
William Stein committed
5352 5353
    
    def generate_evaluation_code(self, code):
5354
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
5355
        self.operand1.generate_evaluation_code(code)
5356
        test_result, uses_temp = self.generate_operand1_test(code)
William Stein's avatar
William Stein committed
5357 5358 5359 5360 5361 5362 5363 5364
        if self.operator == 'and':
            sense = ""
        else:
            sense = "!"
        code.putln(
            "if (%s%s) {" % (
                sense,
                test_result))
5365 5366
        if uses_temp:
            code.funcstate.release_temp(test_result)
5367
        self.operand1.generate_disposal_code(code)
William Stein's avatar
William Stein committed
5368
        self.operand2.generate_evaluation_code(code)
5369
        self.allocate_temp_result(code)
5370
        self.operand2.make_owned_reference(code)
5371
        code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5372 5373
        self.operand2.generate_post_assignment_code(code)
        self.operand2.free_temps(code)
5374
        code.putln("} else {")
5375
        self.operand1.make_owned_reference(code)
5376
        code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5377 5378
        self.operand1.generate_post_assignment_code(code)
        self.operand1.free_temps(code)
5379
        code.putln("}")
William Stein's avatar
William Stein committed
5380 5381 5382 5383
    
    def generate_operand1_test(self, code):
        #  Generate code to test the truth of the first operand.
        if self.type.is_pyobject:
5384 5385
            test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
                                                       manage_ref=False)
William Stein's avatar
William Stein committed
5386
            code.putln(
5387
                "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
William Stein's avatar
William Stein committed
5388 5389
                    test_result,
                    self.operand1.py_result(),
Robert Bradshaw's avatar
Robert Bradshaw committed
5390
                    code.error_goto_if_neg(test_result, self.pos)))
William Stein's avatar
William Stein committed
5391
        else:
5392
            test_result = self.operand1.result()
5393
        return (test_result, self.type.is_pyobject)
William Stein's avatar
William Stein committed
5394 5395


5396
class CondExprNode(ExprNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
5397 5398 5399 5400 5401 5402
    #  Short-circuiting conditional expression.
    #
    #  test        ExprNode
    #  true_val    ExprNode
    #  false_val   ExprNode
    
5403 5404
    true_val = None
    false_val = None
Robert Bradshaw's avatar
Robert Bradshaw committed
5405 5406
    
    subexprs = ['test', 'true_val', 'false_val']
5407
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5408 5409
    def type_dependencies(self, env):
        return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5410
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5411
    def infer_type(self, env):
5412 5413
        return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
                                                    self.false_val.infer_type(env))
5414 5415 5416 5417 5418 5419 5420

    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
5421 5422 5423 5424 5425
    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)
5426
        self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
5427 5428 5429 5430 5431
        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
5432 5433 5434 5435 5436 5437 5438
            self.type_error()
        
    def type_error(self):
        if not (self.true_val.type.is_error or self.false_val.type.is_error):
            error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
                (self.true_val.type, self.false_val.type))
        self.type = PyrexTypes.error_type
5439
    
Robert Bradshaw's avatar
Robert Bradshaw committed
5440
    def check_const(self):
5441 5442 5443
        return (self.test.check_const() 
            and self.true_val.check_const()
            and self.false_val.check_const())
Robert Bradshaw's avatar
Robert Bradshaw committed
5444 5445
    
    def generate_evaluation_code(self, code):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5446 5447 5448 5449
        # 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)
5450
        self.allocate_temp_result(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
5451
        self.test.generate_evaluation_code(code)
5452
        code.putln("if (%s) {" % self.test.result() )
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5453
        self.eval_and_get(code, self.true_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
5454
        code.putln("} else {")
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5455
        self.eval_and_get(code, self.false_val)
Robert Bradshaw's avatar
Robert Bradshaw committed
5456 5457
        code.putln("}")
        self.test.generate_disposal_code(code)
5458
        self.test.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
5459

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
5460 5461 5462 5463 5464 5465 5466
    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)

5467 5468 5469 5470 5471 5472 5473 5474 5475 5476
richcmp_constants = {
    "<" : "Py_LT",
    "<=": "Py_LE",
    "==": "Py_EQ",
    "!=": "Py_NE",
    "<>": "Py_NE",
    ">" : "Py_GT",
    ">=": "Py_GE",
}

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

    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)
5489 5490 5491 5492 5493 5494 5495
        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

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

5511
    def is_cpp_comparison(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
5512
        return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
5513

5514
    def find_common_int_type(self, env, op, operand1, operand2):
5515 5516 5517 5518 5519 5520
        # 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

5521
        if isinstance(operand1, (StringNode, BytesNode, UnicodeNode)) \
5522 5523
               and operand1.can_coerce_to_char_literal():
            type1_can_be_int = True
5524
        if isinstance(operand2, (StringNode, BytesNode, UnicodeNode)) \
5525 5526 5527 5528 5529
                 and operand2.can_coerce_to_char_literal():
            type2_can_be_int = True

        if type1.is_int:
            if type2_can_be_int:
5530
                return type1
5531 5532
        elif type2.is_int:
            if type1_can_be_int:
5533
                return type2
5534 5535
        elif type1_can_be_int:
            if type2_can_be_int:
5536
                return PyrexTypes.c_uchar_type
5537

5538
        return None
5539

5540
    def find_common_type(self, env, op, operand1, common_type=None):
5541 5542 5543 5544
        operand2 = self.operand2
        type1 = operand1.type
        type2 = operand2.type

5545 5546
        new_common_type = None

Stefan Behnel's avatar
Stefan Behnel committed
5547
        # catch general errors
5548 5549 5550
        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")
5551
            new_common_type = error_type
Stefan Behnel's avatar
Stefan Behnel committed
5552 5553

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

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

Stefan Behnel's avatar
Stefan Behnel committed
5599
        # recursively merge types
5600
        if common_type is None or new_common_type.is_error:
5601 5602
            common_type = new_common_type
        else:
5603 5604 5605
            # 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
5606
            common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5607 5608

        if self.cascade:
5609
            common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5610

5611 5612
        return common_type

5613 5614 5615 5616
    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
5617
    def is_python_comparison(self):
5618 5619 5620 5621
        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
5622

5623 5624 5625 5626 5627 5628
    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)
5629

5630
    def is_python_result(self):
5631
        return ((self.has_python_operands() and
5632 5633
                 self.operator not in ('is', 'is_not', 'in', 'not_in') and
                 not self.is_c_string_contains())
5634 5635
            or (self.cascade and self.cascade.is_python_result()))

5636 5637
    def is_c_string_contains(self):
        return self.operator in ('in', 'not_in') and \
5638 5639
               ((self.operand1.type.is_int
                 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
5640 5641 5642
                (self.operand1.type is PyrexTypes.c_py_unicode_type
                 and self.operand2.type is unicode_type))

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

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

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 5771 5772 5773 5774 5775
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
5776

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

Robert Bradshaw's avatar
Robert Bradshaw committed
5795 5796 5797 5798 5799 5800 5801
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

5802
    def calculate_constant_result(self):
5803
        self.calculate_cascaded_constant_result(self.operand1.constant_result)
William Stein's avatar
William Stein committed
5804
    
5805
    def compile_time_value(self, denv):
5806
        operand1 = self.operand1.compile_time_value(denv)
5807 5808
        return self.cascaded_compile_time_value(operand1, denv)

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

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

5844
        if common_type is not None and not common_type.is_error:
5845 5846 5847
            if self.operand1.type != common_type:
                self.operand1 = self.operand1.coerce_to(common_type, env)
            self.coerce_operands_to(common_type, env)
5848

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

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

William Stein's avatar
William Stein committed
5925 5926 5927 5928
    def generate_evaluation_code(self, code):
        self.operand1.generate_evaluation_code(code)
        self.operand2.generate_evaluation_code(code)
        if self.is_temp:
5929
            self.allocate_temp_result(code)
5930
            self.generate_operation_code(code, self.result(), 
William Stein's avatar
William Stein committed
5931 5932 5933
                self.operand1, self.operator, self.operand2)
            if self.cascade:
                self.cascade.generate_evaluation_code(code,
5934
                    self.result(), self.operand2)
William Stein's avatar
William Stein committed
5935
            self.operand1.generate_disposal_code(code)
5936
            self.operand1.free_temps(code)
William Stein's avatar
William Stein committed
5937
            self.operand2.generate_disposal_code(code)
5938
            self.operand2.free_temps(code)
5939

William Stein's avatar
William Stein committed
5940 5941 5942 5943 5944
    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)
5945
        
5946 5947 5948 5949 5950 5951
    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)
        
5952 5953 5954 5955 5956
    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
5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968


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

William Stein's avatar
William Stein committed
5971
    cascade = None
5972 5973
    constant_result = constant_value_not_set # FIXME: where to calculate this?

Robert Bradshaw's avatar
Robert Bradshaw committed
5974 5975 5976 5977 5978 5979 5980
    def infer_type(self, env):
        # TODO: Actually implement this (after merging with -unstable).
        return py_object_type

    def type_dependencies(self, env):
        return ()

5981 5982 5983 5984
    def has_constant_result(self):
        return self.constant_result is not constant_value_not_set and \
               self.constant_result is not not_a_constant

5985
    def analyse_types(self, env):
William Stein's avatar
William Stein committed
5986 5987
        self.operand2.analyse_types(env)
        if self.cascade:
5988
            self.cascade.analyse_types(env)
5989

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

6021 6022 6023 6024 6025
    def annotate(self, code):
        self.operand2.annotate(code)
        if self.cascade:
            self.cascade.annotate(code)

William Stein's avatar
William Stein committed
6026 6027

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

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

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

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


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.

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

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

    def calculate_constant_result(self):
        # FIXME
        pass

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

    def free_temps(self, code):
        self.arg.free_temps(code)
6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168


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

6169 6170 6171
    def may_be_none(self):
        return False

6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182
    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
6183 6184
            StringEncoding.escape_byte_string(
                self.exception_message.encode('UTF-8')),
6185 6186 6187 6188 6189 6190 6191 6192 6193
            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)

6194

William Stein's avatar
William Stein committed
6195 6196 6197
class CoerceToPyTypeNode(CoercionNode):
    #  This node is used to convert a C data type
    #  to a Python object.
6198 6199
    
    type = py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
6200
    is_temp = 1
William Stein's avatar
William Stein committed
6201

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

6212
    gil_message = "Converting to Python object"
6213

6214 6215 6216 6217
    def may_be_none(self):
        # FIXME: is this always safe?
        return False

6218
    def coerce_to_boolean(self, env):
6219
        return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
6220 6221 6222 6223 6224 6225 6226
    
    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)
6227

6228 6229 6230 6231
    def analyse_types(self, env):
        # The arg is always already analysed
        pass

William Stein's avatar
William Stein committed
6232 6233
    def generate_result_code(self, code):
        function = self.arg.type.to_py_function
Robert Bradshaw's avatar
Robert Bradshaw committed
6234
        code.putln('%s = %s(%s); %s' % (
6235
            self.result(), 
William Stein's avatar
William Stein committed
6236
            function, 
6237 6238
            self.arg.result(), 
            code.error_goto_if_null(self.result(), self.pos)))
6239
        code.put_gotref(self.py_result())
William Stein's avatar
William Stein committed
6240 6241


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


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

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


class CoerceToBooleanNode(CoercionNode):
    #  This node is used when a result needs to be used
    #  in a boolean context.
    
6319
    type = PyrexTypes.c_bint_type
6320 6321 6322 6323

    _special_builtins = {
        Builtin.list_type    : 'PyList_GET_SIZE',
        Builtin.tuple_type   : 'PyTuple_GET_SIZE',
6324
        Builtin.bytes_type   : 'PyBytes_GET_SIZE',
6325 6326 6327
        Builtin.unicode_type : 'PyUnicode_GET_SIZE',
        }

William Stein's avatar
William Stein committed
6328 6329 6330 6331
    def __init__(self, arg, env):
        CoercionNode.__init__(self, arg)
        if arg.type.is_pyobject:
            self.is_temp = 1
6332

6333
    def nogil_check(self, env):
6334
        if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
6335
            self.gil_error()
6336

6337
    gil_message = "Truth-testing Python object"
William Stein's avatar
William Stein committed
6338 6339 6340 6341
    
    def check_const(self):
        if self.is_temp:
            self.not_const()
6342 6343
            return False
        return self.arg.check_const()
William Stein's avatar
William Stein committed
6344 6345
    
    def calculate_result_code(self):
6346
        return "(%s != 0)" % self.arg.result()
William Stein's avatar
William Stein committed
6347 6348

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

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

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
6397
        self.constant_result = self.arg.constant_result
William Stein's avatar
William Stein committed
6398 6399 6400
        self.is_temp = 1
        if self.type.is_pyobject:
            self.result_ctype = py_object_type
6401 6402 6403

    gil_message = "Creating temporary Python reference"

6404 6405 6406
    def analyse_types(self, env):
        # The arg is always already analysed
        pass
6407 6408 6409
        
    def coerce_to_boolean(self, env):
        self.arg = self.arg.coerce_to_boolean(env)
6410 6411
        if self.arg.is_simple():
            return self.arg
6412 6413 6414
        self.type = self.arg.type
        self.result_ctype = self.type
        return self
6415

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


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

Robert Bradshaw's avatar
Robert Bradshaw committed
6453 6454 6455 6456
    def analyse_types(self, env):
        self.type = self.arg.type
        self.result_ctype = self.arg.result_ctype
        self.is_temp = 1
6457 6458
        if hasattr(self.arg, 'entry'):
            self.entry = self.arg.entry
William Stein's avatar
William Stein committed
6459 6460 6461 6462 6463 6464
    
    def generate_evaluation_code(self, code):
        pass

    def generate_result_code(self, code):
        pass
6465
        
6466
    def generate_disposal_code(self, code):
6467 6468
        pass
                
6469 6470
    def free_temps(self, code):
        pass
6471

6472

6473 6474 6475 6476 6477 6478 6479 6480 6481 6482
class ModuleRefNode(ExprNode):
    # Simple returns the module object
    
    type = py_object_type
    is_temp = False
    subexprs = []
    
    def analyse_types(self, env):
        pass

6483 6484 6485
    def may_be_none(self):
        return False

6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513
    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
6514 6515 6516 6517 6518 6519
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

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

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

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

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

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

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

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

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

6644 6645
create_class_utility_code = UtilityCode(
proto = """
6646
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6647 6648
""",
impl = """
William Stein's avatar
William Stein committed
6649
static PyObject *__Pyx_CreateClass(
6650
    PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
William Stein's avatar
William Stein committed
6651 6652 6653
{
    PyObject *py_modname;
    PyObject *result = 0;
6654

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

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

6677 6678
cpp_exception_utility_code = UtilityCode(
proto = """
6679 6680
#ifndef __Pyx_CppExn2PyErr
static void __Pyx_CppExn2PyErr() {
Robert Bradshaw's avatar
Robert Bradshaw committed
6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696
  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");
  }
}
6697
#endif
6698 6699 6700
""",
impl = ""
)
Robert Bradshaw's avatar
Robert Bradshaw committed
6701 6702

#------------------------------------------------------------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
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 6734 6735 6736 6737 6738
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 = """

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

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

6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794
getitem_int_pyunicode_utility_code = UtilityCode(
proto = '''
#define __Pyx_GetItemInt_Unicode(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                               __Pyx_GetItemInt_Unicode_Fast(o, i) : \\
                                               __Pyx_GetItemInt_Generic(o, to_py_func(i)))

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

static CYTHON_INLINE Py_UNICODE __Pyx_GetItemInt_Unicode_Generic(PyObject* ustring, PyObject* j) {
    PyObject *r;
    Py_UNICODE uchar;
    if (!j) return (Py_UNICODE)-1;
    r = PyObject_GetItem(ustring, j);
    Py_DECREF(j);
    if (!r) return (Py_UNICODE)-1;
    uchar = PyUnicode_AS_UNICODE(r)[0];
    Py_DECREF(r);
    return uchar;
}
''',
)

6795 6796
getitem_int_utility_code = UtilityCode(
proto = """
6797

6798
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6799
    PyObject *r;
6800
    if (!j) return NULL;
6801 6802 6803 6804
    r = PyObject_GetItem(o, j);
    Py_DECREF(j);
    return r;
}
6805

6806 6807
""" + ''.join([
"""
6808 6809
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
6810 6811
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

6812
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
6813
    if (likely(o != Py_None)) {
6814
        if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6815 6816 6817 6818
            PyObject *r = Py%(type)s_GET_ITEM(o, i);
            Py_INCREF(r);
            return r;
        }
6819
        else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6820
            PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6821 6822 6823
            Py_INCREF(r);
            return r;
        }
6824
    }
6825
    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
6826
}
6827 6828
""" % {'type' : type_name} for type_name in ('List', 'Tuple')
]) + """
6829

6830 6831
#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_GetItemInt_Fast(o, i) : \\
6832 6833
                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))

6834
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6835
    PyObject *r;
6836
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6837 6838 6839
        r = PyList_GET_ITEM(o, i);
        Py_INCREF(r);
    }
6840
    else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6841 6842 6843
        r = PyTuple_GET_ITEM(o, i);
        Py_INCREF(r);
    }
6844
    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
6845
        r = PySequence_GetItem(o, i);
6846
    }
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6847
    else {
6848
        r = __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6849 6850 6851 6852
    }
    return r;
}
""",
6853 6854
impl = """
""")
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6855

6856 6857


Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6858 6859
#------------------------------------------------------------------------------------

6860 6861
setitem_int_utility_code = UtilityCode(
proto = """
6862 6863
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_SetItemInt_Fast(o, i, v) : \\
6864 6865
                                                    __Pyx_SetItemInt_Generic(o, to_py_func(i), v))

6866
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6867
    int r;
6868 6869 6870 6871 6872 6873
    if (!j) return -1;
    r = PyObject_SetItem(o, j, v);
    Py_DECREF(j);
    return r;
}

6874
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
6875
    if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6876
        Py_INCREF(v);
6877
        Py_DECREF(PyList_GET_ITEM(o, i));
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6878 6879 6880
        PyList_SET_ITEM(o, i, v);
        return 1;
    }
6881 6882
    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
6883
    else {
6884
        PyObject *j = PyInt_FromSsize_t(i);
6885
        return __Pyx_SetItemInt_Generic(o, j, v);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
6886 6887 6888
    }
}
""",
6889 6890 6891
impl = """
""")

6892 6893
#------------------------------------------------------------------------------------

6894 6895
delitem_int_utility_code = UtilityCode(
proto = """
6896 6897
#define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
                                                    __Pyx_DelItemInt_Fast(o, i) : \\
6898 6899
                                                    __Pyx_DelItem_Generic(o, to_py_func(i)))

6900
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6901
    int r;
6902 6903 6904 6905 6906 6907
    if (!j) return -1;
    r = PyObject_DelItem(o, j);
    Py_DECREF(j);
    return r;
}

6908
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
6909 6910
    if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
        return PySequence_DelItem(o, i);
6911
    else {
6912
        PyObject *j = PyInt_FromSsize_t(i);
6913
        return __Pyx_DelItem_Generic(o, j);
6914 6915 6916 6917 6918 6919 6920 6921
    }
}
""",
impl = """
""")

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

6922 6923
raise_too_many_values_to_unpack = UtilityCode(
proto = """
6924
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void);
6925 6926
""",
impl = '''
6927
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) {
6928 6929 6930 6931 6932 6933
    PyErr_SetString(PyExc_ValueError, "too many values to unpack");
}
''')

raise_need_more_values_to_unpack = UtilityCode(
proto = """
6934
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6935 6936
""",
impl = '''
6937
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949
    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");
}
''')

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

6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969
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]
)

6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001
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
7002

7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014
#------------------------------------------------------------------------------------

# 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;
7015
    if (likely(PyDict_Check(kwargs))) {
7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029
        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
7030 7031 7032 7033 7034

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

int_pow_utility_code = UtilityCode(
proto="""
7035
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
7036 7037
""",
impl="""
7038
static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
Robert Bradshaw's avatar
Robert Bradshaw committed
7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059
    %(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;
}
""")
7060 7061 7062

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

7063 7064
div_int_utility_code = UtilityCode(
proto="""
7065
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
7066 7067
""",
impl="""
7068
static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
7069 7070
    %(type)s q = a / b;
    %(type)s r = a - q*b;
7071
    q -= ((r != 0) & ((r ^ b) < 0));
7072 7073
    return q;
}
7074 7075
""")

7076
mod_int_utility_code = UtilityCode(
7077
proto="""
7078
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7079 7080
""",
impl="""
7081
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7082
    %(type)s r = a %% b;
7083
    r += ((r != 0) & ((r ^ b) < 0)) * b;
7084
    return r;
7085 7086 7087
}
""")

7088
mod_float_utility_code = UtilityCode(
7089
proto="""
7090
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
7091 7092
""",
impl="""
7093
static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
7094
    %(type)s r = fmod%(math_h_modifier)s(a, b);
7095
    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
7096
    return r;
7097 7098
}
""")
Robert Bradshaw's avatar
Robert Bradshaw committed
7099

7100
cdivision_warning_utility_code = UtilityCode(
Robert Bradshaw's avatar
Robert Bradshaw committed
7101
proto="""
7102
static int __Pyx_cdivision_warning(void); /* proto */
Robert Bradshaw's avatar
Robert Bradshaw committed
7103 7104
""",
impl="""
7105 7106 7107 7108 7109
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,
7110
                              __Pyx_MODULE_NAME,
7111
                              NULL);
Robert Bradshaw's avatar
Robert Bradshaw committed
7112
}
7113 7114 7115 7116
""" % {
    'FILENAME': Naming.filename_cname,
    'LINENO':  Naming.lineno_cname,
})
7117 7118 7119 7120 7121

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