Final refractor
BIN
ColorError.png
Normal file
After Width: | Height: | Size: 788 B |
@ -1,4 +1,4 @@
|
|||||||
import interpreter.imageWrapper as imageWrapper
|
import interpreter.imageFunctions as imageWrapper
|
||||||
|
|
||||||
|
|
||||||
class canvasManager():
|
class canvasManager():
|
||||||
@ -6,29 +6,54 @@ class canvasManager():
|
|||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.image = image
|
self.image = image
|
||||||
self.programState = programState
|
self.programState = programState
|
||||||
|
self.previousProgramState = None
|
||||||
self.scaleSize = scaleSize
|
self.scaleSize = scaleSize
|
||||||
|
|
||||||
|
|
||||||
def updateImage(self, newImage):
|
def updateImage(self, newImage):
|
||||||
self.image = newImage
|
self.image = newImage
|
||||||
|
|
||||||
|
|
||||||
def updateScaleSize(self, scaleSize):
|
def updateScaleSize(self, scaleSize):
|
||||||
self.scaleSize = scaleSize
|
self.scaleSize = scaleSize
|
||||||
|
|
||||||
|
|
||||||
def updateProgramState(self, newProgramState):
|
def updateProgramState(self, newProgramState):
|
||||||
|
self.previousProgramState = self.programState
|
||||||
self.programState = newProgramState
|
self.programState = newProgramState
|
||||||
|
|
||||||
|
|
||||||
def pixelToHexString(self, pixel) -> str:
|
def pixelToHexString(self, pixel) -> str:
|
||||||
|
"""
|
||||||
|
Transforms the color of a pixel to hex-string
|
||||||
|
:param pixel: list with three values (RGB)
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
return '#%02x%02x%02x' %(pixel[0], pixel[1], pixel[2])
|
return '#%02x%02x%02x' %(pixel[0], pixel[1], pixel[2])
|
||||||
|
|
||||||
|
|
||||||
def updateCanvas(self):
|
def updateCanvas(self):
|
||||||
|
"""
|
||||||
|
Draws the canvas, then highlights the current codel. If a previous game state exists, it only reverses the highlight, instead of redrawing the entire canvas
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
if self.image is None or self.canvas is None or self.programState is None or self.scaleSize is None:
|
if self.image is None or self.canvas is None or self.programState is None or self.scaleSize is None:
|
||||||
|
print("one is not none")
|
||||||
return False
|
return False
|
||||||
self.drawImage()
|
|
||||||
|
if self.previousProgramState is None:
|
||||||
|
self.drawImage()
|
||||||
|
else:
|
||||||
|
self.unHighlightCodel()
|
||||||
self.highlightCodel()
|
self.highlightCodel()
|
||||||
# Draw breakpoint
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def drawImage(self):
|
def drawImage(self):
|
||||||
|
"""
|
||||||
|
Draw the image pixel for pixel, upscaled to the scaleSize.
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.clearCanvas()
|
self.clearCanvas()
|
||||||
for raw_y, row in enumerate(self.image):
|
for raw_y, row in enumerate(self.image):
|
||||||
for raw_x, pixel in enumerate(row):
|
for raw_x, pixel in enumerate(row):
|
||||||
@ -39,19 +64,56 @@ class canvasManager():
|
|||||||
|
|
||||||
|
|
||||||
def clearCanvas(self):
|
def clearCanvas(self):
|
||||||
width = self.canvas.winfo_width()
|
"""
|
||||||
height = self.canvas.winfo_height()
|
Draws a white rectangle over the canvas
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
width = len(self.image[0]) * self.scaleSize
|
||||||
|
height = len(self.image) * self.scaleSize
|
||||||
self.canvas.create_rectangle(0,0, width, height, fill="#FFFFFF")
|
self.canvas.create_rectangle(0,0, width, height, fill="#FFFFFF")
|
||||||
|
|
||||||
|
|
||||||
def highlightCodel(self):
|
def highlightCodel(self):
|
||||||
|
"""
|
||||||
|
Outlines the current codel with complemented colors
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
codel = imageWrapper.getCodel(self.image, self.programState.position)
|
codel = imageWrapper.getCodel(self.image, self.programState.position)
|
||||||
pixel = imageWrapper.getPixel(self.image, self.programState.position)
|
pixel = imageWrapper.getPixel(self.image, self.programState.position)
|
||||||
color = self.pixelToHexString(pixel)
|
color = self.pixelToHexString(pixel)
|
||||||
self.colorCodel(codel, color, "#000000")
|
outline = self.pixelToHexString(self.complement(int(pixel[0]), int(pixel[1]), int(pixel[2])))
|
||||||
|
self.colorCodel(codel, color, outline)
|
||||||
|
|
||||||
|
|
||||||
|
def unHighlightCodel(self):
|
||||||
|
codel = imageWrapper.getCodel(self.image, self.previousProgramState.position)
|
||||||
|
pixel = imageWrapper.getPixel(self.image, self.previousProgramState.position)
|
||||||
|
color = self.pixelToHexString(pixel)
|
||||||
|
self.colorCodel(codel, color, color)
|
||||||
|
|
||||||
|
|
||||||
def colorCodel(self, codel, fill, outline):
|
def colorCodel(self, codel, fill, outline):
|
||||||
for position in codel.codel:
|
for position in codel.codel:
|
||||||
x = position.coords[0] * self.scaleSize
|
x = position.coords[0] * self.scaleSize
|
||||||
y = position.coords[1] * self.scaleSize
|
y = position.coords[1] * self.scaleSize
|
||||||
self.canvas.create_rectangle(x,y, x+self.scaleSize - 1, y+self.scaleSize - 1, fill=fill, outline=outline)
|
self.canvas.create_rectangle(x,y, x+self.scaleSize - 1, y+self.scaleSize - 1, fill=fill, outline=outline)
|
||||||
|
|
||||||
|
|
||||||
|
def hilo(self, a, b, c):
|
||||||
|
"""
|
||||||
|
Credit to StackOverflow user 'PM 2Ring' for making this code.
|
||||||
|
"""
|
||||||
|
if c < b: b, c = c, b
|
||||||
|
if b < a: a, b = b, a
|
||||||
|
if c < b: b, c = c, b
|
||||||
|
return a + c
|
||||||
|
|
||||||
|
|
||||||
|
def complement(self, r, g, b):
|
||||||
|
"""
|
||||||
|
Credit to StackOverflow user 'PM 2Ring' for making this code.
|
||||||
|
"""
|
||||||
|
if r == 255 and g == 255 and b == 255:
|
||||||
|
return (0,0,0)
|
||||||
|
k = self.hilo(r, g, b)
|
||||||
|
return tuple(k - u for u in (r, g, b))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import interpreter.imageWrapper as imageWrapper
|
import interpreter.imageFunctions as imageWrapper
|
||||||
import interpreter.colors as colors
|
import interpreter.colors as colors
|
||||||
import interpreter.tokens as lexerTokens
|
import interpreter.tokens as lexerTokens
|
||||||
import interpreter.movement as movement
|
import interpreter.movementFunctions as movement
|
||||||
from interpreter.dataStructures import direction
|
from interpreter.dataStructures import direction
|
||||||
|
|
||||||
class infoManager():
|
class infoManager():
|
||||||
@ -15,26 +15,12 @@ class infoManager():
|
|||||||
self.updateProgramStateInfo(programState)
|
self.updateProgramStateInfo(programState)
|
||||||
|
|
||||||
def updateGeneralinfo(self, image, graph, programState):
|
def updateGeneralinfo(self, image, graph, programState):
|
||||||
self.updateCodelInfo(image, programState.position)
|
|
||||||
self.updateEdgesInfo(image, graph, programState)
|
self.updateEdgesInfo(image, graph, programState)
|
||||||
|
|
||||||
def updateProgramStateInfo(self, programState):
|
def updateProgramStateInfo(self, programState):
|
||||||
self.updateStackInfo(programState.dataStack)
|
self.updateStackInfo(programState.dataStack)
|
||||||
self.updatePointersInfo(programState.position, programState.direction)
|
self.updatePointersInfo(programState.position, programState.direction)
|
||||||
|
|
||||||
def updateCodelInfo(self, image, newPosition):
|
|
||||||
infoMessage = self.builder.get_object('positionInfoMessage', self.generalInfo)
|
|
||||||
if colors.isBlack(imageWrapper.getPixel(image, newPosition)):
|
|
||||||
infoMessage.configure(text="Black pixels are no codel, and have no edges")
|
|
||||||
return None
|
|
||||||
|
|
||||||
baseString = "Selected codel contains:\n"
|
|
||||||
codel = imageWrapper.getCodel(image, newPosition)
|
|
||||||
for position in codel.codel:
|
|
||||||
baseString += "{}\n".format(position)
|
|
||||||
|
|
||||||
infoMessage.configure(text=baseString.strip('\n'))
|
|
||||||
|
|
||||||
|
|
||||||
def updateEdgesInfo(self, image, inputGraph, programState):
|
def updateEdgesInfo(self, image, inputGraph, programState):
|
||||||
edgesInfo = self.builder.get_object('codelEdgesMessage', self.generalInfo)
|
edgesInfo = self.builder.get_object('codelEdgesMessage', self.generalInfo)
|
||||||
|
108
GUI/main.py
@ -1,17 +1,10 @@
|
|||||||
# helloworld.py
|
|
||||||
import pygubu
|
import pygubu
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
sys.path.insert(0, "GUI/TKinter/.")
|
from interpreter import imageFunctions as imageWrapper
|
||||||
from interpreter import imageWrapper as imageWrapper
|
|
||||||
from interpreter import lexer as lexer
|
from interpreter import lexer as lexer
|
||||||
from interpreter import tokens as lexerTokens
|
from interpreter import executeFunctions as main
|
||||||
from interpreter import colors as colors
|
|
||||||
from interpreter import movement as movement
|
|
||||||
from interpreter import executionFunctions as main
|
|
||||||
from interpreter.dataStructures import programState, direction, position
|
from interpreter.dataStructures import programState, direction, position
|
||||||
import threading
|
|
||||||
|
|
||||||
from GUI import infoManager
|
from GUI import infoManager
|
||||||
from GUI import canvasManager
|
from GUI import canvasManager
|
||||||
@ -20,7 +13,7 @@ from GUI import canvasManager
|
|||||||
class GUI:
|
class GUI:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# In pixelWidth/height per pixel. scaleSize = 25 means that every pixel will show as a 25x25 square
|
# In pixelWidth/height per pixel. scaleSize = 25 means that every pixel will show as a 25x25 square
|
||||||
self.scaleSize = 25
|
self.scaleSize = 15
|
||||||
# In percentage
|
# In percentage
|
||||||
self.executionSpeed = 15
|
self.executionSpeed = 15
|
||||||
|
|
||||||
@ -38,13 +31,13 @@ class GUI:
|
|||||||
self.canvas = None
|
self.canvas = None
|
||||||
|
|
||||||
#1: Create a builder
|
#1: Create a builder
|
||||||
self.builder = builder = pygubu.Builder()
|
self.builder = pygubu.Builder()
|
||||||
|
|
||||||
#2: Load an ui file
|
#2: Load an ui file
|
||||||
builder.add_from_file("{}/tkinterLayout.ui".format(os.path.abspath(os.path.dirname(__file__))))
|
self.builder.add_from_file("{}/tkinterLayout.ui".format(os.path.abspath(os.path.dirname(__file__))))
|
||||||
|
|
||||||
#3: Create the mainwindow
|
#3: Create the mainwindow
|
||||||
self.mainwindow = builder.get_object('rootWindow')
|
self.mainwindow = self.builder.get_object('rootWindow')
|
||||||
|
|
||||||
self.initializeFrames()
|
self.initializeFrames()
|
||||||
self.initializeCallbacks()
|
self.initializeCallbacks()
|
||||||
@ -60,14 +53,16 @@ class GUI:
|
|||||||
self.builder.connect_callbacks({
|
self.builder.connect_callbacks({
|
||||||
'loadFile': self.loadFile,
|
'loadFile': self.loadFile,
|
||||||
'setScale': self.setScale,
|
'setScale': self.setScale,
|
||||||
'takeStep': self.takeStep,
|
'takeStep': self.takeStep
|
||||||
'setExecutionSpeed': self.setExecutionSpeed,
|
|
||||||
'setBreakpoint': self.setBreakpoint,
|
|
||||||
'runProgram': self.runProgram,
|
|
||||||
'updateHighlight': self.toggleHighlight
|
|
||||||
})
|
})
|
||||||
|
|
||||||
self.canvas.bind("<Button-1>", self.canvasPressed)
|
horizontalBar = self.builder.get_object("canvasHorizontalScroll", self.canvasFrame)
|
||||||
|
verticalBar = self.builder.get_object("canvasVerticalScroll", self.canvasFrame)
|
||||||
|
horizontalBar.config(command = self.canvas.xview)
|
||||||
|
verticalBar.config(command = self.canvas.yview)
|
||||||
|
self.canvas.config(xscrollcommand=horizontalBar.set, yscrollcommand=verticalBar.set)
|
||||||
|
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||||
|
|
||||||
|
|
||||||
def initializeFrames(self):
|
def initializeFrames(self):
|
||||||
self.optionBar = self.builder.get_object('optionBar', self.mainwindow)
|
self.optionBar = self.builder.get_object('optionBar', self.mainwindow)
|
||||||
@ -75,8 +70,8 @@ class GUI:
|
|||||||
self.actionBar = self.builder.get_object('actionBar', self.mainwindow)
|
self.actionBar = self.builder.get_object('actionBar', self.mainwindow)
|
||||||
self.generalInfoFrame = self.builder.get_object("generalInfoFrame", self.content)
|
self.generalInfoFrame = self.builder.get_object("generalInfoFrame", self.content)
|
||||||
self.programStateInfoFrame = self.builder.get_object("programStateInfoFrame", self.content)
|
self.programStateInfoFrame = self.builder.get_object("programStateInfoFrame", self.content)
|
||||||
canvasFrame = self.builder.get_object('canvasFrame', self.content)
|
self.canvasFrame = self.builder.get_object('canvasFrame', self.content)
|
||||||
self.canvas = self.builder.get_object('canvas', canvasFrame)
|
self.canvas = self.builder.get_object('canvas', self.canvasFrame)
|
||||||
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -85,6 +80,7 @@ class GUI:
|
|||||||
self.canvasManager.updateImage(self.image)
|
self.canvasManager.updateImage(self.image)
|
||||||
self.canvasManager.updateProgramState(self.programState)
|
self.canvasManager.updateProgramState(self.programState)
|
||||||
self.canvasManager.updateCanvas()
|
self.canvasManager.updateCanvas()
|
||||||
|
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||||
|
|
||||||
|
|
||||||
def takeStep(self):
|
def takeStep(self):
|
||||||
@ -92,77 +88,59 @@ class GUI:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
newProgramState = main.takeStep(self.image, self.programState)
|
newProgramState = main.takeStep(self.image, self.programState)
|
||||||
if isinstance(newProgramState, bool):
|
# Error encountered, close window
|
||||||
return False
|
if isinstance(newProgramState, BaseException):
|
||||||
|
self.mainwindow.destroy()
|
||||||
|
self.mainwindow.quit()
|
||||||
|
raise newProgramState
|
||||||
|
|
||||||
self.programState = newProgramState
|
self.programState = newProgramState
|
||||||
self.selectedPosition = self.programState.position
|
self.selectedPosition = self.programState.position
|
||||||
self.update()
|
self.update()
|
||||||
print("Take step!")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def setBreakpoint(self):
|
|
||||||
print("BREAKPOINT")
|
|
||||||
|
|
||||||
def setFileText(self, filePath):
|
def setFileText(self, filePath):
|
||||||
print("Filepath: {}".format(filePath))
|
|
||||||
self.builder.get_object("fileNameEntry", self.optionBar).delete(0, len(self.builder.get_object("fileNameEntry", self.optionBar).get()))
|
self.builder.get_object("fileNameEntry", self.optionBar).delete(0, len(self.builder.get_object("fileNameEntry", self.optionBar).get()))
|
||||||
self.builder.get_object("fileNameEntry", self.optionBar).insert(0, filePath)
|
self.builder.get_object("fileNameEntry", self.optionBar).insert(0, filePath)
|
||||||
print("Get filepath: {}".format(self.builder.get_object("fileNameEntry", self.optionBar).get()))
|
|
||||||
|
|
||||||
def setExecutionSpeed(self, pos):
|
def setExecutionSpeed(self, pos):
|
||||||
if 0 < float(pos) < 100:
|
if 0 < float(pos) < 100:
|
||||||
self.executionSpeed = float(pos)
|
self.executionSpeed = float(pos)
|
||||||
|
|
||||||
def toggleHighlight(self):
|
|
||||||
print(self.builder.get_object("highlightEdgeCheck", self.actionBar).instate(['selected']))
|
|
||||||
|
|
||||||
def getWaitTime(self):
|
|
||||||
return self.executionSpeed/100*self.maxWait
|
|
||||||
|
|
||||||
def runProgram(self):
|
|
||||||
if self.graph is None or self.image is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
step = self.takeStep()
|
|
||||||
if step:
|
|
||||||
timer = threading.Timer(self.getWaitTime(), self.runProgram)
|
|
||||||
timer.start()
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def setScale(self):
|
def setScale(self):
|
||||||
scaleValue = int(self.builder.get_object('scaleEntry', self.optionBar).get())
|
scaleValue = int(self.builder.get_object('scaleEntry', self.optionBar).get())
|
||||||
if 0 < scaleValue < 100:
|
if 0 < scaleValue < 100:
|
||||||
|
self.canvasManager.clearCanvas()
|
||||||
self.scaleSize = int(scaleValue)
|
self.scaleSize = int(scaleValue)
|
||||||
self.update()
|
self.update()
|
||||||
print("SCALE")
|
self.canvasManager.drawImage()
|
||||||
|
self.canvasManager.updateCanvas()
|
||||||
|
|
||||||
|
|
||||||
def loadFile(self):
|
def loadFile(self):
|
||||||
fileName = self.builder.get_object('fileNameEntry', self.optionBar).get()
|
fileName = self.builder.get_object('fileNameEntry', self.optionBar).get()
|
||||||
if len(fileName) < 1:
|
if len(fileName) < 1:
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
|
tmpImage = imageWrapper.getImage(fileName)
|
||||||
|
except FileNotFoundError:
|
||||||
|
edgeInfo = self.infoManager.builder.get_object('codelEdgesMessage', self.infoManager.generalInfo)
|
||||||
|
edgeInfo.configure(text="The file '{}' could not be found".format(fileName))
|
||||||
|
return False
|
||||||
|
|
||||||
self.image = imageWrapper.getImage(fileName)
|
tmpResult = lexer.graphImage(tmpImage)
|
||||||
self.graph = lexer.graphImage(self.image)[0]
|
if len(tmpResult[1]) != 0:
|
||||||
|
edgeInfo = self.infoManager.builder.get_object('codelEdgesMessage', self.infoManager.generalInfo)
|
||||||
|
edgeInfo.configure(text="The following exceptions occured while making the graph:\n{}".format("".join(list(map(lambda x: "\t{}\n".format(x), tmpResult[1])))))
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.image = tmpImage
|
||||||
|
self.graph = tmpResult[0]
|
||||||
self.programState = programState(self.graph, position((0,0)), direction((0,0)))
|
self.programState = programState(self.graph, position((0,0)), direction((0,0)))
|
||||||
|
# Reset previous state
|
||||||
|
self.canvasManager.previousProgramState = None
|
||||||
|
self.canvasManager.programState = None
|
||||||
self.update()
|
self.update()
|
||||||
print("LOAD FILE!")
|
|
||||||
|
|
||||||
|
|
||||||
def canvasPressed(self, event):
|
|
||||||
unscaled_x = int(event.x / self.scaleSize)
|
|
||||||
unscaled_y = int(event.y / self.scaleSize)
|
|
||||||
|
|
||||||
self.selectedPosition = (unscaled_x, unscaled_y)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app = GUI()
|
|
||||||
app.run()
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object id="scaleEntry" class="ttk.Entry">
|
<object id="scaleEntry" class="ttk.Entry">
|
||||||
<property name="text" translatable="yes">75</property>
|
<property name="text" translatable="yes">15</property>
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">3</property>
|
<property name="column">3</property>
|
||||||
<property name="ipady">2</property>
|
<property name="ipady">2</property>
|
||||||
@ -108,32 +108,6 @@
|
|||||||
</column>
|
</column>
|
||||||
</columns>
|
</columns>
|
||||||
</layout>
|
</layout>
|
||||||
<child>
|
|
||||||
<object id="runProgram" class="ttk.Button">
|
|
||||||
<property name="command">runProgram</property>
|
|
||||||
<property name="text" translatable="yes">Run program</property>
|
|
||||||
<layout>
|
|
||||||
<property name="column">0</property>
|
|
||||||
<property name="propagate">True</property>
|
|
||||||
<property name="row">0</property>
|
|
||||||
</layout>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object id="executionSpeed" class="ttk.Scale">
|
|
||||||
<property name="command">setExecutionSpeed</property>
|
|
||||||
<property name="from_">1</property>
|
|
||||||
<property name="orient">horizontal</property>
|
|
||||||
<property name="to">100</property>
|
|
||||||
<property name="value">15</property>
|
|
||||||
<property name="variable">int:pos</property>
|
|
||||||
<layout>
|
|
||||||
<property name="column">1</property>
|
|
||||||
<property name="propagate">True</property>
|
|
||||||
<property name="row">0</property>
|
|
||||||
</layout>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object id="takeStep" class="ttk.Button">
|
<object id="takeStep" class="ttk.Button">
|
||||||
<property name="command">takeStep</property>
|
<property name="command">takeStep</property>
|
||||||
@ -147,18 +121,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object id="highlightEdgeCheck" class="ttk.Checkbutton">
|
|
||||||
<property name="command">updateHighlight</property>
|
|
||||||
<property name="text" translatable="yes">Highlight edges</property>
|
|
||||||
<property name="variable">int:0</property>
|
|
||||||
<layout>
|
|
||||||
<property name="column">4</property>
|
|
||||||
<property name="propagate">True</property>
|
|
||||||
<property name="row">0</property>
|
|
||||||
</layout>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@ -213,31 +175,12 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object id="positionInfoMessage" class="tk.Message">
|
|
||||||
<property name="background">#ffffff</property>
|
|
||||||
<property name="highlightcolor">#a7a7a7</property>
|
|
||||||
<property name="highlightthickness">1</property>
|
|
||||||
<property name="text" translatable="yes">Selected codel contains the following positions:
|
|
||||||
- (0,0)
|
|
||||||
- (0,1)</property>
|
|
||||||
<property name="width">200</property>
|
|
||||||
<layout>
|
|
||||||
<property name="column">0</property>
|
|
||||||
<property name="padx">5</property>
|
|
||||||
<property name="propagate">True</property>
|
|
||||||
<property name="row">1</property>
|
|
||||||
</layout>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object id="codelEdgesMessage" class="tk.Message">
|
<object id="codelEdgesMessage" class="tk.Message">
|
||||||
<property name="background">#FFFFFF</property>
|
<property name="background">#FFFFFF</property>
|
||||||
<property name="highlightcolor">#a7a7a7</property>
|
<property name="highlightbackground">#39af36</property>
|
||||||
<property name="highlightthickness">1</property>
|
<property name="highlightthickness">1</property>
|
||||||
<property name="text" translatable="yes">Codel edges are as follows:
|
<property name="text" translatable="yes">Codel edges are as follows: </property>
|
||||||
|
|
||||||
(0,1) -> (1,0) push 0</property>
|
|
||||||
<property name="width">200</property>
|
<property name="width">200</property>
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">0</property>
|
<property name="column">0</property>
|
||||||
@ -246,17 +189,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object id="setBreakPoint" class="ttk.Button">
|
|
||||||
<property name="command">setBreakpoint</property>
|
|
||||||
<property name="text" translatable="yes">Set breakpoint</property>
|
|
||||||
<layout>
|
|
||||||
<property name="column">0</property>
|
|
||||||
<property name="propagate">True</property>
|
|
||||||
<property name="row">3</property>
|
|
||||||
</layout>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@ -286,6 +218,7 @@
|
|||||||
<object id="stackContents" class="tk.Message">
|
<object id="stackContents" class="tk.Message">
|
||||||
<property name="anchor">center</property>
|
<property name="anchor">center</property>
|
||||||
<property name="background">#ffffff</property>
|
<property name="background">#ffffff</property>
|
||||||
|
<property name="highlightbackground">#39af36</property>
|
||||||
<property name="highlightcolor">#a7a7a7</property>
|
<property name="highlightcolor">#a7a7a7</property>
|
||||||
<property name="highlightthickness">1</property>
|
<property name="highlightthickness">1</property>
|
||||||
<layout>
|
<layout>
|
||||||
@ -320,6 +253,8 @@
|
|||||||
<child>
|
<child>
|
||||||
<object id="pointerMessage" class="tk.Message">
|
<object id="pointerMessage" class="tk.Message">
|
||||||
<property name="background">#ffffff</property>
|
<property name="background">#ffffff</property>
|
||||||
|
<property name="highlightbackground">#39af36</property>
|
||||||
|
<property name="highlightthickness">1</property>
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">1</property>
|
<property name="column">1</property>
|
||||||
<property name="propagate">True</property>
|
<property name="propagate">True</property>
|
||||||
@ -337,6 +272,7 @@
|
|||||||
<property name="column">2</property>
|
<property name="column">2</property>
|
||||||
<property name="propagate">True</property>
|
<property name="propagate">True</property>
|
||||||
<property name="row">0</property>
|
<property name="row">0</property>
|
||||||
|
<property name="sticky">nw</property>
|
||||||
</layout>
|
</layout>
|
||||||
<child>
|
<child>
|
||||||
<object id="canvas" class="tk.Canvas">
|
<object id="canvas" class="tk.Canvas">
|
||||||
@ -353,26 +289,29 @@
|
|||||||
<property name="pady">5</property>
|
<property name="pady">5</property>
|
||||||
<property name="propagate">True</property>
|
<property name="propagate">True</property>
|
||||||
<property name="row">0</property>
|
<property name="row">0</property>
|
||||||
|
<property name="sticky">n</property>
|
||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object id="Scrollbar_1" class="ttk.Scrollbar">
|
<object id="canvasVerticalScroll" class="tk.Scrollbar">
|
||||||
<property name="orient">vertical</property>
|
<property name="orient">vertical</property>
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">1</property>
|
<property name="column">2</property>
|
||||||
<property name="propagate">True</property>
|
<property name="propagate">True</property>
|
||||||
<property name="row">0</property>
|
<property name="row">0</property>
|
||||||
|
<property name="sticky">ns</property>
|
||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object id="Scrollbar_2" class="ttk.Scrollbar">
|
<object id="canvasHorizontalScroll" class="tk.Scrollbar">
|
||||||
<property name="orient">horizontal</property>
|
<property name="orient">horizontal</property>
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">0</property>
|
<property name="column">0</property>
|
||||||
<property name="propagate">True</property>
|
<property name="propagate">True</property>
|
||||||
<property name="row">1</property>
|
<property name="row">1</property>
|
||||||
|
<property name="sticky">ew</property>
|
||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
BIN
Info/GUI layout.PNG
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
Info/poster.png
Before Width: | Height: | Size: 520 KiB After Width: | Height: | Size: 523 KiB |
BIN
Info/poster.xcf
0
__init__.py
Normal file
Before Width: | Height: | Size: 3.6 KiB |
BIN
countdown.png
Normal file
After Width: | Height: | Size: 613 B |
BIN
divideByZero.png
Normal file
After Width: | Height: | Size: 559 B |
BIN
endless.png
Normal file
After Width: | Height: | Size: 529 B |
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 354 B |
@ -2,7 +2,7 @@ from typing import Dict, Union
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import interpreter.errors as errors
|
from interpreter import errors as errors
|
||||||
|
|
||||||
class possiblePixels:
|
class possiblePixels:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -52,11 +52,10 @@ def getPixelChange(colorStart: np.ndarray, colorEnd: np.ndarray) -> Union[Dict[s
|
|||||||
return {"hueChange": 0, "lightChange": 0}
|
return {"hueChange": 0, "lightChange": 0}
|
||||||
|
|
||||||
pixelsColors = possiblePixels()
|
pixelsColors = possiblePixels()
|
||||||
# Converting np arrays to common lists
|
# Converting np arrays to normal lists
|
||||||
colorStart = list(colorStart)[:3]
|
colorStart = list(colorStart)[:3]
|
||||||
colorEnd = list(colorEnd)[:3]
|
colorEnd = list(colorEnd)[:3]
|
||||||
|
|
||||||
|
|
||||||
if colorStart not in pixelsColors.colors:
|
if colorStart not in pixelsColors.colors:
|
||||||
return errors.UnknownColorError("Color {} is not recognized as a correct color".format(colorStart))
|
return errors.UnknownColorError("Color {} is not recognized as a correct color".format(colorStart))
|
||||||
if colorEnd not in pixelsColors.colors:
|
if colorEnd not in pixelsColors.colors:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from typing import Set, Tuple, Dict, List
|
from typing import Set, Tuple, Dict, List
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import interpreter.tokens as tokens
|
from interpreter import tokens as tokens
|
||||||
|
|
||||||
class position():
|
class position():
|
||||||
"""
|
"""
|
||||||
@ -125,6 +125,9 @@ class graph():
|
|||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
class programState():
|
class programState():
|
||||||
|
"""
|
||||||
|
The program state contains the graph of the program, the position, direction and stack.
|
||||||
|
"""
|
||||||
def __init__(self, newGraph: graph, newPosition: position, newDirection: direction, dataStack: List[int] = None):
|
def __init__(self, newGraph: graph, newPosition: position, newDirection: direction, dataStack: List[int] = None):
|
||||||
if dataStack is None:
|
if dataStack is None:
|
||||||
dataStack = []
|
dataStack = []
|
||||||
@ -135,7 +138,7 @@ class programState():
|
|||||||
self.dataStack = dataStack
|
self.dataStack = dataStack
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{pos} / {pointers}. Stack: {stack}".format(pos=self.position, pointers=self.direction, stack=self.dataStack)
|
return "Pos:{pos} / {pointers}. Stack: {stack}".format(pos=self.position, pointers=self.direction, stack=self.dataStack)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import copy
|
import copy
|
||||||
from typing import Union, List, Callable
|
from typing import Union, List, Callable
|
||||||
import sys
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# sys.path.insert(0, "../")
|
from interpreter import imageFunctions as imageWrapper
|
||||||
from interpreter import imageWrapper as imageWrapper
|
|
||||||
from interpreter import lexer as lexer
|
from interpreter import lexer as lexer
|
||||||
from interpreter import tokens as tokens
|
from interpreter import tokens as tokens
|
||||||
from interpreter import movement as movement
|
from interpreter import movementFunctions as movement
|
||||||
from interpreter import colors as colors
|
from interpreter import colors as colors
|
||||||
from interpreter import tokenFunctions as runner
|
from interpreter import tokenFunctions as runner
|
||||||
from interpreter import errors as errors
|
from interpreter import errors as errors
|
||||||
@ -26,13 +24,15 @@ def interpret(image: np.ndarray) -> Union[programState, List[BaseException]]:
|
|||||||
print("The following exceptions occured while making the graph:\n{}".format("".join(list(map(lambda x: "\t{}\n".format(x), graph[1])))))
|
print("The following exceptions occured while making the graph:\n{}".format("".join(list(map(lambda x: "\t{}\n".format(x), graph[1])))))
|
||||||
return graph[1]
|
return graph[1]
|
||||||
|
|
||||||
|
# This is the default programState.
|
||||||
startPosition = position((0, 0))
|
startPosition = position((0, 0))
|
||||||
pointers = direction((0, 0))
|
pointers = direction((0, 0))
|
||||||
PS = programState(graph[0], startPosition, pointers)
|
PS = programState(graph[0], startPosition, pointers)
|
||||||
|
|
||||||
result = runProgram(image, PS)
|
result = runProgram(image, PS)
|
||||||
|
# Check if executed step had an error
|
||||||
if isinstance(result, BaseException):
|
if isinstance(result, BaseException):
|
||||||
print("The following exceptions occured while executing the next step:\n{}".format(result))
|
print("The following exception occured while executing the next step:\n{}".format(result))
|
||||||
return [result]
|
return [result]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -64,8 +64,13 @@ def runProgram(image: np.ndarray, PS: programState) -> Union[programState, BaseE
|
|||||||
return runProgram(image, newState)
|
return runProgram(image, newState)
|
||||||
|
|
||||||
|
|
||||||
def countSteps(f: Callable):
|
def countSteps(f: Callable[[np.ndarray, programState], programState]) -> Callable[[np.ndarray, programState], programState]:
|
||||||
def inner(image: np.ndarray, PS: programState):
|
"""
|
||||||
|
A decorator function to count the steps taken in the program
|
||||||
|
:param f: original function to call
|
||||||
|
:return: A decorated function
|
||||||
|
"""
|
||||||
|
def inner(image: np.ndarray, PS: programState) -> programState:
|
||||||
inner.counter += 1
|
inner.counter += 1
|
||||||
return f(image, PS)
|
return f(image, PS)
|
||||||
inner.counter = 0
|
inner.counter = 0
|
||||||
@ -90,21 +95,18 @@ def takeStep(image: np.ndarray, PS: programState) -> Union[programState, BaseExc
|
|||||||
|
|
||||||
result = runner.executeToken(newToken, newState.direction, newState.dataStack)
|
result = runner.executeToken(newToken, newState.direction, newState.dataStack)
|
||||||
|
|
||||||
|
# Add additional information to the error message (Position and direction)
|
||||||
if isinstance(result, BaseException):
|
if isinstance(result, BaseException):
|
||||||
return result
|
return type(result)("{}, at position {}, direction {}".format(result.args[0], edgePosition,newState.direction))
|
||||||
|
# return result
|
||||||
|
|
||||||
# If the next token is either white or color, just move along. If the token was black (or terminate), the direction
|
# If the next token is either white or color, just move along. If the token was black (or terminate), the direction
|
||||||
# is already changed
|
# is already changed, but the position shouldn't move
|
||||||
if isinstance(newToken, (tokens.toWhiteToken, tokens.toColorToken)):
|
if isinstance(newToken, (tokens.toWhiteToken, tokens.toColorToken)):
|
||||||
newState.position = movement.getNextPosition(edgePosition, newState.direction.pointers[0])
|
newState.position = movement.getNextPosition(edgePosition, newState.direction.pointers[0])
|
||||||
|
|
||||||
|
# Use the new direction and stack for the next step
|
||||||
newState.direction = result[0]
|
newState.direction = result[0]
|
||||||
newState.dataStack = result[1]
|
newState.dataStack = result[1]
|
||||||
|
|
||||||
return newState
|
return newState
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.setrecursionlimit(1000000)
|
|
||||||
im = imageWrapper.getImage("../Piet_hello.png")
|
|
||||||
interpret(im)
|
|
@ -1,11 +1,11 @@
|
|||||||
from typing import Union, List, Any
|
from typing import Union
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import interpreter.imageWrapper as imageWrapper
|
from interpreter import imageFunctions as imageWrapper
|
||||||
import interpreter.colors as colors
|
from interpreter import colors as colors
|
||||||
import interpreter.movement as movement
|
from interpreter import movementFunctions as movement
|
||||||
import interpreter.tokens as tokens
|
from interpreter import tokens as tokens
|
||||||
import interpreter.errors as errors
|
from interpreter import errors as errors
|
||||||
from interpreter.dataStructures import edge
|
from interpreter.dataStructures import edge
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ def getCodel(image: np.ndarray, inputPosition: position, foundPixels: codel = No
|
|||||||
if inputPosition in foundPixels.codel:
|
if inputPosition in foundPixels.codel:
|
||||||
return foundPixels
|
return foundPixels
|
||||||
|
|
||||||
|
# Adjacent white colors don't form a codel
|
||||||
if colors.isWhite(getPixel(image, inputPosition)):
|
if colors.isWhite(getPixel(image, inputPosition)):
|
||||||
foundPixels.codel.add(inputPosition)
|
foundPixels.codel.add(inputPosition)
|
||||||
return foundPixels
|
return foundPixels
|
@ -3,10 +3,10 @@ import copy
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import interpreter.colors as colors
|
import interpreter.colors as colors
|
||||||
import interpreter.imageWrapper as imageWrapper
|
import interpreter.imageFunctions as imageWrapper
|
||||||
import interpreter.tokens as tokens
|
import interpreter.tokens as tokens
|
||||||
import interpreter.helperFunctions as helperFunctions
|
import interpreter.helperFunctions as helperFunctions
|
||||||
import interpreter.movement as movement
|
import interpreter.movementFunctions as movement
|
||||||
from interpreter.dataStructures import position, codel, edge, graphNode, graph, direction
|
from interpreter.dataStructures import position, codel, edge, graphNode, graph, direction
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
import operator
|
||||||
|
|
||||||
from interpreter.dataStructures import direction, position, codel
|
from interpreter.dataStructures import direction, position, codel
|
||||||
|
|
||||||
@ -110,7 +111,6 @@ def flip(inputDirection: direction) -> direction:
|
|||||||
return direction((flipDP(inputDirection.pointers[0]), inputDirection.pointers[1]))
|
return direction((flipDP(inputDirection.pointers[0]), inputDirection.pointers[1]))
|
||||||
|
|
||||||
|
|
||||||
# TODO FIX KEYERROR
|
|
||||||
def getNextPosition(startPosition: position, directionPointer: int) -> Union[position, KeyError]:
|
def getNextPosition(startPosition: position, directionPointer: int) -> Union[position, KeyError]:
|
||||||
"""
|
"""
|
||||||
Finds next position along the direction pointer
|
Finds next position along the direction pointer
|
||||||
@ -155,49 +155,44 @@ def findEdge(inputCodel: codel, inputDirection: direction) -> Union[position, bo
|
|||||||
dp = inputDirection.pointers[0]
|
dp = inputDirection.pointers[0]
|
||||||
cc = inputDirection.pointers[1]
|
cc = inputDirection.pointers[1]
|
||||||
|
|
||||||
|
# Right side
|
||||||
if dp == 0:
|
if dp == 0:
|
||||||
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
||||||
for pos in inputCodel.codel:
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
|
||||||
if pos.coords[0] == edgePosition.coords[0]:
|
if cc == 0:
|
||||||
# -> ^ Right and up
|
# -> ^ Right and up
|
||||||
if cc == 0 and pos.coords[1] < edgePosition.coords[1]:
|
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
||||||
edgePosition = pos
|
else:
|
||||||
# -> V Right and down
|
# -> V Right and down
|
||||||
if cc == 1 and pos.coords[1] > edgePosition.coords[1]:
|
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
||||||
edgePosition = pos
|
# Bottom side
|
||||||
return edgePosition
|
|
||||||
elif dp == 1:
|
elif dp == 1:
|
||||||
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
||||||
for pos in inputCodel.codel:
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
|
||||||
if pos.coords[1] == edgePosition.coords[1]:
|
if cc == 0:
|
||||||
# V -> Down and right
|
# V -> Down and right
|
||||||
if cc == 0 and pos.coords[0] > edgePosition.coords[0]:
|
return max(maxValues, key=lambda lambaPos: lambaPos.coords[0])
|
||||||
edgePosition = pos
|
else:
|
||||||
# V <- Down and left
|
# V <- Down and left
|
||||||
elif cc == 1 and pos.coords[0] < edgePosition.coords[0]:
|
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])
|
||||||
edgePosition = pos
|
# Left side
|
||||||
return edgePosition
|
|
||||||
elif dp == 2:
|
elif dp == 2:
|
||||||
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
||||||
for pos in inputCodel.codel:
|
minValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
|
||||||
if pos.coords[0] == edgePosition.coords[0]:
|
if cc == 0:
|
||||||
# <- V Left and down
|
# <- V Left and down
|
||||||
if cc == 0 and pos.coords[1] > edgePosition.coords[1]:
|
return max(minValues, key=lambda lambaPos: lambaPos.coords[1])
|
||||||
edgePosition = pos
|
else:
|
||||||
# <- ^ left and up
|
# <- ^ left and up
|
||||||
elif cc == 1 and pos.coords[1] < edgePosition.coords[1]:
|
return min(minValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
||||||
edgePosition = pos
|
|
||||||
return edgePosition
|
# Top side
|
||||||
elif dp == 3:
|
else: # dp == 3
|
||||||
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
||||||
for pos in inputCodel.codel:
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
|
||||||
if pos.coords[1] == edgePosition.coords[1]:
|
if cc == 0:
|
||||||
# ^ <- Up and left
|
# ^ <- Up and left
|
||||||
if cc == 0 and pos.coords[0] < edgePosition.coords[0]:
|
return min(maxValues, key=lambda lambaPos: lambaPos.coords[0])
|
||||||
edgePosition = pos
|
else:
|
||||||
# ^ -> Up and right
|
# ^ -> Up and right
|
||||||
elif cc == 1 and pos.coords[0] > edgePosition.coords[0]:
|
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])
|
||||||
edgePosition = pos
|
|
||||||
return edgePosition
|
|
||||||
else:
|
|
||||||
raise SyntaxError("DirectionPointer '{}' is unknown".format(dp))
|
|
@ -1,14 +1,12 @@
|
|||||||
from typing import List, Tuple, Union
|
from typing import List, Tuple, Union
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import interpreter.tokens as lexerTokens
|
from interpreter import tokens as lexerTokens
|
||||||
import interpreter.movement as movement
|
from interpreter import movementFunctions as movement
|
||||||
import interpreter.errors as errors
|
from interpreter import errors as errors
|
||||||
from interpreter.dataStructures import direction
|
from interpreter.dataStructures import direction
|
||||||
|
|
||||||
|
|
||||||
# TODO Nettere afhandeling errors (Union[Tuple[List[int], Tuple[int, int]], bool])
|
|
||||||
# TODO Test cases maken per token
|
|
||||||
def executeToken(token: lexerTokens.baseLexerToken, inputDirection: direction, dataStack: List[int]) -> Union[Tuple[direction, List[int]], BaseException]:
|
def executeToken(token: lexerTokens.baseLexerToken, inputDirection: direction, dataStack: List[int]) -> Union[Tuple[direction, List[int]], BaseException]:
|
||||||
"""
|
"""
|
||||||
Executes the function associated with tokens
|
Executes the function associated with tokens
|
||||||
@ -144,16 +142,16 @@ def divideOperator(inputDirection: direction, dataStack: List[int]) -> Union[Tup
|
|||||||
:return: Tuple with the new data stack and new pointers
|
:return: Tuple with the new data stack and new pointers
|
||||||
"""
|
"""
|
||||||
newStack = dataStack.copy()
|
newStack = dataStack.copy()
|
||||||
inputDirection = copy.deepcopy(inputDirection)
|
newDirection = copy.deepcopy(inputDirection)
|
||||||
if len(newStack) < 2:
|
if len(newStack) < 2:
|
||||||
return (inputDirection, newStack)
|
return (newDirection, newStack)
|
||||||
|
|
||||||
first = newStack.pop()
|
first = newStack.pop()
|
||||||
second = newStack.pop()
|
second = newStack.pop()
|
||||||
if second == 0:
|
if second == 0:
|
||||||
return ZeroDivisionError("Division by zero {}/{}".format(first, second))
|
return ZeroDivisionError("Division by zero {}/{}".format(first, second))
|
||||||
newStack.append(int(second / first))
|
newStack.append(int(second / first))
|
||||||
return (inputDirection, newStack)
|
return (newDirection, newStack)
|
||||||
|
|
||||||
|
|
||||||
def modOperator(inputDirection: direction, dataStack: List[int]) -> Union[Tuple[direction, List[int]], BaseException]:
|
def modOperator(inputDirection: direction, dataStack: List[int]) -> Union[Tuple[direction, List[int]], BaseException]:
|
||||||
@ -170,7 +168,6 @@ def modOperator(inputDirection: direction, dataStack: List[int]) -> Union[Tuple[
|
|||||||
valA = newStack.pop()
|
valA = newStack.pop()
|
||||||
valB = newStack.pop()
|
valB = newStack.pop()
|
||||||
if valB == 0:
|
if valB == 0:
|
||||||
# TODO ERROR
|
|
||||||
return ZeroDivisionError("Second value is 0: {}%{}".format(valA, valB))
|
return ZeroDivisionError("Second value is 0: {}%{}".format(valA, valB))
|
||||||
newStack.append(valB % valA)
|
newStack.append(valB % valA)
|
||||||
return (inputDirection, newStack)
|
return (inputDirection, newStack)
|
||||||
|
@ -10,21 +10,33 @@ class baseLexerToken():
|
|||||||
|
|
||||||
|
|
||||||
class toBlackToken(baseLexerToken):
|
class toBlackToken(baseLexerToken):
|
||||||
|
"""
|
||||||
|
Used when a transition to black (or edge) occurs
|
||||||
|
"""
|
||||||
def __init__(self, tokenType: str = "toBlack"):
|
def __init__(self, tokenType: str = "toBlack"):
|
||||||
super().__init__(tokenType)
|
super().__init__(tokenType)
|
||||||
|
|
||||||
|
|
||||||
class toWhiteToken(baseLexerToken):
|
class toWhiteToken(baseLexerToken):
|
||||||
|
"""
|
||||||
|
Used when a transition to white occurs
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("toWhite")
|
super().__init__("toWhite")
|
||||||
|
|
||||||
|
|
||||||
class terminateToken(baseLexerToken):
|
class terminateToken(baseLexerToken):
|
||||||
|
"""
|
||||||
|
Used when a codel has no possible way to escape (8 * toBlack)
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("exit")
|
super().__init__("exit")
|
||||||
|
|
||||||
|
|
||||||
class toColorToken(baseLexerToken):
|
class toColorToken(baseLexerToken):
|
||||||
|
"""
|
||||||
|
Used when a transition to a color occurs
|
||||||
|
"""
|
||||||
def __init__(self, tokenType: str, codelSize: int):
|
def __init__(self, tokenType: str, codelSize: int):
|
||||||
super().__init__(tokenType)
|
super().__init__(tokenType)
|
||||||
self.codelSize = codelSize
|
self.codelSize = codelSize
|
||||||
@ -34,6 +46,12 @@ class toColorToken(baseLexerToken):
|
|||||||
|
|
||||||
|
|
||||||
def getTokenType(hueChange: int, lightChange: int) -> str:
|
def getTokenType(hueChange: int, lightChange: int) -> str:
|
||||||
|
"""
|
||||||
|
Find the toColorToken type based on hue change and lightness change
|
||||||
|
:param hueChange: number of hue changes between two pixels
|
||||||
|
:param lightChange: number of lightness changes between two pixels
|
||||||
|
:return: A string with the toColorToken type
|
||||||
|
"""
|
||||||
tokens = [
|
tokens = [
|
||||||
["noop", "push", "pop"],
|
["noop", "push", "pop"],
|
||||||
["add", "subtract", "multiply"],
|
["add", "subtract", "multiply"],
|
||||||
|
8
main.py
@ -1,7 +1,10 @@
|
|||||||
import argparse
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
from interpreter import executionFunctions as executionFunctions
|
sys.setrecursionlimit(100000)
|
||||||
from interpreter import imageWrapper as imageWrapper
|
|
||||||
|
from interpreter import executeFunctions as executionFunctions
|
||||||
|
from interpreter import imageFunctions as imageWrapper
|
||||||
from GUI import main as GUIMain
|
from GUI import main as GUIMain
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Interprets a piet image')
|
parser = argparse.ArgumentParser(description='Interprets a piet image')
|
||||||
@ -17,7 +20,6 @@ if not args.graphical:
|
|||||||
if args.verbose:
|
if args.verbose:
|
||||||
print("\nTotal steps: {}".format(executionFunctions.takeStep.counter))
|
print("\nTotal steps: {}".format(executionFunctions.takeStep.counter))
|
||||||
else:
|
else:
|
||||||
print("GUI TIME!")
|
|
||||||
app = GUIMain.GUI()
|
app = GUIMain.GUI()
|
||||||
app.setFileText(args.file)
|
app.setFileText(args.file)
|
||||||
app.loadFile()
|
app.loadFile()
|
||||||
|