Final refractor

This commit is contained in:
Jens Bouman 2020-05-09 12:53:26 +02:00
parent afa67b21ac
commit 0fb7601130
25 changed files with 223 additions and 8418 deletions

BIN
ColorError.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

View File

@ -1,4 +1,4 @@
import interpreter.imageWrapper as imageWrapper
import interpreter.imageFunctions as imageWrapper
class canvasManager():
@ -6,29 +6,54 @@ class canvasManager():
self.canvas = canvas
self.image = image
self.programState = programState
self.previousProgramState = None
self.scaleSize = scaleSize
def updateImage(self, newImage):
self.image = newImage
def updateScaleSize(self, scaleSize):
self.scaleSize = scaleSize
def updateProgramState(self, newProgramState):
self.previousProgramState = self.programState
self.programState = newProgramState
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])
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:
print("one is not none")
return False
self.drawImage()
if self.previousProgramState is None:
self.drawImage()
else:
self.unHighlightCodel()
self.highlightCodel()
# Draw breakpoint
return True
def drawImage(self):
"""
Draw the image pixel for pixel, upscaled to the scaleSize.
:return:
"""
self.clearCanvas()
for raw_y, row in enumerate(self.image):
for raw_x, pixel in enumerate(row):
@ -39,19 +64,56 @@ class canvasManager():
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")
def highlightCodel(self):
"""
Outlines the current codel with complemented colors
:return:
"""
codel = imageWrapper.getCodel(self.image, self.programState.position)
pixel = imageWrapper.getPixel(self.image, self.programState.position)
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):
for position in codel.codel:
x = position.coords[0] * 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)
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))

View File

@ -1,7 +1,7 @@
import interpreter.imageWrapper as imageWrapper
import interpreter.imageFunctions as imageWrapper
import interpreter.colors as colors
import interpreter.tokens as lexerTokens
import interpreter.movement as movement
import interpreter.movementFunctions as movement
from interpreter.dataStructures import direction
class infoManager():
@ -15,26 +15,12 @@ class infoManager():
self.updateProgramStateInfo(programState)
def updateGeneralinfo(self, image, graph, programState):
self.updateCodelInfo(image, programState.position)
self.updateEdgesInfo(image, graph, programState)
def updateProgramStateInfo(self, programState):
self.updateStackInfo(programState.dataStack)
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):
edgesInfo = self.builder.get_object('codelEdgesMessage', self.generalInfo)

View File

@ -1,17 +1,10 @@
# helloworld.py
import pygubu
import sys
import os
sys.path.insert(0, "GUI/TKinter/.")
from interpreter import imageWrapper as imageWrapper
from interpreter import imageFunctions as imageWrapper
from interpreter import lexer as lexer
from interpreter import tokens as lexerTokens
from interpreter import colors as colors
from interpreter import movement as movement
from interpreter import executionFunctions as main
from interpreter import executeFunctions as main
from interpreter.dataStructures import programState, direction, position
import threading
from GUI import infoManager
from GUI import canvasManager
@ -20,7 +13,7 @@ from GUI import canvasManager
class GUI:
def __init__(self):
# 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
self.executionSpeed = 15
@ -38,13 +31,13 @@ class GUI:
self.canvas = None
#1: Create a builder
self.builder = builder = pygubu.Builder()
self.builder = pygubu.Builder()
#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
self.mainwindow = builder.get_object('rootWindow')
self.mainwindow = self.builder.get_object('rootWindow')
self.initializeFrames()
self.initializeCallbacks()
@ -60,14 +53,16 @@ class GUI:
self.builder.connect_callbacks({
'loadFile': self.loadFile,
'setScale': self.setScale,
'takeStep': self.takeStep,
'setExecutionSpeed': self.setExecutionSpeed,
'setBreakpoint': self.setBreakpoint,
'runProgram': self.runProgram,
'updateHighlight': self.toggleHighlight
'takeStep': self.takeStep
})
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):
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.generalInfoFrame = self.builder.get_object("generalInfoFrame", self.content)
self.programStateInfoFrame = self.builder.get_object("programStateInfoFrame", self.content)
canvasFrame = self.builder.get_object('canvasFrame', self.content)
self.canvas = self.builder.get_object('canvas', canvasFrame)
self.canvasFrame = self.builder.get_object('canvasFrame', self.content)
self.canvas = self.builder.get_object('canvas', self.canvasFrame)
def update(self):
@ -85,6 +80,7 @@ class GUI:
self.canvasManager.updateImage(self.image)
self.canvasManager.updateProgramState(self.programState)
self.canvasManager.updateCanvas()
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def takeStep(self):
@ -92,77 +88,59 @@ class GUI:
return None
newProgramState = main.takeStep(self.image, self.programState)
if isinstance(newProgramState, bool):
return False
# Error encountered, close window
if isinstance(newProgramState, BaseException):
self.mainwindow.destroy()
self.mainwindow.quit()
raise newProgramState
self.programState = newProgramState
self.selectedPosition = self.programState.position
self.update()
print("Take step!")
return True
def setBreakpoint(self):
print("BREAKPOINT")
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).insert(0, filePath)
print("Get filepath: {}".format(self.builder.get_object("fileNameEntry", self.optionBar).get()))
def setExecutionSpeed(self, pos):
if 0 < float(pos) < 100:
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):
scaleValue = int(self.builder.get_object('scaleEntry', self.optionBar).get())
if 0 < scaleValue < 100:
self.canvasManager.clearCanvas()
self.scaleSize = int(scaleValue)
self.update()
print("SCALE")
self.canvasManager.drawImage()
self.canvasManager.updateCanvas()
def loadFile(self):
fileName = self.builder.get_object('fileNameEntry', self.optionBar).get()
if len(fileName) < 1:
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)
self.graph = lexer.graphImage(self.image)[0]
tmpResult = lexer.graphImage(tmpImage)
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)))
# Reset previous state
self.canvasManager.previousProgramState = None
self.canvasManager.programState = None
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()

