- The fun way
ghci Main.hs letsGo
- The other way
ghci Main.hs emulate "your Fun code" - The hard way (*see at the bottom of the ReadMe)
We made four adjustments to the F syntax:
-
We decided to interchange the semicolons between multiple
Local Definitionswith commas because we wanted semicolons to be used exclusively between multipleDefinitions(for better readability). -
According to the script the precedence of the negation should be lower than the precedence of an addition. This would lead to
-5 + 2being evaluated as-7. We wanted our syntax to be more intuitive so we changed the precedences to let-5 + 2be evaluated as-3. -
As opposed to the script we allow inputs of the form
A-B-CandA/B/Cby implementing a left associativity for-and/. -
We also implemented exponential expressions. Only integers are allowed as exponents.
The Main module is the interface for our entire implementation. It imports all of the modules below. You can either call the modules' functions directly or call letsGo for a fun and interactive experience of Fun!
Each module provides a function and a showFunction. When other modules want to continue processing the result of a different module they always call function, never showFunction. The only purpose of showFunction is to create a nice, more comprehensive output of an intermediate result.
-
takes a
String(your Fun program) as input, splits it up intoTokensand returns them in a list.
-
takes a
String(your Fun program) as input, callstokenizeon it and converts the list ofTokensinto an AST (abstract syntax tree) withExpressionsas nodes and leaves. -
creates an output that is easier to comprehend than the output of
parse. It lists allDefinitionswith their arguments and represents the AST structure of the function body with parentheses.For example
showParse "main = cool 1; cool x = 10*x;"creates the following output:Definition main [] (Function (Variable "cool") (Val 1)) Definition cool ["x"] (Mult (Val 10) (Variable "x"))
-
takes a
String(your Fun program) as input, callsparseon it and converts the AST into a list ofInstructions. This list is appended toinitCodewhich contains theInstructionsthat call themainfunction, ensure the termination of the code and enable the emulation of unary, binary and ifExpressions.compilealso initializesHeap,Global,PCandStack:pc = 0 code = initCode ++ [Instruction] stack = [] heap = [DEF name arity codeAddress] global = [(name, heapAddress)]
Heapis initialized withDEFcells which consist of the name, arity and code address of each function. TheGlobalenvironment contains the function names and correspondingHeapaddresses of thoseDEFcells.These five sets of data are returned as a
State:State pc code stack heap global -
provides a better visualization of the initial
State. It only showsInstructions,HeapandGlobal.
-
takes a
String(your Fun program) as input, callscompileon it and uses theStateas input forrunwhich emulates theInstructionsstep by step and changesPC,StackandHeapaccordingly. It is a recursive function which overwrites the oldStateafter eachInstructionis processed. The finalStatecontains the result of the emulation and is returned toemulatewhich unpacks the result and returns it. -
visualizes
emulateby showing each state of the emulation process. In order to do that, it needs to know how theStatelooked after eachInstructionbut run doesn't provide this information. So it callsshowRunwhich doesn't overwrite the oldState, but rather appends each newStateto a list in a recursive manner.
- letsGo function
- monadic error handling
- console output of
showFunctions - associativity of
-and/ - exponential functions
- it works
- it's Fun!
*3. The hard way
-- myProgram.hs
import Tokenizer
import Parser
import Compiler
import Emulator
import Datatypes
example = showTokenize "your Fun code"ghci myProgram.hs
example