-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpile.py
139 lines (113 loc) · 4.54 KB
/
pile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/bin/python
# PyOberon 0.1 - Oberon 07 compiler (re-)written in Python
# Copyright (C) 2016 John "The Blue Wizard" Rogers
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Pile data structure
# (should now be usable for records, scopes, blocks and modules)
# Each entry of 'layers' is a pair: a list containing
# some information about that layer (the first entry
# MUST be a reference to an item), and a list of items
# (which in the simplest case can be strings or number).
# Note: The concept of level or activation is NOT explicitly
# encoded. In my PyOberon compiler, level info is obtained
# by getting second item (after the reference).
# To get a stack-like snapshot, use the
# get_stack_image() method, with appropriate layer
# indexing as its parameter if desired.
class Layer:
def __init__(self, parent=[None,None]):
self.parent = parent
self.items = []
def add(self, item):
self.items.append(item)
def find(self, etc):
pass
class Pile:
def __init__(self):
# create first usable layer
# make a list containing first pair representing the first layer
self.layers = [ Layer() ]
self.active_layers = [0] # make it refer to first working layer
def get_current_layer(self):
return self.active_layers[-1]
def get_current_position(self):
# returns the current position being worked on
working_layer = self.get_current_layer()
working_index = len(self.layers[working_layer].items)-1
return [working_layer, working_index]
def open_sublayer(self):
# add a new layer, with some linkbacks
new_layer = Layer(self.get_current_position())
self.layers.append(new_layer)
# mark new layer as the current active one
self.active_layers.append(len(self.layers)-1)
def close_sublayer(self):
# return old "current" information
return self.active_layers.pop()
def add(self, item):
working_layer = self.get_current_layer()
self.layers[working_layer].add(item)
def find(self, item, seek=lambda _list,obj:_list.index(obj), next=lambda layer,index: [layer,index]):
search_layer = self.get_current_layer()
while search_layer != None:
try:
return search_layer, seek(self.layers[search_layer].items, item)
except ValueError:
parent_layer, parent_index = self.layers[search_layer].parent
if parent_layer == None:
search_layer = None
else:
search_layer, search_index = next(parent_layer, parent_index)
return [None, None]
def get_stack_image(self, layer=None):
# create and return a stack-like image
stack = []
if layer == None:
layer = self.get_current_layer()
index = len(self.layers[layer].items)-1
while layer != None:
stack.insert(0, self.layers[layer].items[:index+1])
layer, index = self.layers[layer].parent
return stack
### quick testing suite
if __name__ == '__main__':
test = '''\
system oberon object
( version fixorg code data
Put0 ( op a b c temp )
Put1 ( op a b imm )
FixLink ( L | L1 )
record ( parent | f1 f2 f3 )
Big ( a1 a2 | m1 m2 m3
Little ( b1 b2 | g1 g2 )
stuff
)
morerecord ( | j1 j2 j3 j4 )
) main
'''.split()
p = Pile()
for t in test:
if t == '(':
p.open_sublayer()
elif t == ')':
junk = p.close_sublayer()
elif t == '|':
junk = p.close_sublayer()
p.open_sublayer()
else:
p.add(t)
# verify that it indeed gives a sequence of stack-like
# behavior in semi-chronological order:
for pl in range(len(p.layers)):
print 'Stack at:', pl, p.get_stack_image(layer=pl)
for k in 'main oberon data system xyz'.split():
print p.find(k)