View File

@ -71,7 +71,7 @@
</child>
<child>
<object id="scaleEntry" class="ttk.Entry">
<property name="text" translatable="yes">75</property>
<property name="text" translatable="yes">15</property>
<layout>
<property name="column">3</property>
<property name="ipady">2</property>
@ -108,32 +108,6 @@
</column>
</columns>
</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>
<object id="takeStep" class="ttk.Button">
<property name="command">takeStep</property>
@ -147,18 +121,6 @@
</layout>
</object>
</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>
</child>
<child>
@ -213,31 +175,12 @@
</layout>
</object>
</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>
<object id="codelEdgesMessage" class="tk.Message">
<property name="background">#FFFFFF</property>
<property name="highlightcolor">#a7a7a7</property>
<property name="highlightbackground">#39af36</property>
<property name="highlightthickness">1</property>
<property name="text" translatable="yes">Codel edges are as follows:
(0,1) -&gt; (1,0) push 0</property>
<property name="text" translatable="yes">Codel edges are as follows: </property>
<property name="width">200</property>
<layout>
<property name="column">0</property>
@ -246,17 +189,6 @@
</layout>
</object>
</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>
</child>
<child>
@ -286,6 +218,7 @@
<object id="stackContents" class="tk.Message">
<property name="anchor">center</property>
<property name="background">#ffffff</property>
<property name="highlightbackground">#39af36</property>
<property name="highlightcolor">#a7a7a7</property>
<property name="highlightthickness">1</property>
<layout>
@ -320,6 +253,8 @@
<child>
<object id="pointerMessage" class="tk.Message">
<property name="background">#ffffff</property>
<property name="highlightbackground">#39af36</property>
<property name="highlightthickness">1</property>
<layout>
<property name="column">1</property>
<property name="propagate">True</property>
@ -337,6 +272,7 @@
<property name="column">2</property>
<property name="propagate">True</property>
<property name="row">0</property>
<property name="sticky">nw</property>
</layout>
<child>
<object id="canvas" class="tk.Canvas">
@ -353,26 +289,29 @@
<property name="pady">5</property>
<property name="propagate">True</property>
<property name="row">0</property>
<property name="sticky">n</property>
</layout>
</object>
</child>
<child>
<object id="Scrollbar_1" class="ttk.Scrollbar">
<object id="canvasVerticalScroll" class="tk.Scrollbar">
<property name="orient">vertical</property>
<layout>
<property name="column">1</property>
<property name="column">2</property>
<property name="propagate">True</property>
<property name="row">0</property>
<property name="sticky">ns</property>
</layout>
</object>
</child>
<child>
<object id="Scrollbar_2" class="ttk.Scrollbar">
<object id="canvasHorizontalScroll" class="tk.Scrollbar">
<property name="orient">horizontal</property>
<layout>
<property name="column">0</property>
<property name="propagate">True</property>
<property name="row">1</property>
<property name="sticky">ew</property>
</layout>
</object>
</child>

BIN
Info/GUI layout.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 KiB

After

Width:  |  Height:  |  Size: 523 KiB

Binary file not shown.

0
__init__.py Normal file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

BIN
countdown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

BIN
divideByZero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
endless.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

View File

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 354 B

View File

@ -2,7 +2,7 @@ from typing import Dict, Union
import numpy as np
import interpreter.errors as errors
from interpreter import errors as errors
class possiblePixels:
def __init__(self):
@ -52,11 +52,10 @@ def getPixelChange(colorStart: np.ndarray, colorEnd: np.ndarray) -> Union[Dict[s
return {"hueChange": 0, "lightChange": 0}
pixelsColors = possiblePixels()
# Converting np arrays to common lists
# Converting np arrays to normal lists
colorStart = list(colorStart)[:3]
colorEnd = list(colorEnd)[:3]
if colorStart not in pixelsColors.colors:
return errors.UnknownColorError("Color {} is not recognized as a correct color".format(colorStart))
if colorEnd not in pixelsColors.colors:

View File

@ -1,7 +1,7 @@
from typing import Set, Tuple, Dict, List
import copy
import interpreter.tokens as tokens
from interpreter import tokens as tokens
class position():
"""
@ -125,6 +125,9 @@ class graph():
return str(self)
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):
if dataStack is None:
dataStack = []
@ -135,7 +138,7 @@ class programState():
self.dataStack = dataStack
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):
return str(self)

View File

@ -1,14 +1,12 @@
import copy
from typing import Union, List, Callable
import sys
import numpy as np
# sys.path.insert(0, "../")
from interpreter import imageWrapper as imageWrapper
from interpreter import imageFunctions as imageWrapper
from interpreter import lexer as lexer
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 tokenFunctions as runner
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])))))
return graph[1]
# This is the default programState.
startPosition = position((0, 0))
pointers = direction((0, 0))
PS = programState(graph[0], startPosition, pointers)
result = runProgram(image, PS)
# Check if executed step had an error
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
@ -64,8 +64,13 @@ def runProgram(image: np.ndarray, PS: programState) -> Union[programState, BaseE
return runProgram(image, newState)
def countSteps(f: Callable):
def inner(image: np.ndarray, PS: programState):
def countSteps(f: Callable[[np.ndarray, programState], programState]) -> Callable[[np.ndarray, programState], 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
return f(image, PS)
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)
# Add additional information to the error message (Position and direction)
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
# is already changed
# is already changed, but the position shouldn't move
if isinstance(newToken, (tokens.toWhiteToken, tokens.toColorToken)):
newState.position = movement.getNextPosition(edgePosition, newState.direction.pointers[0])
# Use the new direction and stack for the next step
newState.direction = result[0]
newState.dataStack = result[1]
return newState
if __name__ == "__main__":
sys.setrecursionlimit(1000000)
im = imageWrapper.getImage("../Piet_hello.png")
interpret(im)

View File

@ -1,11 +1,11 @@
from typing import Union, List, Any
from typing import Union
import numpy as np
import interpreter.imageWrapper as imageWrapper
import interpreter.colors as colors
import interpreter.movement as movement
import interpreter.tokens as tokens
import interpreter.errors as errors
from interpreter import imageFunctions as imageWrapper
from interpreter import colors as colors
from interpreter import movementFunctions as movement
from interpreter import tokens as tokens
from interpreter import errors as errors
from interpreter.dataStructures import edge

View File

@ -54,6 +54,7 @@ def getCodel(image: np.ndarray, inputPosition: position, foundPixels: codel = No
if inputPosition in foundPixels.codel:
return foundPixels
# Adjacent white colors don't form a codel
if colors.isWhite(getPixel(image, inputPosition)):
foundPixels.codel.add(inputPosition)
return foundPixels

View File

@ -3,10 +3,10 @@ import copy
import numpy as np
import interpreter.colors as colors
import interpreter.imageWrapper as imageWrapper
import interpreter.imageFunctions as imageWrapper
import interpreter.tokens as tokens
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

View File

@ -1,4 +1,5 @@
from typing import Union
import operator
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]))
# TODO FIX KEYERROR
def getNextPosition(startPosition: position, directionPointer: int) -> Union[position, KeyError]:
"""
Finds next position along the direction pointer
@ -155,49 +155,44 @@ def findEdge(inputCodel: codel, inputDirection: direction) -> Union[position, bo
dp = inputDirection.pointers[0]
cc = inputDirection.pointers[1]
# Right side
if dp == 0:
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
for pos in inputCodel.codel:
if pos.coords[0] == edgePosition.coords[0]:
# -> ^ Right and up
if cc == 0 and pos.coords[1] < edgePosition.coords[1]:
edgePosition = pos
# -> V Right and down
if cc == 1 and pos.coords[1] > edgePosition.coords[1]:
edgePosition = pos
return edgePosition
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
if cc == 0:
# -> ^ Right and up
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
else:
# -> V Right and down
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
# Bottom side
elif dp == 1:
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
for pos in inputCodel.codel:
if pos.coords[1] == edgePosition.coords[1]:
# V -> Down and right
if cc == 0 and pos.coords[0] > edgePosition.coords[0]:
edgePosition = pos
# V <- Down and left
elif cc == 1 and pos.coords[0] < edgePosition.coords[0]:
edgePosition = pos
return edgePosition
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
if cc == 0:
# V -> Down and right
return max(maxValues, key=lambda lambaPos: lambaPos.coords[0])
else:
# V <- Down and left
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])
# Left side
elif dp == 2:
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
for pos in inputCodel.codel:
if pos.coords[0] == edgePosition.coords[0]:
# <- V Left and down
if cc == 0 and pos.coords[1] > edgePosition.coords[1]:
edgePosition = pos
# <- ^ left and up
elif cc == 1 and pos.coords[1] < edgePosition.coords[1]:
edgePosition = pos
return edgePosition
elif dp == 3:
minValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
if cc == 0:
# <- V Left and down
return max(minValues, key=lambda lambaPos: lambaPos.coords[1])
else:
# <- ^ left and up
return min(minValues, key=lambda lambdaPos: lambdaPos.coords[1])
# Top side
else: # dp == 3
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
for pos in inputCodel.codel:
if pos.coords[1] == edgePosition.coords[1]:
# ^ <- Up and left
if cc == 0 and pos.coords[0] < edgePosition.coords[0]:
edgePosition = pos
# ^ -> Up and right
elif cc == 1 and pos.coords[0] > edgePosition.coords[0]:
edgePosition = pos
return edgePosition
else:
raise SyntaxError("DirectionPointer '{}' is unknown".format(dp))
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
if cc == 0:
# ^ <- Up and left
return min(maxValues, key=lambda lambaPos: lambaPos.coords[0])
else:
# ^ -> Up and right
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,12 @@
from typing import List, Tuple, Union
import copy
import interpreter.tokens as lexerTokens
import interpreter.movement as movement
import interpreter.errors as errors
from interpreter import tokens as lexerTokens
from interpreter import movementFunctions as movement
from interpreter import errors as errors
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]:
"""
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
"""
newStack = dataStack.copy()
inputDirection = copy.deepcopy(inputDirection)
newDirection = copy.deepcopy(inputDirection)
if len(newStack) < 2:
return (inputDirection, newStack)
return (newDirection, newStack)
first = newStack.pop()
second = newStack.pop()
if second == 0:
return ZeroDivisionError("Division by zero {}/{}".format(first, second))
newStack.append(int(second / first))
return (inputDirection, newStack)
return (newDirection, newStack)
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()
valB = newStack.pop()
if valB == 0:
# TODO ERROR
return ZeroDivisionError("Second value is 0: {}%{}".format(valA, valB))
newStack.append(valB % valA)
return (inputDirection, newStack)

