-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.py
221 lines (188 loc) · 8.23 KB
/
app.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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
"""
Abstract Machine Interpreter
CSC615M - Automata, Computability, and Formal Languages
Sir Ryan Austin Fernandez
Project by:
@author Adriel Isaiah V. Amoguis
"""
# Dependency Imports
import sys, os, time
from threading import Thread
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QPlainTextEdit, QLineEdit, QGroupBox, QFormLayout, QPushButton, QLayout, QCheckBox
from PyQt6.QtGui import QPixmap, QFontDatabase
from PyQt6 import QtCore
# Module Imports
from input_parser import InputParser
from abstract_simulator import AbstractMachineSimulator
from abstract_grapher import graph_abstract_machine
# Main App
app = QApplication(sys.argv)
# Components
window = QWidget()
window.setWindowTitle("Abstract Machine Interpreter")
window.setGeometry(100, 100, 640, 480)
# Handler Functions
def log(message):
output_console.appendPlainText(message)
machine_instance = None
def update_memory_inspector():
global machine_instance
global memory_inspector
try:
memory_inspector.clear()
# Input Tape
memory_inspector.appendPlainText("Input Tape: " + str(machine_instance.input_tape))
memory_inspector.appendPlainText("Tape Head: " + str(" " * machine_instance.input_tape.head) + " ^")
memory_inspector.appendPlainText("")
# Display current state
memory_inspector.appendPlainText("Current State: " + str(machine_instance.current_state or list(machine_instance.state_map.keys())[0]))
memory_inspector.appendPlainText("")
if len(machine_instance.memory.keys()) < 1:
memory_inspector.appendPlainText("No auxiliary memory used.")
for key in machine_instance.memory.keys():
memory_inspector.appendPlainText(str(machine_instance.aux_data[key]["type"]) + " " + key + ": " + str(machine_instance.memory[key]))
memory_inspector.appendPlainText("")
# Output Tape
out = "".join(machine_instance.output)
memory_inspector.appendPlainText("Output Buffer: " + out)
memory_inspector.appendPlainText("")
# Machine States
memory_inspector.appendPlainText("Halted State: " + str(machine_instance.halted))
memory_inspector.appendPlainText("Accept State: " + str(machine_instance.accepted))
# Update the machine graph
graph_abstract_machine(machine_instance.logic, machine_instance.current_state)
machine_graph.setPixmap(QPixmap("./graph_abstract_machine.png").scaled(600, 600, aspectRatioMode=QtCore.Qt.AspectRatioMode.KeepAspectRatio, transformMode=QtCore.Qt.TransformationMode.SmoothTransformation))
os.remove("./graph_abstract_machine.png")
except Exception as e:
log("Error: " + str(e))
def compile_machine():
global machine_instance
# Clear the output log
output_console.clear()
try:
parser = InputParser(machine_description.toPlainText())
machine_instance = AbstractMachineSimulator(parser.parse())
graph_abstract_machine(machine_instance.logic)
machine_graph.setPixmap(QPixmap("./graph_abstract_machine.png").scaled(600, 600, aspectRatioMode=QtCore.Qt.AspectRatioMode.KeepAspectRatio, transformMode=QtCore.Qt.TransformationMode.SmoothTransformation))
os.remove("./graph_abstract_machine.png")
btn_step_machine.setDisabled(False)
btn_slow_run.setDisabled(False)
btn_run_machine.setDisabled(False)
log("Machine Compiled Successfully.")
# Check if aux memory has a tape
is_turing_machine = False
for key in machine_instance.aux_data.keys():
if machine_instance.aux_data[key]["type"] == "TAPE":
is_turing_machine = True
break
machine_instance.set_input_tape(input_tape.text(), is_turing_machine=is_turing_machine)
if is_turing_machine: log("Turing machine detected. Input tape set to first aux memory tape.")
log("Using input tape: " + str(machine_instance.input_tape))
update_memory_inspector()
except Exception as e:
log("Error: " + str(e))
def step_machine():
global machine_instance
try:
# Check if machine is halted
if machine_instance.halted:
log("Machine is halted.")
return
machine_instance.step(verbose=verbose_checkbox.isChecked(), logger=log)
log("Machine stepped successfully.")
update_memory_inspector()
except Exception as e:
log("Error: " + str(e))
def run_machine():
global machine_instance
try:
# Check if machine is halted
if machine_instance.halted:
log("Machine is halted.")
return
machine_instance.run(verbose=verbose_checkbox.isChecked(), logger=log)
log("Machine ran successfully.")
update_memory_inspector()
except Exception as e:
log("Error: " + str(e))
def slow_run_machine():
global machine_instance
global step_machine
try:
# Run the "step_machine" function in a separate thread
def run():
while not machine_instance.halted:
step_machine()
time.sleep(0.5)
Thread(target=run).start()
except Exception as e:
log("Error: " + str(e))
# Interactable Components
machine_description = QPlainTextEdit()
machine_description.resize(600, 1000)
machine_description.setPlainText("""// This is a comment.
.LOGIC
A] SCAN RIGHT (0,A), (1,B), (#,accept)
B] SCAN LEFT (0,C), (1,reject)
C] SCAN RIGHT (1,A)""")
monospaced_font = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
monospaced_font.setPointSize(12)
machine_description.setFont(monospaced_font)
machine_description.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
execution_panel = QGroupBox("Execution Panel")
verbose_checkbox = QCheckBox("Verbose Execution")
input_tape = QLineEdit()
input_tape.setPlaceholderText("#aaabbbccc12344321#")
input_tape.setText("##")
monospaced_font2 = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
monospaced_font2.setPointSize(18)
input_tape.setFont(monospaced_font2)
btn_compile_machine = QPushButton("Compile / Reset Machine")
btn_compile_machine.clicked.connect(compile_machine)
btn_step_machine = QPushButton("Step Machine")
btn_step_machine.clicked.connect(step_machine)
btn_slow_run = QPushButton("Slowly Run Machine")
btn_slow_run.clicked.connect(slow_run_machine)
btn_run_machine = QPushButton("Run Machine")
btn_run_machine.clicked.connect(run_machine)
btn_step_machine.setDisabled(True)
btn_slow_run.setDisabled(True)
btn_run_machine.setDisabled(True)
execution_panel_layout = QFormLayout()
execution_panel_layout.addRow(QLabel("Input Tape:"), input_tape)
execution_panel_layout.addRow(verbose_checkbox)
execution_panel_layout.addRow(btn_compile_machine)
execution_panel_layout.addRow(btn_step_machine)
execution_panel_layout.addRow(btn_slow_run)
execution_panel_layout.addRow(btn_run_machine)
execution_panel_layout.setSizeConstraint(QLayout.SizeConstraint.SetNoConstraint)
execution_panel.setLayout(execution_panel_layout)
machine_graph = QLabel()
machine_graph.setPixmap(QPixmap("./sample.png").scaled(600, 600, aspectRatioMode=QtCore.Qt.AspectRatioMode.KeepAspectRatio, transformMode=QtCore.Qt.TransformationMode.SmoothTransformation))
output_console = QPlainTextEdit()
output_console.setReadOnly(True)
output_console.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
output_console.setFont(monospaced_font)
output_console.setPlainText("""Abstract Machine Interpreter by Adriel Isaiah Amoguis (v1)
Compile a machine to get started.""")
memory_inspector = QPlainTextEdit()
memory_inspector.setReadOnly(True)
memory_inspector.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
memory_inspector.setFont(monospaced_font)
# Layout Manager
layout = QGridLayout()
# Widgets
layout.addWidget(QLabel("Enter Machine Description below:"), 0, 0)
layout.addWidget(machine_description, 1, 0, 7, 12)
layout.addWidget(execution_panel, 8, 0, 8, 12)
layout.addWidget(QLabel("Machine Graph:"), 0, 13)
layout.addWidget(machine_graph, 1, 13, 15, 20)
layout.addWidget(QLabel("Output Console:"), 17, 0)
layout.addWidget(output_console, 18, 0, 20, 16)
layout.addWidget(QLabel("Memory Inspector:"), 17, 17)
layout.addWidget(memory_inspector, 18, 17, 20, 20)
# Show Window
window.setLayout(layout)
window.show()
# Run Event Loop
sys.exit(app.exec())