-
Notifications
You must be signed in to change notification settings - Fork 0
/
loader_gui.py
193 lines (165 loc) · 6.01 KB
/
loader_gui.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import tkinter as tk
from loader_sim import *
try:
import pyperclip
except ImportError:
print("Install pyperclip if you want to use the clipboard functionality")
fileHandle = open("loader.c", "r")
loaderc = fileHandle.read()
fileHandle.close()
# Line numbers in loader.c for each of the stages where the program seeks a bit
stage_lines = {
'warmup': 45,
'loop': 45,
'apply': 51,
'new-var': 53,
'abstract': 57,
'make-lambda': 59,
'scope': 63}
loaderc_lines = loaderc.split('\n')
#loaderc_d = '\n'.join(loaderc_lines[:8] + ['...'] + loaderc_lines[38:-3])
loaderc_d = '\n'.join(loaderc_lines[39:-4])
for stage in stage_lines:
stage_lines[stage] -= 39
class LoaderGUI:
def __init__(self, parent):
self.parent = parent
self.panes = tk.Frame(parent)
self.panes.pack()
self.mainFrame = tk.Frame(self.panes)
self.mainFrame.pack(side=tk.LEFT)
seperator = tk.Frame(self.panes, width=2, bd=1, relief=tk.SUNKEN);
seperator.pack(side=tk.LEFT, fill=tk.Y, padx=2)
self.program = LineFocus(self.panes, stage_lines['warmup'],
text=loaderc_d)
self.program.pack(side=tk.LEFT)
#self.program.line_configure(3, foreground='red')
seperator = tk.Frame(self.panes, width=2, bd=1, relief=tk.SUNKEN);
seperator.pack(side=tk.LEFT, fill=tk.Y, padx=2)
self.stackSpace = tk.Frame(self.panes)
self.stackSpace.pack(side=tk.LEFT)
self.bin = ""
self.binLabel = tk.Label(self.mainFrame, text=self.bin,
justify=tk.RIGHT, anchor=tk.E)
self.binLabel.pack(side=tk.TOP)
self.buttonFrame = tk.Frame(self.mainFrame)
self.buttonFrame.pack(side=tk.TOP)
self.b0 = tk.Button(self.buttonFrame, command=self.p0, text="0")
self.b0.pack(side=tk.LEFT)
self.b1 = tk.Button(self.buttonFrame, command=self.p1, text="1")
self.b1.pack(side=tk.LEFT)
self.undo = tk.Button(self.buttonFrame, command=self.undo, text="Undo")
self.undo.pack(side=tk.LEFT)
self.copy = tk.Button(self.buttonFrame, command=self.copy_to_clipboard,
text="Copy to clipboard")
self.copy.pack(side=tk.LEFT)
self.quit = tk.Button(self.buttonFrame, command=self.mainFrame.quit,
text="Quit")
self.quit.pack(side=tk.LEFT)
self.logtext = "TEST\n"
self.logBox = tk.Label(self.mainFrame, text=self.logtext)
#self.logBox.pack(side=tk.TOP)
self.state = tk.Label(self.mainFrame, text='')
self.state.pack(side=tk.TOP)
self.stack = GUIStack(self.stackSpace)
self.backend = interactive_parse(self.stack, self.log)
self.state.configure(text=next(self.backend))
def copy_to_clipboard(self):
pyperclip.copy(self.bin)
def p0(self):
self.add_bit(0)
def p1(self):
self.add_bit(1)
def add_bit(self, bit, update_gui=True):
self.bin = str(bit) + self.bin
if (len(self.bin) + 1) % 61 == 0:
self.bin = "\n" + self.bin
new_state = self.backend.send(bit > 0)
if update_gui:
self.update_gui(new_state)
return new_state
def update_gui(self, new_state):
self.labelUpdate()
self.program.set_focus(stage_lines[new_state])
self.state.configure(text=new_state)
t = self.stack.top()
self.stack.update()
def labelUpdate(self):
self.binLabel.configure(text=self.bin)
def log(self, out):
self.logtext += out + "\n"
self.logBox.configure(text=self.logtext)
print(out)
def undo(self):
"""This implementation is ugly"""
newbin = self.bin.strip()[1:]
self.bin = ""
self.stack.list = []
self.backend = interactive_parse(self.stack, self.log)
state = next(self.backend)
for c in reversed(newbin):
if c == "\n":
continue
state = self.add_bit(int(c), update_gui=False)
self.update_gui(state)
class TextLines:
def __init__(self, parent, text=''):
self.parent = parent
self.text = text
self.frame = tk.Frame(self.parent)
self.lines = []
for l in self.text.split('\n'):
line = tk.Label(self.frame, text=l, anchor=tk.E)
line.pack(side=tk.TOP, anchor=tk.W)
self.lines.append(line)
def pack(self, *arg, **kw):
self.frame.pack(*arg, **kw)
def line_configure(self, ln, **kw):
self.lines[ln].configure(**kw)
class LineFocus(TextLines):
def __init__(self, parent, focus, *arg, **kw):
TextLines.__init__(self, parent, *arg, **kw)
self.focus = focus
self.line_configure(focus, foreground='red')
def set_focus(self, focus):
#assert focus >= 0
prev_focus = self.focus
if prev_focus == focus:
return
else:
self.line_configure(prev_focus, foreground='black')
self.line_configure(focus, foreground='red')
self.focus = focus
class GUIStack(Stack):
def __init__(self, parent):
Stack.__init__(self)
self.parent = parent
self.label = tk.Label(self.parent)
self.label.pack(side=tk.TOP)
self.update()
#self.history = [self.copy()]
def do_and_update(func):
def new_func(self, *arg, **key):
res = func(self, *arg, **key)
self.update()
return res
return new_func
push = do_and_update(Stack.push)
pop = do_and_update(Stack.pop)
def update(self):
objs = []
for t in self:
t_str = show_judgement(t)
# Add indentation
t_str_ind = t_str[:100]
t_str = t_str[100:]
while len(t_str) > 0:
t_str_ind = t_str_ind + "\n\t" + t_str[:100]
t_str = t_str[100:]
objs.append(t_str_ind)
txt = '\n'.join(objs)
self.label.configure(text=txt)
if __name__ == "__main__":
root = tk.Tk()
loadergui = LoaderGUI(root)
root.mainloop()