View File

@ -10,21 +10,33 @@ class baseLexerToken():
class toBlackToken(baseLexerToken):
"""
Used when a transition to black (or edge) occurs
"""
def __init__(self, tokenType: str = "toBlack"):
super().__init__(tokenType)
class toWhiteToken(baseLexerToken):
"""
Used when a transition to white occurs
"""
def __init__(self):
super().__init__("toWhite")
class terminateToken(baseLexerToken):
"""
Used when a codel has no possible way to escape (8 * toBlack)
"""
def __init__(self):
super().__init__("exit")
class toColorToken(baseLexerToken):
"""
Used when a transition to a color occurs
"""
def __init__(self, tokenType: str, codelSize: int):
super().__init__(tokenType)
self.codelSize = codelSize
@ -34,6 +46,12 @@ class toColorToken(baseLexerToken):
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 = [
["noop", "push", "pop"],
["add", "subtract", "multiply"],

View File

@ -1,7 +1,10 @@
import argparse
import sys
from interpreter import executionFunctions as executionFunctions
from interpreter import imageWrapper as imageWrapper
sys.setrecursionlimit(100000)
from interpreter import executeFunctions as executionFunctions
from interpreter import imageFunctions as imageWrapper
from GUI import main as GUIMain
parser = argparse.ArgumentParser(description='Interprets a piet image')
@ -17,7 +20,6 @@ if not args.graphical:
if args.verbose:
print("\nTotal steps: {}".format(executionFunctions.takeStep.counter))
else:
print("GUI TIME!")
app = GUIMain.GUI()
app.setFileText(args.file)
app.loadFile()