Commit 3d32b841 authored by Robert Bradshaw's avatar Robert Bradshaw

HTML source annotation module

parent fdae4c23
...@@ -25,6 +25,7 @@ Options: ...@@ -25,6 +25,7 @@ Options:
--incref-local-binop Force local an extra incref on local variables before --incref-local-binop Force local an extra incref on local variables before
performing any binary operations. performing any binary operations.
-D, --no-docstrings Remove docstrings. -D, --no-docstrings Remove docstrings.
-a, --annotate Produce an colorized version of the source.
""" """
#The following experimental options are supported only on MacOSX: #The following experimental options are supported only on MacOSX:
# -C, --compile Compile generated .c file to .o file # -C, --compile Compile generated .c file to .o file
...@@ -85,6 +86,8 @@ def parse_command_line(args): ...@@ -85,6 +86,8 @@ def parse_command_line(args):
Options.generate_cleanup_code = int(pop_arg()) Options.generate_cleanup_code = int(pop_arg())
elif option in ("-D", "--no-docstrings"): elif option in ("-D", "--no-docstrings"):
Options.docstrings = False Options.docstrings = False
elif option in ("-a", "--annotate"):
Options.annotate = True
else: else:
bad_usage() bad_usage()
else: else:
......
...@@ -96,6 +96,8 @@ class CCodeWriter: ...@@ -96,6 +96,8 @@ class CCodeWriter:
return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4] return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
def mark_pos(self, pos): def mark_pos(self, pos):
# if self.marker is not None:
# print "new marker"
file, line, col = pos file, line, col = pos
contents = self.file_contents(file) contents = self.file_contents(file)
......
...@@ -12,6 +12,7 @@ import PyrexTypes ...@@ -12,6 +12,7 @@ import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type from PyrexTypes import py_object_type, c_long_type, typecast, error_type
import Symtab import Symtab
import Options import Options
from Annotate import AnnotationItem
from Cython.Debugging import print_call_chain from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \ from DebugFlags import debug_disposal_code, debug_temp_alloc, \
...@@ -404,6 +405,7 @@ class ExprNode(Node): ...@@ -404,6 +405,7 @@ class ExprNode(Node):
code.put_incref(self.result_code, self.ctype()) code.put_incref(self.result_code, self.ctype())
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
code.mark_pos(self.pos)
# Generate code to evaluate this node and # Generate code to evaluate this node and
# its sub-expressions, and dispose of any # its sub-expressions, and dispose of any
# temporary results of its sub-expressions. # temporary results of its sub-expressions.
...@@ -456,6 +458,12 @@ class ExprNode(Node): ...@@ -456,6 +458,12 @@ class ExprNode(Node):
# will have been reported earlier. # will have been reported earlier.
pass pass
# ---------------- Annotation ---------------------
def annotate(self, code):
for node in self.subexpr_nodes():
node.annotate(code)
# ----------------- Coercion ---------------------- # ----------------- Coercion ----------------------
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
...@@ -970,6 +978,14 @@ class NameNode(AtomicExprNode): ...@@ -970,6 +978,14 @@ class NameNode(AtomicExprNode):
Naming.module_cname, Naming.module_cname,
self.entry.name)) self.entry.name))
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)))
class BackquoteNode(ExprNode): class BackquoteNode(ExprNode):
# `expr` # `expr`
...@@ -1971,6 +1987,12 @@ class AttributeNode(ExprNode): ...@@ -1971,6 +1987,12 @@ class AttributeNode(ExprNode):
error(self.pos, "Cannot delete C attribute of extension type") error(self.pos, "Cannot delete C attribute of extension type")
self.obj.generate_disposal_code(code) self.obj.generate_disposal_code(code)
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)))
#------------------------------------------------------------------- #-------------------------------------------------------------------
# #
# Constructor nodes # Constructor nodes
...@@ -2090,6 +2112,15 @@ class SequenceNode(ExprNode): ...@@ -2090,6 +2112,15 @@ class SequenceNode(ExprNode):
code.putln("}") code.putln("}")
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)
class TupleNode(SequenceNode): class TupleNode(SequenceNode):
# Tuple constructor. # Tuple constructor.
...@@ -2177,6 +2208,9 @@ class ListComprehensionNode(SequenceNode): ...@@ -2177,6 +2208,9 @@ class ListComprehensionNode(SequenceNode):
code.error_goto_if_null(self.result_code, self.pos))) code.error_goto_if_null(self.result_code, self.pos)))
self.loop.generate_execution_code(code) self.loop.generate_execution_code(code)
def annotate(self, code):
self.loop.annotate(code)
class ListComprehensionAppendNode(ExprNode): class ListComprehensionAppendNode(ExprNode):
...@@ -2250,6 +2284,10 @@ class DictNode(ExprNode): ...@@ -2250,6 +2284,10 @@ class DictNode(ExprNode):
key.generate_disposal_code(code) key.generate_disposal_code(code)
value.generate_disposal_code(code) value.generate_disposal_code(code)
def annotate(self, code):
for key, value in self.key_value_pairs:
key.annotate(code)
value.annotate(code)
class ClassNode(ExprNode): class ClassNode(ExprNode):
# Helper class used in the implementation of Python # Helper class used in the implementation of Python
...@@ -3322,6 +3360,12 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -3322,6 +3360,12 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1.generate_disposal_code(code) self.operand1.generate_disposal_code(code)
self.operand2.generate_disposal_code(code) self.operand2.generate_disposal_code(code)
def annotate(self, code):
self.operand1.annotate(code)
self.operand2.annotate(code)
if self.cascade:
self.cascade.annotate(code)
class CascadedCmpNode(Node, CmpNode): class CascadedCmpNode(Node, CmpNode):
# A CascadedCmpNode is not a complete expression node. It # A CascadedCmpNode is not a complete expression node. It
...@@ -3385,6 +3429,11 @@ class CascadedCmpNode(Node, CmpNode): ...@@ -3385,6 +3429,11 @@ class CascadedCmpNode(Node, CmpNode):
self.operand2.generate_disposal_code(code) self.operand2.generate_disposal_code(code)
code.putln("}") code.putln("}")
def annotate(self, code):
self.operand2.annotate(code)
if self.cascade:
self.cascade.annotate(code)
binop_node_classes = { binop_node_classes = {
"or": BoolBinopNode, "or": BoolBinopNode,
...@@ -3435,6 +3484,12 @@ class CoercionNode(ExprNode): ...@@ -3435,6 +3484,12 @@ class CoercionNode(ExprNode):
if debug_coercion: if debug_coercion:
print self, "Coercing", self.arg print self, "Coercing", self.arg
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)))
class CastNode(CoercionNode): class CastNode(CoercionNode):
# Wrap a node in a C type cast. # Wrap a node in a C type cast.
......
...@@ -6,6 +6,7 @@ import os, time ...@@ -6,6 +6,7 @@ import os, time
from cStringIO import StringIO from cStringIO import StringIO
from PyrexTypes import CPtrType from PyrexTypes import CPtrType
import Annotate
import Code import Code
import Naming import Naming
import Nodes import Nodes
...@@ -200,6 +201,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -200,6 +201,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_c_code(self, env, result): def generate_c_code(self, env, result):
modules = self.referenced_modules modules = self.referenced_modules
if Options.annotate:
code = Annotate.AnnotationCCodeWriter(StringIO())
else:
code = Code.CCodeWriter(StringIO()) code = Code.CCodeWriter(StringIO())
code.h = Code.CCodeWriter(StringIO()) code.h = Code.CCodeWriter(StringIO())
code.init_labels() code.init_labels()
...@@ -233,6 +237,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -233,6 +237,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
f.write(code.f.getvalue()) f.write(code.f.getvalue())
f.close() f.close()
result.c_file_generated = 1 result.c_file_generated = 1
if Options.annotate:
self.annotate(code)
code.save_annotation(result.c_file[:-1] + "pyx") # change?
def find_referenced_modules(self, env, module_list, modules_seen): def find_referenced_modules(self, env, module_list, modules_seen):
if env not in modules_seen: if env not in modules_seen:
...@@ -388,6 +395,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -388,6 +395,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
return header, footer return header, footer
def generate_struct_union_definition(self, entry, code): def generate_struct_union_definition(self, entry, code):
code.mark_pos(entry.pos)
type = entry.type type = entry.type
scope = type.scope scope = type.scope
if scope: if scope:
...@@ -407,6 +415,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -407,6 +415,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(footer) code.putln(footer)
def generate_enum_definition(self, entry, code): def generate_enum_definition(self, entry, code):
code.mark_pos(entry.pos)
type = entry.type type = entry.type
name = entry.cname or entry.name or "" name = entry.cname or entry.name or ""
header, footer = \ header, footer = \
...@@ -450,6 +459,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -450,6 +459,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# code.putln("staticforward PyTypeObject %s;" % name) # code.putln("staticforward PyTypeObject %s;" % name)
def generate_exttype_vtable_struct(self, entry, code): def generate_exttype_vtable_struct(self, entry, code):
code.mark_pos(entry.pos)
# Generate struct declaration for an extension type's vtable. # Generate struct declaration for an extension type's vtable.
type = entry.type type = entry.type
scope = type.scope scope = type.scope
...@@ -470,6 +480,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -470,6 +480,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"};") "};")
def generate_exttype_vtabptr_declaration(self, entry, code): def generate_exttype_vtabptr_declaration(self, entry, code):
code.mark_pos(entry.pos)
# Generate declaration of pointer to an extension type's vtable. # Generate declaration of pointer to an extension type's vtable.
type = entry.type type = entry.type
if type.vtabptr_cname: if type.vtabptr_cname:
...@@ -478,6 +489,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -478,6 +489,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.vtabptr_cname)) type.vtabptr_cname))
def generate_obj_struct_definition(self, type, code): def generate_obj_struct_definition(self, type, code):
code.mark_pos(type.pos)
# Generate object struct definition for an # Generate object struct definition for an
# extension type. # extension type.
if not type.scope: if not type.scope:
......
...@@ -84,6 +84,13 @@ class Node: ...@@ -84,6 +84,13 @@ class Node:
raise InternalError("generate_code not implemented for %s" % \ raise InternalError("generate_code not implemented for %s" % \
self.__class__.__name__) self.__class__.__name__)
def annotate(self, code):
# mro does the wrong thing
if isinstance(self, BlockNode):
self.body.annotate(code)
else:
print "skipping", self
class BlockNode: class BlockNode:
# Mixin class for nodes representing a declaration block. # Mixin class for nodes representing a declaration block.
...@@ -161,6 +168,10 @@ class StatListNode(Node): ...@@ -161,6 +168,10 @@ class StatListNode(Node):
code.mark_pos(stat.pos) code.mark_pos(stat.pos)
stat.generate_execution_code(code) stat.generate_execution_code(code)
def annotate(self, code):
for stat in self.stats:
stat.annotate(code)
class StatNode(Node): class StatNode(Node):
# #
...@@ -201,6 +212,9 @@ class CDefExternNode(StatNode): ...@@ -201,6 +212,9 @@ class CDefExternNode(StatNode):
def generate_execution_code(self, code): def generate_execution_code(self, code):
pass pass
def annotate(self, code):
self.body.annotate(code)
class CDeclaratorNode(Node): class CDeclaratorNode(Node):
# Part of a C declaration. # Part of a C declaration.
...@@ -303,6 +317,8 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -303,6 +317,8 @@ class CFuncDeclaratorNode(CDeclaratorNode):
# nogil boolean Can be called without gil # nogil boolean Can be called without gil
# with_gil boolean Acquire gil around function body # with_gil boolean Acquire gil around function body
overridable = 0
def analyse(self, return_type, env): def analyse(self, return_type, env):
func_type_args = [] func_type_args = []
for arg_node in self.args: for arg_node in self.args:
...@@ -373,6 +389,10 @@ class CArgDeclNode(Node): ...@@ -373,6 +389,10 @@ class CArgDeclNode(Node):
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
return self.declarator.analyse(base_type, env) return self.declarator.analyse(base_type, env)
def annotate(self, code):
if self.default:
self.default.annotate(code)
class CBaseTypeNode(Node): class CBaseTypeNode(Node):
# Abstract base class for C base type nodes. # Abstract base class for C base type nodes.
...@@ -599,6 +619,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -599,6 +619,7 @@ class FuncDefNode(StatNode, BlockNode):
return 0 return 0
def generate_function_definitions(self, env, code): def generate_function_definitions(self, env, code):
code.mark_pos(self.pos)
# Generate C code for header and body of function # Generate C code for header and body of function
genv = env.global_scope() genv = env.global_scope()
lenv = LocalScope(name = self.entry.name, outer_scope = genv) lenv = LocalScope(name = self.entry.name, outer_scope = genv)
...@@ -1579,6 +1600,10 @@ class CClassDefNode(StatNode): ...@@ -1579,6 +1600,10 @@ class CClassDefNode(StatNode):
if self.body: if self.body:
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
def annotate(self, code):
if self.body:
self.body.annotate(code)
class PropertyNode(StatNode): class PropertyNode(StatNode):
# Definition of a property in an extension type. # Definition of a property in an extension type.
...@@ -1604,6 +1629,9 @@ class PropertyNode(StatNode): ...@@ -1604,6 +1629,9 @@ class PropertyNode(StatNode):
def generate_execution_code(self, code): def generate_execution_code(self, code):
pass pass
def annotate(self, code):
self.body.annotate(code)
class GlobalNode(StatNode): class GlobalNode(StatNode):
# Global variable declaration. # Global variable declaration.
...@@ -1636,6 +1664,9 @@ class ExprStatNode(StatNode): ...@@ -1636,6 +1664,9 @@ class ExprStatNode(StatNode):
code.putln("%s;" % self.expr.result_code) code.putln("%s;" % self.expr.result_code)
self.expr.generate_disposal_code(code) self.expr.generate_disposal_code(code)
def annotate(self, code):
self.expr.annotate(code)
class AssignmentNode(StatNode): class AssignmentNode(StatNode):
# Abstract base class for assignment nodes. # Abstract base class for assignment nodes.
...@@ -1705,6 +1736,10 @@ class SingleAssignmentNode(AssignmentNode): ...@@ -1705,6 +1736,10 @@ class SingleAssignmentNode(AssignmentNode):
def generate_assignment_code(self, code): def generate_assignment_code(self, code):
self.lhs.generate_assignment_code(self.rhs, code) self.lhs.generate_assignment_code(self.rhs, code)
def annotate(self, code):
self.lhs.annotate(code)
self.rhs.annotate(code)
class CascadedAssignmentNode(AssignmentNode): class CascadedAssignmentNode(AssignmentNode):
# An assignment with multiple left hand sides: # An assignment with multiple left hand sides:
...@@ -1781,6 +1816,13 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -1781,6 +1816,13 @@ class CascadedAssignmentNode(AssignmentNode):
# Assignment has disposed of the cloned RHS # Assignment has disposed of the cloned RHS
self.rhs.generate_disposal_code(code) self.rhs.generate_disposal_code(code)
def annotate(self, code):
for i in range(len(self.lhs_list)):
lhs = self.lhs_list[i].annotate(code)
rhs = self.coerced_rhs_list[i].annotate(code)
self.rhs.annotate(code)
class ParallelAssignmentNode(AssignmentNode): class ParallelAssignmentNode(AssignmentNode):
# A combined packing/unpacking assignment: # A combined packing/unpacking assignment:
# #
...@@ -1818,6 +1860,11 @@ class ParallelAssignmentNode(AssignmentNode): ...@@ -1818,6 +1860,11 @@ class ParallelAssignmentNode(AssignmentNode):
for stat in self.stats: for stat in self.stats:
stat.generate_assignment_code(code) stat.generate_assignment_code(code)
def annotate(self, code):
for stat in self.stats:
stat.annotate(code)
class InPlaceAssignmentNode(AssignmentNode): class InPlaceAssignmentNode(AssignmentNode):
# An in place arithmatic operand: # An in place arithmatic operand:
# #
...@@ -1922,6 +1969,11 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -1922,6 +1969,11 @@ class InPlaceAssignmentNode(AssignmentNode):
"%": "PyNumber_InPlaceRemainder", "%": "PyNumber_InPlaceRemainder",
} }
def annotate(self, code):
self.lhs.annotate(code)
self.rhs.annotate(code)
self.dup.annotate(code)
class PrintStatNode(StatNode): class PrintStatNode(StatNode):
# print statement # print statement
...@@ -1953,6 +2005,10 @@ class PrintStatNode(StatNode): ...@@ -1953,6 +2005,10 @@ class PrintStatNode(StatNode):
"if (__Pyx_PrintNewline() < 0) %s" % "if (__Pyx_PrintNewline() < 0) %s" %
code.error_goto(self.pos)) code.error_goto(self.pos))
def annotate(self, code):
for arg in self.args:
arg.annotate(code)
class DelStatNode(StatNode): class DelStatNode(StatNode):
# del statement # del statement
...@@ -1976,6 +2032,10 @@ class DelStatNode(StatNode): ...@@ -1976,6 +2032,10 @@ class DelStatNode(StatNode):
arg.generate_deletion_code(code) arg.generate_deletion_code(code)
# else error reported earlier # else error reported earlier
def annotate(self, code):
for arg in self.args:
arg.annotate(code)
class PassStatNode(StatNode): class PassStatNode(StatNode):
# pass statement # pass statement
...@@ -2049,6 +2109,7 @@ class ReturnStatNode(StatNode): ...@@ -2049,6 +2109,7 @@ class ReturnStatNode(StatNode):
error(self.pos, "Return value required") error(self.pos, "Return value required")
def generate_execution_code(self, code): def generate_execution_code(self, code):
code.mark_pos(self.pos)
if not self.return_type: if not self.return_type:
# error reported earlier # error reported earlier
return return
...@@ -2075,6 +2136,10 @@ class ReturnStatNode(StatNode): ...@@ -2075,6 +2136,10 @@ class ReturnStatNode(StatNode):
# code.return_label) # code.return_label)
code.put_goto(code.return_label) code.put_goto(code.return_label)
def annotate(self, code):
if self.value:
self.value.annotate(code)
class RaiseStatNode(StatNode): class RaiseStatNode(StatNode):
# raise statement # raise statement
...@@ -2141,6 +2206,14 @@ class RaiseStatNode(StatNode): ...@@ -2141,6 +2206,14 @@ class RaiseStatNode(StatNode):
code.putln( code.putln(
code.error_goto(self.pos)) code.error_goto(self.pos))
def annotate(self, code):
if self.exc_type:
self.exc_type.annotate(code)
if self.exc_value:
self.exc_value.annotate(code)
if self.exc_tb:
self.exc_tb.annotate(code)
class ReraiseStatNode(StatNode): class ReraiseStatNode(StatNode):
...@@ -2195,6 +2268,12 @@ class AssertStatNode(StatNode): ...@@ -2195,6 +2268,12 @@ class AssertStatNode(StatNode):
self.cond.generate_disposal_code(code) self.cond.generate_disposal_code(code)
code.putln("#endif") code.putln("#endif")
def annotate(self, code):
self.cond.annotate(code)
if self.value:
self.value.annotate(code)
class IfStatNode(StatNode): class IfStatNode(StatNode):
# if statement # if statement
# #
...@@ -2214,6 +2293,7 @@ class IfStatNode(StatNode): ...@@ -2214,6 +2293,7 @@ class IfStatNode(StatNode):
self.else_clause.analyse_expressions(env) self.else_clause.analyse_expressions(env)
def generate_execution_code(self, code): def generate_execution_code(self, code):
code.mark_pos(self.pos)
end_label = code.new_label() end_label = code.new_label()
for if_clause in self.if_clauses: for if_clause in self.if_clauses:
if_clause.generate_execution_code(code, end_label) if_clause.generate_execution_code(code, end_label)
...@@ -2223,6 +2303,12 @@ class IfStatNode(StatNode): ...@@ -2223,6 +2303,12 @@ class IfStatNode(StatNode):
code.putln("}") code.putln("}")
code.put_label(end_label) code.put_label(end_label)
def annotate(self, code):
for if_clause in self.if_clauses:
if_clause.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
class IfClauseNode(Node): class IfClauseNode(Node):
# if or elif clause in an if statement # if or elif clause in an if statement
...@@ -2253,6 +2339,10 @@ class IfClauseNode(Node): ...@@ -2253,6 +2339,10 @@ class IfClauseNode(Node):
code.put_goto(end_label) code.put_goto(end_label)
code.putln("}") code.putln("}")
def annotate(self, code):
self.condition.annotate(code)
self.body.annotate(code)
class WhileStatNode(StatNode): class WhileStatNode(StatNode):
# while statement # while statement
...@@ -2294,6 +2384,12 @@ class WhileStatNode(StatNode): ...@@ -2294,6 +2384,12 @@ class WhileStatNode(StatNode):
code.putln("}") code.putln("}")
code.put_label(break_label) code.put_label(break_label)
def annotate(self, code):
self.condition.annotate(code)
self.body.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
def ForStatNode(pos, **kw): def ForStatNode(pos, **kw):
if kw.has_key('iterator'): if kw.has_key('iterator'):
...@@ -2351,6 +2447,14 @@ class ForInStatNode(StatNode): ...@@ -2351,6 +2447,14 @@ class ForInStatNode(StatNode):
code.put_label(break_label) code.put_label(break_label)
self.iterator.generate_disposal_code(code) self.iterator.generate_disposal_code(code)
def annotate(self, code):
self.target.annotate(code)
self.iterator.annotate(code)
self.body.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
self.item.annotate(code)
class ForFromStatNode(StatNode): class ForFromStatNode(StatNode):
# for name from expr rel name rel expr # for name from expr rel name rel expr
...@@ -2469,6 +2573,16 @@ class ForFromStatNode(StatNode): ...@@ -2469,6 +2573,16 @@ class ForFromStatNode(StatNode):
'>' : ("-1", "--") '>' : ("-1", "--")
} }
def annotate(self, code):
self.target.annotate(code)
self.bound1.annotate(code)
self.bound2.annotate(code)
if self.step:
self.bound2.annotate(code)
self.body.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
class TryExceptStatNode(StatNode): class TryExceptStatNode(StatNode):
# try .. except statement # try .. except statement
...@@ -2524,6 +2638,13 @@ class TryExceptStatNode(StatNode): ...@@ -2524,6 +2638,13 @@ class TryExceptStatNode(StatNode):
code.put_goto(code.error_label) code.put_goto(code.error_label)
code.put_label(end_label) code.put_label(end_label)
def annotate(self, code):
self.body.annotate(code)
for except_node in self.except_clauses:
except_node.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
class ExceptClauseNode(Node): class ExceptClauseNode(Node):
# Part of try ... except statement. # Part of try ... except statement.
...@@ -2597,6 +2718,12 @@ class ExceptClauseNode(Node): ...@@ -2597,6 +2718,12 @@ class ExceptClauseNode(Node):
code.putln( code.putln(
"}") "}")
def annotate(self, code):
self.pattern.annotate(code)
if self.target:
self.target.annotate(code)
self.body.annotate(code)
class TryFinallyStatNode(StatNode): class TryFinallyStatNode(StatNode):
# try ... finally statement # try ... finally statement
...@@ -2763,6 +2890,10 @@ class TryFinallyStatNode(StatNode): ...@@ -2763,6 +2890,10 @@ class TryFinallyStatNode(StatNode):
code.putln( code.putln(
"}") "}")
def annotate(self, code):
self.body.annotate(code)
self.finally_clause.annotate(code)
class GILStatNode(TryFinallyStatNode): class GILStatNode(TryFinallyStatNode):
# 'with gil' or 'with nogil' statement # 'with gil' or 'with nogil' statement
......
...@@ -20,3 +20,5 @@ incref_local_binop = 0 ...@@ -20,3 +20,5 @@ incref_local_binop = 0
# Decref global variables in this module on exit for garbage collection. # Decref global variables in this module on exit for garbage collection.
# 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects # 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects
generate_cleanup_code = 1 generate_cleanup_code = 1
annotate = 0
\ No newline at end of file
...@@ -847,6 +847,7 @@ class ModuleScope(Scope): ...@@ -847,6 +847,7 @@ class ModuleScope(Scope):
# #
if not entry: if not entry:
type = PyExtensionType(name, typedef_flag, base_type) type = PyExtensionType(name, typedef_flag, base_type)
type.pos = pos
if visibility == 'extern': if visibility == 'extern':
type.module_name = module_name type.module_name = module_name
else: else:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment