1.1 --- a/lib/builtins.py Mon Sep 06 01:08:58 2010 +0200
1.2 +++ b/lib/builtins.py Tue Sep 07 01:07:23 2010 +0200
1.3 @@ -427,7 +427,25 @@
1.4 def hex(number): pass
1.5 def id(obj): pass
1.6 def input(prompt=None): pass
1.7 -def isinstance(obj, cls_or_tuple): pass
1.8 +
1.9 +def isinstance(obj, cls_or_tuple):
1.10 +
1.11 + """
1.12 + Return whether 'obj' is an instance of 'cls_or_tuple', where the latter is
1.13 + either a class or a tuple of classes.
1.14 + """
1.15 +
1.16 + # NOTE: tuple.__class__ is tuple in micropython!
1.17 + if cls_or_tuple is not tuple and cls_or_tuple.__class__ is tuple:
1.18 + for cls in cls_or_tuple:
1.19 + if _isinstance(obj, cls):
1.20 + return True
1.21 + return False
1.22 + else:
1.23 + return _isinstance(obj, cls_or_tuple)
1.24 +
1.25 +def _isinstance(obj, cls): pass
1.26 +
1.27 def issubclass(obj, cls_or_tuple): pass
1.28
1.29 def iter(collection):
2.1 --- a/micropython/data.py Mon Sep 06 01:08:58 2010 +0200
2.2 +++ b/micropython/data.py Tue Sep 07 01:07:23 2010 +0200
2.3 @@ -421,17 +421,13 @@
2.4 with the given 'attrname'.
2.5 """
2.6
2.7 - for users in (self.attribute_users[-1], self.loop_users[-1]):
2.8 -
2.9 - # Add the usage to all current users.
2.10 -
2.11 - if users.has_key(name):
2.12 - for user in users[name]:
2.13 - user._attrnames[name].add(attrname)
2.14 -
2.15 users = self.attribute_users[-1]
2.16
2.17 + # Add the usage to all current users.
2.18 +
2.19 if users.has_key(name):
2.20 + for user in users[name]:
2.21 + user._attrnames[name].add(attrname)
2.22 return users[name]
2.23 else:
2.24 return []
2.25 @@ -461,6 +457,8 @@
2.26 self._init_attribute_user_for_name(node, name)
2.27
2.28 # Propagate any loop usage forward to any redefinition of a name.
2.29 + # This models the name acquiring the existing usage as it remains active
2.30 + # upon starting a new iteration.
2.31
2.32 loop_users = self.loop_users[-1]
2.33
2.34 @@ -494,37 +492,43 @@
2.35 self.user_shelves.append([])
2.36 self.scope_shelves.append([])
2.37
2.38 - def _new_branch(self, loop_node=None):
2.39 + def _new_branch(self, node, loop=0):
2.40
2.41 """
2.42 Establish a new control-flow branch, transferring attribute usage to
2.43 the new branch so that it may be augmented for each name locally.
2.44
2.45 - If the optional 'loop_node' is given, add it as an active user to be
2.46 - informed of attribute usage.
2.47 + Add the given 'node' as an active user to be informed of attribute
2.48 + usage.
2.49 """
2.50
2.51 + new_usage = {}
2.52 + new_users = {}
2.53 +
2.54 + # Define usage on this node based on current usage.
2.55 +
2.56 + for users in self.attribute_users[-1].values():
2.57 + for user in users:
2.58 + for name, usage in user._attrnames.items():
2.59 + if not new_usage.has_key(name):
2.60 + new_usage[name] = set(usage)
2.61 + else:
2.62 + new_usage[name] = new_usage[name].union(set(usage))
2.63 +
2.64 + # Set the usage on this node.
2.65 +
2.66 + node._attrnames = {}
2.67 +
2.68 + for name, usage in new_usage.items():
2.69 + node._attrnames[name] = usage
2.70 + new_users[name] = [node]
2.71 +
2.72 # Retain a record of active users.
2.73
2.74 - new_users = {}
2.75 - new_users.update(self.attribute_users[-1])
2.76 self.attribute_users.append(new_users)
2.77
2.78 - # Where a loop is the cause of the branch, register the loop node as a
2.79 - # user of each name so that attribute usage is also recorded for the
2.80 - # loop.
2.81 -
2.82 - loop_users = {}
2.83 - loop_users.update(self.loop_users[-1])
2.84 - self.loop_users.append(loop_users)
2.85 -
2.86 - if loop_node is not None:
2.87 - for name in new_users.keys():
2.88 - if not loop_users.has_key(name):
2.89 - loop_users[name] = set([loop_node])
2.90 - else:
2.91 - loop_users[name] = loop_users[name].union([loop_node])
2.92 - self._init_attribute_user_for_name(loop_node, name)
2.93 + if loop:
2.94 + self.loop_users.append(new_users)
2.95
2.96 # Retain a record of scope usage.
2.97
2.98 @@ -532,6 +536,10 @@
2.99 scope_usage.update(self.scope_usage[-1])
2.100 self.scope_usage.append(scope_usage)
2.101
2.102 + # Remember this user.
2.103 +
2.104 + self.all_attribute_users.add(node)
2.105 +
2.106 def _abandon_branch(self):
2.107
2.108 """
2.109 @@ -556,7 +564,7 @@
2.110 scope_usage = self.scope_usage.pop()
2.111 self.scope_shelves[-1].append(scope_usage)
2.112
2.113 - def _merge_branches(self):
2.114 + def _merge_branches(self, loop=0):
2.115
2.116 """
2.117 Merge control-flow branches. This should find the users active within
2.118 @@ -567,6 +575,9 @@
2.119 # Combine the attribute users. This ensures that a list of users
2.120 # affected by attribute usage is maintained for the current branch.
2.121
2.122 + if loop:
2.123 + self.loop_users.pop()
2.124 +
2.125 users = self.attribute_users[-1]
2.126 new_users = {}
2.127
3.1 --- a/micropython/inspect.py Mon Sep 06 01:08:58 2010 +0200
3.2 +++ b/micropython/inspect.py Tue Sep 07 01:07:23 2010 +0200
3.3 @@ -350,8 +350,8 @@
3.4 def new_branchpoint(self):
3.5 self.get_namespace()._new_branchpoint()
3.6
3.7 - def new_branch(self, loop_node=None):
3.8 - self.get_namespace()._new_branch(loop_node)
3.9 + def new_branch(self, node, loop=0):
3.10 + self.get_namespace()._new_branch(node, loop)
3.11
3.12 def abandon_branch(self):
3.13 self.get_namespace()._abandon_branch()
3.14 @@ -359,8 +359,8 @@
3.15 def shelve_branch(self):
3.16 self.get_namespace()._shelve_branch()
3.17
3.18 - def merge_branches(self):
3.19 - self.get_namespace()._merge_branches()
3.20 + def merge_branches(self, loop=0):
3.21 + self.get_namespace()._merge_branches(loop)
3.22
3.23 def define_attribute_user(self, node):
3.24
3.25 @@ -786,21 +786,20 @@
3.26 # Enter the loop.
3.27 # Propagate attribute usage to branches.
3.28
3.29 - self.new_branch(node)
3.30 + self.new_branch(node, 1)
3.31 self.dispatch(node.body)
3.32 self.shelve_branch()
3.33
3.34 self.in_loop = in_loop
3.35
3.36 - # Maintain a branch for the else clause or the current retained usage
3.37 - # where execution avoids the conditional clauses.
3.38 + # Maintain a branch for the else clause.
3.39
3.40 - self.new_branch()
3.41 if node.else_ is not None:
3.42 + self.new_branch(node.else_)
3.43 self.dispatch(node.else_)
3.44 - self.shelve_branch()
3.45 + self.shelve_branch()
3.46
3.47 - self.merge_branches()
3.48 + self.merge_branches(1)
3.49 return None
3.50
3.51 def visitFrom(self, node):
3.52 @@ -866,17 +865,16 @@
3.53 for test, body in node.tests:
3.54 self.dispatch(test)
3.55
3.56 - self.new_branch()
3.57 + self.new_branch(body)
3.58 self.dispatch(body)
3.59 self.shelve_branch()
3.60
3.61 - # Maintain a branch for the else clause or the current retained usage
3.62 - # where execution avoids the conditional clauses.
3.63 + # Maintain a branch for the else clause.
3.64
3.65 - self.new_branch()
3.66 if node.else_ is not None:
3.67 + self.new_branch(node.else_)
3.68 self.dispatch(node.else_)
3.69 - self.shelve_branch()
3.70 + self.shelve_branch()
3.71
3.72 self.merge_branches()
3.73 return None
3.74 @@ -934,7 +932,7 @@
3.75 # Enter the loop.
3.76 # Propagate attribute usage to branches.
3.77
3.78 - self.new_branch(node)
3.79 + self.new_branch(node, 1)
3.80
3.81 for if_ in node.ifs:
3.82 self.dispatch(if_)
3.83 @@ -942,7 +940,7 @@
3.84 self.shelve_branch()
3.85 self.in_loop = in_loop
3.86
3.87 - self.merge_branches()
3.88 + self.merge_branches(1)
3.89 return None
3.90
3.91 visitListCompIf = NOP
3.92 @@ -1000,7 +998,7 @@
3.93 self.new_branchpoint()
3.94
3.95 for name, var, n in node.handlers:
3.96 - self.new_branch()
3.97 + self.new_branch(name)
3.98
3.99 # Establish the local for the handler.
3.100
3.101 @@ -1011,10 +1009,10 @@
3.102
3.103 self.shelve_branch()
3.104
3.105 - self.new_branch()
3.106 if node.else_ is not None:
3.107 + self.new_branch(node.else_)
3.108 self.dispatch(node.else_)
3.109 - self.shelve_branch()
3.110 + self.shelve_branch()
3.111
3.112 self.merge_branches()
3.113 return None
3.114 @@ -1035,19 +1033,18 @@
3.115 in_loop = self.in_loop
3.116 self.in_loop = 1
3.117 self.dispatch(node.test)
3.118 - self.new_branch(node)
3.119 + self.new_branch(node, 1)
3.120 self.dispatch(node.body)
3.121 self.shelve_branch()
3.122 self.in_loop = in_loop
3.123
3.124 - # Maintain a branch for the else clause or the current retained usage
3.125 - # where execution avoids the conditional clauses.
3.126 + # Maintain a branch for the else clause.
3.127 # NOTE: Consider merging here before the else clause.
3.128
3.129 - self.new_branch()
3.130 if node.else_ is not None:
3.131 + self.new_branch(node.else_)
3.132 self.dispatch(node.else_)
3.133 - self.shelve_branch()
3.134 + self.shelve_branch()
3.135
3.136 self.merge_branches()
3.137 return None
4.1 --- a/rsvplib.py Mon Sep 06 01:08:58 2010 +0200
4.2 +++ b/rsvplib.py Tue Sep 07 01:07:23 2010 +0200
4.3 @@ -453,6 +453,19 @@
4.4 def builtins_object_init(self):
4.5 pass
4.6
4.7 + def builtins_isinstance(self):
4.8 + frame = self.local_sp_stack[-1]
4.9 +
4.10 + # Get the operand addresses.
4.11 +
4.12 + obj_value = self.frame_stack[frame]
4.13 + cls_value = self.frame_stack[frame + 1]
4.14 +
4.15 + if self.machine._CheckInstance(obj_value.ref, cls_value.ref):
4.16 + self.machine.result = DataValue(self.constants[True], self.constants[True])
4.17 + else:
4.18 + self.machine.result = DataValue(self.constants[False], self.constants[False])
4.19 +
4.20 native_functions = {
4.21
4.22 # Native method implementations:
4.23 @@ -495,6 +508,10 @@
4.24 # Native instantiator helpers:
4.25
4.26 "__builtins__.list.__new__" : builtins_list_new,
4.27 +
4.28 + # Native helper functions:
4.29 +
4.30 + "__builtins__._isinstance" : builtins_isinstance,
4.31 }
4.32
4.33 # vim: tabstop=4 expandtab shiftwidth=4
5.1 --- a/tests/attribute_access_type_restriction_conditional_choice.py Mon Sep 06 01:08:58 2010 +0200
5.2 +++ b/tests/attribute_access_type_restriction_conditional_choice.py Tue Sep 07 01:07:23 2010 +0200
5.3 @@ -20,16 +20,15 @@
5.4
5.5 def test_conditional(obj):
5.6 # obj: C, D, E (f)
5.7 - if obj.f(): # C, D, E (f)
5.8 - obj.g() # D (f, g)
5.9 + if obj.f(): # C, D, E (f)
5.10 + return obj.g() # D (f, g)
5.11 else:
5.12 - obj.h() # E (f, h)
5.13 - # # (f, g) ^ (f, h)
5.14 - return 2
5.15 + return obj.h() # E (f, h)
5.16 + # # (f, g) ^ (f, h)
5.17
5.18 c = C()
5.19 d = D()
5.20 e = E()
5.21 -result1_2 = test_conditional(d)
5.22 +result1_3 = test_conditional(d)
5.23
5.24 # vim: tabstop=4 expandtab shiftwidth=4
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/tests/attribute_access_type_restriction_conditional_choice_incompatible.py Tue Sep 07 01:07:23 2010 +0200
6.3 @@ -0,0 +1,26 @@
6.4 +#!/usr/bin/env python
6.5 +
6.6 +class C:
6.7 + def f(self):
6.8 + return 0
6.9 +
6.10 +class D:
6.11 + def f(self):
6.12 + return 2
6.13 +
6.14 + def g(self):
6.15 + return 3
6.16 +
6.17 +def test_conditional(obj):
6.18 + # obj: C, D (f)
6.19 + if obj.f(): # C, D (f)
6.20 + return obj.g() # D (f, g)
6.21 + else:
6.22 + return obj.f() # C (f)
6.23 + # # (f, g) ^ (f)
6.24 +
6.25 +c = C()
6.26 +d = D()
6.27 +result1_0 = test_conditional(c)
6.28 +
6.29 +# vim: tabstop=4 expandtab shiftwidth=4