This is a compiler written primarily in F# for my CSC 124 class at Hofstra. Quack as a programming language is built to closely emulate the syntax of languages like Java.
░░░░░░░░░░
░░██████████░░
░░██████████████░░
░░████████░░░░██░░░░░░░░░░
░░ ░░████████░░░░██░░██████░░
░░██░░ ░░██████████████░░██████░░
░░████░░ ░░██████████████░░░░░░░░
░░████████░░ ░░████████████░░
░░████████░░░░░░░░░░░░████████░░
░░████████░░████████████████████░░
░░████████████████████████████████░░
░░████████████████████████████████░░
░░████████████████████████████████░░
░░████████████████████████████████░░
░░████████████████████████████████░░
░░██████████████████████████████░░
░░██████████████████████████░░
░░░░░░████████████████░░░░
░░░░░░░░░░░░░░░░
The quack compiler has several scripts to increase the ease of use and developer efficiency when working with the compiler
To compile all of the files for the compiler, utilze the following command.
./compileQuackTo run the compiler on a given file, use the command. This automatically runs the sequence defined in manual compilation.
./runCompiler [Path to .quack file]In order to debug issues in the compilation stage, the following manual process can be run for any stage of compilation
The grammar for the abstract syntax tree is defined in quack.grammar. The following cases are defined.
The grammar defines the following 4 primitive types
- Integers (LLint)
- Floatpt (LLfloat)
- LLstring (LLstring)
- ListLiteral (LLlist)
- Nil (LLunit)
- Generic Type (lltype)
- Pointers (llpointer)
- Tuples (LLtuple of lltype)
The abstract syntax defines the following arithmetic operations
- Uniop
- Binop These operations are denoted by a symbol identifying the operation to perform.
- Unary Operations
- (-) Negation
- (print) Print function
- (not) Binary negation
- (car) List deconstruction item
- (cdr) List deconstruction remainder
- (~) Can't remember
Functions show up in the abstract syntax as either
- TypedLambda or Lambda (LLfun)
During the typecheck stage, Lambdas get converted into typed lambdas through type inference. Function application takes place through the use of the operator. The type of lambda ,
LLFunis further specified by it's argument and return types. The full type declaration of a LLFun type looks likeLLfun of (lltype list)*lltypewith the type list being the list of arguments and the final lltype being the return type of the function.
Functions are called in the abstract syntax through the Apply operation.