diff --git a/lib/winx86-64/lowlevel.qfall b/lib/winx86-64/lowlevel.qfall deleted file mode 100644 index 304a7c5..0000000 --- a/lib/winx86-64/lowlevel.qfall +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The quickfall std::lowlevel for Windows x86-64 architecture. - */ - -/** - * Marks a specific amount of bytes of the stack as used. - * @param the size to mark (in bytes). - */ -func salloc(int size) {} - -/** - * Marks a specific amount of bytes of the stack as used. - * @param size the size to mark (in bytes). - */ -func sfree(int size) {} - -/** - * Puts a value of the provided type into a stack section. - * @param type the Assembly type of the value. - * @param value the value. - */ -func sput(? type, ? value) {} - -/** - * Moves a section register value into another register. - * @param section the Assembly section where the origin value is stored. - * @param originRegister the register to grab the origin value from. - * @param destRegister the register where the value needs to be moved. - */ -func mov(str section, str originRegister, str destRegister) {} diff --git a/src/cli/main.c b/src/cli/main.c index 3943aa1..301e54c 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -18,7 +18,11 @@ #include "../compiler/compiler.h" #include "../compiler/pe/pe.h" -#include "../compiler/ir.h" + +#include "../ir/structs.h" +#include "../ir/ir.h" + +#include "../qasm/writer/writer.h" #include "../utils/logging.c" @@ -40,8 +44,8 @@ void showCommandEntry(char* commandName, char* description, int argumentCount, c void showHelpMessage() { printf("\n%sQuickfall%s - The programming language.\n\nCommands:\n", TEXT_CYAN, RESET); - char** arguments = malloc(5 * 24); - char** argumentDescriptions = malloc(5 * 256); + char** arguments = malloc(4); + char** argumentDescriptions = malloc(125); arguments[0] = "-p"; argumentDescriptions[0] = "Determines the targeted platform. Defaults to the current platform."; @@ -114,17 +118,17 @@ int main(int argc, char* argv[]) { fclose(fptr); LEXER_RESULT result = runLexer(buff, size); - AST_NODE* root = parseNodes(result, 0, AST_ROOT); + AST_TREE_BRANCH* root = (AST_TREE_BRANCH*) parseRoot(result, 0, AST_TYPE_ROOT); + IR_OUTPUT* irOut = parseIR(root); - IR_CTX* ctx = makeContext(root); - - if(ctx == NULL) { - printf("Error: the IR context is null! Something went wrong during compiling! Please check any logs for errors\n"); + if(irOut == NULL) { + printf("Error: IR parsing failed\n"); return -1; } fptr = fopen(outputFile, "w"); - compile(ctx, fptr); + + writeQASM(fptr, irOut); // experimental: ir -> QASM break; case 'v': diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 7081887..0ffd2b5 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -7,182 +7,13 @@ #include #include "./compiler.h" -#include "./ir.h" - -#include "../parser/ast.h" - -#include "../utils/hash.h" -#include "../utils/hashmap.h" #include "./pe/pe.h" -/** - * Parses the AST tree into a context. - * @param tree the AST tree. - */ -IR_CTX* makeContext(AST_NODE* tree) { - IR_CTX* ctx = malloc(sizeof(IR_CTX)); - - int buffSize = 32; - ctx->nodes = malloc(sizeof(IR_NODE) * 32); - - ctx->nodeIndex = 0; - ctx->nodeMap = createHashmap(512,200); - - while(tree != NULL) { - switch(tree->type) { - case AST_VARIABLE_DECLARATION: - - int hash = hashstr(tree->left->value); - - if(hashGet(ctx->nodeMap, hash) != NULL) { - printf("Variable %s is already declared!\n", tree->left->value); - return NULL; - } - - IR_NODE* node = createIRNode(IR_VARIABLE, tree->left->value); - - node->type = tree->value; - - if(tree->right != NULL && tree->right->value) node->value = tree->right->value; - - ctx->nodes[ctx->nodeIndex] = node; - ctx->nodeIndex++; - - hashPut(ctx->nodeMap, hash, node); - - if(ctx->nodeIndex > buffSize) { - buffSize = buffSize * 1.5; - ctx->nodes = realloc(ctx->nodes, buffSize); - } - - break; - - case AST_FUNCTION_DECLARATION: - - hash = hashstr(tree->left->right->value); - - if(hashGet(ctx->nodeMap, hash) != NULL) { - printf("Function %s was already declared!\n", tree->left->right->value); - return NULL; - } - - node = createIRNode(IR_FUNCTION, tree->left->right->value); - - node->type = tree->left->value; - - while(tree->left->left->next != NULL) { - - IR_NODE* var = createIRNode(IR_FUNCTION_ARGUMENT, tree->right->value); - - node->variables[node->variableIndex] = var; - node->variableIndex++; - - hashPut(node->variableMap, hashstr(tree->left->left->right->value), var); - - tree->left->left = tree->left->left->next; - } - - node->tree = tree->right; - - ctx->nodes[ctx->nodeIndex] = node; - ctx->nodeIndex++; - - hashPut(ctx->nodeMap, hash, node); - break; - - case AST_ASM_FUNCTION_DECLARATION: - hash = hashstr(tree->left->right->value); - - if(hashGet(ctx->nodeMap, hash) != NULL) { - printf("Assembly function %s is already defined!\n"); - return NULL; - } - - node = createIRNode(IR_ASM_FUNCTION, tree->left->right->value); - - node->value = tree->value; - node->valueSize = tree->valueSize; - - while(tree->left->left->next != NULL) { - - IR_NODE* var = createIRNode(IR_FUNCTION_ARGUMENT, tree->left->left->right->value); - - node->variables[node->variableIndex] = var; - node->variableIndex++; - - hashPut(node->variableMap, hashstr(tree->left->left->right->value), var); - - - tree->left->left = tree->left->left->next; - } - - ctx->nodes[ctx->nodeIndex] = node; - ctx->nodeIndex++; - - hashPut(ctx->nodeMap, hash, node); - - break; - - } - - tree = tree->next; - } - - return ctx; -} - /** * Compiles the Context tree to an executable named the provided file name. * @param ctx the IR context. * @param out the output file. */ -void compile(IR_CTX* ctx, FILE* out) { - - uint8_t* buff = malloc(sizeof(uint8_t) * 512); - int i = 0; - - int h = hashstr("main"); - - if(hashGet(ctx->nodeMap, h) == NULL) { - printf("Error: the main function wasn't defined!\n"); - return; - } - - IR_NODE* node = hashGet(ctx->nodeMap, h); - - if(node->nodeType != IR_FUNCTION) { - printf("Error: main must be a function!\n"); - return; - } - - while(node->tree != NULL) { - - if(node->tree->type == AST_FUNCTION_INVOKE) { - - int hash = hashstr(node->tree->value); - - IR_NODE* wa = hashGet(ctx->nodeMap, hash); - - if(wa == NULL) { - printf("Error: The %s function doesn't exist!\n", node->tree->value); - return; - } - - if(wa->nodeType == IR_ASM_FUNCTION) { - unsigned char b; - unsigned char* ptr = (unsigned char*) wa->value; - - for(int ii = 0; ii < wa->valueSize; ++ii) { - buff[i] = ptr[ii]; - ++i; - } - } - } - - node->tree = node->tree->next; - } - - //todo: change format based on user - compilePE(out, buff, i); +void compile(FILE* out) { } diff --git a/src/compiler/compiler.h b/src/compiler/compiler.h index 93ec267..c0e36ea 100644 --- a/src/compiler/compiler.h +++ b/src/compiler/compiler.h @@ -5,22 +5,11 @@ #ifndef COMPILER_H #define COMPILER_H -#include "../utils/hashmap.h" -#include "../parser/ast.h" - -#include "./ir.h" - -/** - * Parses the AST tree into a context. - * @param tree the AST tree. - */ -IR_CTX* makeContext(AST_NODE* tree); - /** * Compiles the Context tree to an executable named the provided name. * @param ctx the IR context. * @param char the output file. */ -void compile(IR_CTX* ctx, FILE* outputFileName); +void compile(FILE* outputFileName); #endif diff --git a/src/compiler/ir.c b/src/compiler/ir.c deleted file mode 100644 index 11a2af9..0000000 --- a/src/compiler/ir.c +++ /dev/null @@ -1,29 +0,0 @@ -/** - * The compiler's internal IR. - */ - -#include - -#include "./ir.h" - -#include "../utils/hashmap.h" - -/** - * Creates an IR node based on the type and the name given. - * @param type the IR type of the node. - * @param nodeName the name of the IR node. - */ -inline IR_NODE* createIRNode(IR_TYPE type, char* nodeName) { - IR_NODE* node = malloc(sizeof(IR_NODE)); - - node->nodeType = type; - node->nodeName = nodeName; - - node->variableIndex = 0; - - if(type == IR_FUNCTION) { - node->variableMap = createHashmap(512, 50); - } - - return node; -} diff --git a/src/compiler/ir.h b/src/compiler/ir.h deleted file mode 100644 index 43c6e59..0000000 --- a/src/compiler/ir.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The compiler's internal IR. - */ - -#include "../parser/ast.h" - -#include "../utils/hashmap.h" - -#ifndef IR_H -#define IR_H - -typedef enum { - IR_FUNCTION, - - IR_ASM_FUNCTION, - - IR_VARIABLE, - IR_FUNCTION_ARGUMENT, - IR_FUNCTION_BODY_VARIABLE -} IR_TYPE; - -/** - * An IR Node. - */ -typedef struct IR_NODE { - - IR_TYPE nodeType; - - // Shared Properties - - char* nodeName; - char* type; - - // Variable Properties - void* value; - int valueSize; - - // Function Properties - struct IR_NODE** variables; - int variableIndex; - - struct Hashmap* variableMap; - - AST_NODE* tree; -} IR_NODE; - -/** - * The overall IR context. - */ -typedef struct { - IR_NODE** nodes; - int nodeIndex; - - struct Hashmap* nodeMap; - - IR_NODE* mainFunc; - -} IR_CTX; - -/** - * Creates an IR node based on the type and the name given. - * @param type the IR type of the node. - * @param nodeName the name of the IR node. - */ -inline extern IR_NODE* createIRNode(IR_TYPE type, char* nodeName); - -#endif diff --git a/src/ir/instructions.h b/src/ir/instructions.h new file mode 100644 index 0000000..0286b9d --- /dev/null +++ b/src/ir/instructions.h @@ -0,0 +1,138 @@ +/** + * The instruction codes for the Quickfall IR. + */ + +#ifndef IR_INSTRUCTIONS +#define IR_INSTRUCTIONS + +/** + * The instruction codes of IR. + */ +typedef enum IR_INSTRUCTION_CODE { + + /** + * Swaps the current IR block. + * @param block the new IR block index in the context (function for instance). + */ + BLOCK_SWAP, + + /** + * Swaps the current IR block if a condition is met. + * @param block the new IR block index in the context (function for instance). + * @param cond the condition to match. + */ + COND_BLOCK_SWAP, + + /** + * Swaps the current IR block depending on a condition result. + * @param trueBlock the new IR block index in the context (function for instance) if the condition is met. + * @param falseBlock the new IR block index in the context (function for instance) if the condition isn't met. + * @param cond the condition. + */ + LOGICAL_BLOCK_SWAP, + + /** + * Allocates a set amount of bits in the stack. + * @param size the size of the pointer. + * @param ptr the pointer that is going to be allocated. + */ + S_ALLOC, + + /** + * Sets the value of the pointer's address to the provided element. + * @param val the new value (an integer for now). + * @param ptr the pointer containing the target address. + */ + PTR_SET, + + /** + * Loads the values of a specific address into a variable. + * @param var the output variable. + * @param ptr the pointer containing the target address. + */ + PTR_LOAD, + + + /** + * Adds two 32 bit integers together. + * @param output the output variable of the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + IADD, + + /** + * Subtracts two 32 bit integers together. + * @param output the output variable of the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + ISUB, + + /** + * Multiplies two 32 bit integers together. + * @param output the output variable of the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + IMUL, + + /** + * Divides two 32 bit integers together. + * @param output the output variable of the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + IDIV, + + /** + * Compares two 32 bit integers to check if they are equal. + * @param out the output variable containing the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + ICMP, + + /** + * Compares two 32 bit integers to check if the first one is higher than the second one. + * @param out the output variable containing the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + ICMP_H, + + /** + * Compares two 32 bit integers to check if the first one is higher or equal to the second one. + * @param out the output variable containing the result. + * @param i1 the first integer. + * @param i2 the second integer. + */ + ICMP_L, + + /** + * Moves a variable value into the parameter registers. + * @param var the variable holding the value. + * @param index the index of the parameter to register to. + */ + PRM_PUSH, + + /** + * Moves a variable value into the return value register. + * @param var the variable holding the value. + */ + RET_PUSH, + + /** + * Calls a function. + * @param funcName the functionName. + */ + CALL, + + /** + * Returns from a function. + */ + RET + +} IR_INSTRUCTION_CODE; + +#endif \ No newline at end of file diff --git a/src/ir/ir.c b/src/ir/ir.c new file mode 100644 index 0000000..dc33288 --- /dev/null +++ b/src/ir/ir.c @@ -0,0 +1,87 @@ +/** + * The Intermediate Representation of Quickfall Code. + */ + +#include +#include +#include + +#include "./instructions.h" +#include "./structs.h" + +#include "../parser/structs/tree.h" +#include "../parser/structs/functions.h" +#include "../parser/structs/variables.h" +#include "../parser/structs/values.h" + +#include "./irs/variables.h" +#include "./irs/values.h" +#include "./irs/functions.h" + +#include "../parser/ast.h" + +/** + * Appends an IR instruction into the basic block. + * @param block the IR basic block. + * @param instruction the instruction. + */ +void pushInstruction(IR_BASIC_BLOCK* block, IR_INSTRUCTION* instruction) { + if(block->allocatedSize == 0) { + block->instructions = malloc(sizeof(IR_INSTRUCTION*) * 20); + block->allocatedSize = 20; + } + + block->instructions[block->instructionCount] = instruction; + block->instructionCount++; +} + + +/** + * Appends an IR instruction into the basic block. + * @parma block the IR basic block. + * @param opCode the operation code of the instruction. + * @param params the parameters of the operation. + * @param paramsCount the count of the parameters of the operation. + */ +void appendInstruction(IR_BASIC_BLOCK* block, IR_INSTRUCTION_CODE code, void** params, int paramsCount) { + IR_INSTRUCTION* instruction = malloc(sizeof(IR_INSTRUCTION)); + + instruction->opCode = code; + instruction->params = params; + instruction->paramCount = paramsCount; + + pushInstruction(block, instruction); +} + + +/** + * Converts the AST tree into IR. + */ +IR_OUTPUT* parseIR(AST_TREE_BRANCH* node) { + IR_OUTPUT* out = malloc(sizeof(IR_OUTPUT)); + + out->allocatedBlockCount = 10; + out->blockCount = 0; + out->blocks = malloc(sizeof(IR_BASIC_BLOCK*) * out->allocatedBlockCount); + out->map = createHashmap(512,200); + + while(node != NULL) { + switch(node->type) { + case AST_TYPE_FUNCTION_DECLARATION: + parseFunction(out, (AST_FUNCTION_DEC*)node); + break; + case AST_TYPE_ASM_FUNCTION_DECLARATION: + parseASMFunction(out, (AST_ASM_FUNCTION_DEC*)node); + break; + case AST_TYPE_VARIABLE_DECLARATION: + parseVariableDeclaration(out->blocks[0], (AST_VARIABLE_DEC*)node); + break; + case AST_TYPE_VARIABLE_MODIFICATION: + parseVariableModification(out->blocks[0], (AST_VARIABLE_MOD*)node); + break; + } + node = node->next; + } + + return out; +} \ No newline at end of file diff --git a/src/ir/ir.h b/src/ir/ir.h new file mode 100644 index 0000000..e02e115 --- /dev/null +++ b/src/ir/ir.h @@ -0,0 +1,38 @@ +/** + * The Intermediate Representation of Quickfall Code. + */ + +#ifndef IR2_H +#define IR2_H + +#include "./instructions.h" +#include "./structs.h" + +#include "../parser/structs/variables.h" +#include "../parser/structs/functions.h" +#include "../parser/structs/tree.h" + +#include "../parser/ast.h" + +/** + * Appends an IR instruction into the basic block. + * @param block the IR basic block. + * @param instruction the instruction. + */ +void pushInstruction(IR_BASIC_BLOCK* block, IR_INSTRUCTION* instruction); + +/** + * Appends an IR instruction into the basic block. + * @parma block the IR basic block. + * @param opCode the operation code of the instruction. + * @param params the parameters of the operation. + * @param paramsCount the count of the parameters of the operation. + */ +void appendInstruction(IR_BASIC_BLOCK* block, IR_INSTRUCTION_CODE code, void** params, int paramsCount); + +/** + * Converts the AST tree into IR. + */ +IR_OUTPUT* parseIR(AST_TREE_BRANCH* node); + +#endif \ No newline at end of file diff --git a/src/ir/irs/functions.c b/src/ir/irs/functions.c new file mode 100644 index 0000000..bff5aeb --- /dev/null +++ b/src/ir/irs/functions.c @@ -0,0 +1,84 @@ +/** + * IR for function related. + */ + +#include +#include + +#include "../../qasm/parser/parser.h" + +#include "../structs.h" + +#include "../../parser/structs/functions.h" +#include "../../parser/structs/variables.h" +#include "../../parser/structs/tree.h" + +#include "../../parser/ast.h" + +#include "./variables.h" + +#include "../../utils/hash.h" +#include "../../utils/hashmap.h" + +/** + * Parses a AST function into IR. + * @param node the AST node representing the function. + */ +void parseFunction(IR_OUTPUT* out, AST_FUNCTION_DEC* node) { + int hash = hashstr(node->funcName); + IR_FUNCTION* func = malloc(sizeof(IR_FUNCTION)); + + func->startBlock = out->blockCount; + func->typeCount = node->parameterIndex; + + func->types = malloc(func->typeCount + 1); + + if(node->returnType != NULL) func->types[0] = node->returnType[0]; + else func->types[0] = 0x00; + + for(int i = 0; i < func->typeCount; ++i) { + func->types[i + 1] = node->parameters[i].type[0]; + } + + hashPut(out->map, hash, func); + + out->blocks[out->blockCount] = malloc(sizeof(IR_BASIC_BLOCK)); + out->blocks[out->blockCount]->instructions = NULL; + out->blocks[out->blockCount]->instructionCount = 0; + out->blocks[out->blockCount]->allocatedSize = 0; + + AST_TREE_BRANCH* branch = (AST_TREE_BRANCH*) node->body; + while(branch->next != NULL) { + branch = ((AST_TREE_BRANCH*)branch->next); + + switch(branch->type) { + case AST_TYPE_VARIABLE_DECLARATION: + parseVariableDeclaration(out->blocks[out->blockCount], (AST_VARIABLE_DEC*) branch); + break; + case AST_TYPE_VARIABLE_MODIFICATION: + parseVariableModification(out->blocks[out->blockCount], (AST_VARIABLE_MOD*)branch); + break; + } + } +} + +/** + * Parses a AST Asm function into IR. + * @param node the AST node representing the Asm function. + */ +void parseASMFunction(IR_OUTPUT* out, AST_ASM_FUNCTION_DEC* node) { + IR_FUNCTION* func = malloc(sizeof(IR_FUNCTION)); + func->startBlock = out->blockCount; + + func->types = malloc(1); + func->types[0] = 0x00; + func->typeCount = 1; + + hashPut(out->map, hashstr(node->funcName), func); + + out->blocks[out->blockCount] = malloc(sizeof(IR_BASIC_BLOCK)); + out->blocks[out->blockCount]->instructions = NULL; + out->blocks[out->blockCount]->instructionCount = 0; + + parseQAsmInstructions(out->blocks[out->blockCount], node->buff, node->buffIndex); +} \ No newline at end of file diff --git a/src/ir/irs/functions.h b/src/ir/irs/functions.h new file mode 100644 index 0000000..5bdb6a7 --- /dev/null +++ b/src/ir/irs/functions.h @@ -0,0 +1,24 @@ +/** + * IR for function related. + */ + +#include "../structs.h" +#include "../../parser/structs/functions.h" + + +#ifndef IR_FUNCTIONS_H +#define IR_FUNCTIONS_H + +/** + * Parses a AST function into IR. + * @param node the AST node representing the function. + */ +void parseFunction(IR_OUTPUT* out, AST_FUNCTION_DEC* node); + +/** + * Parses a AST Asm function into IR. + * @param node the AST node representing the Asm function. + */ +void parseASMFunction(IR_OUTPUT* out, AST_ASM_FUNCTION_DEC* node); + +#endif \ No newline at end of file diff --git a/src/ir/irs/values.c b/src/ir/irs/values.c new file mode 100644 index 0000000..f79d1a7 --- /dev/null +++ b/src/ir/irs/values.c @@ -0,0 +1,42 @@ +/** + * IR for value related. + */ + +#include + +#include "../../parser/ast.h" + +#include "../../parser/structs/values.h" +#include "../../parser/structs/tree.h" + +/** + * Parses the value into the buffer. + * @param buff the byte buffer. + * @param index the starting index of the buffer. + * @param value the value to parse. + */ +void parseValue(void** buff, int index, void* value) { + if(((AST_TREE_BRANCH*)value)->type == AST_TYPE_VALUE) { + AST_VALUE* val = (AST_VALUE*)value; + + if(val->valueType[0] == 0x01) { //int32 + int num = atoi(val->value); + + buff[index] = malloc(4); + + ((unsigned char*)buff[index])[0] = (num >> 24) & 0xFF; + ((unsigned char*)buff[index])[1] = (num >> 16) & 0xFF; + ((unsigned char*)buff[index])[2] = (num >> 8) & 0xFF; + ((unsigned char*)buff[index])[3] = num & 0xFF; + } + } +} + +/** + * Gets the value size for a certain type for a parameter. + * @param type the type's byte indentifier. + */ +int getValueSize(unsigned char type) { + if(type == 0x01) return 4; // int32 type -> 4 bytes + return 0; +} diff --git a/src/ir/irs/values.h b/src/ir/irs/values.h new file mode 100644 index 0000000..018b3ad --- /dev/null +++ b/src/ir/irs/values.h @@ -0,0 +1,22 @@ +/** + * IR for value related. + */ + +#ifndef IR_VALUES_H +#define IR_VALUES_H + +/** + * Parses the value into the buffer. + * @param buff the byte buffer. + * @param index the index of the buffer. + * @param value the value to parse. + */ +void parseValue(void** buff, int index, void* value); + +/** + * Gets the value size for a certain type for a parameter. + * @param type the type's byte indentifier. + */ +int getValueSize(unsigned char type); + +#endif \ No newline at end of file diff --git a/src/ir/irs/variables.c b/src/ir/irs/variables.c new file mode 100644 index 0000000..fcd7b99 --- /dev/null +++ b/src/ir/irs/variables.c @@ -0,0 +1,61 @@ +/** + * IR for variable related. + */ + +#include +#include +#include + +#include "../../parser/structs/variables.h" + +#include "./values.h" + +#include "../ir.h" + +/** + * Parses a variable declaration. + * @param block the IR basic block to append to. + * @param node the AST node representing the variable. + */ +void parseVariableDeclaration(IR_BASIC_BLOCK* block, AST_VARIABLE_DEC* node) { + int allocSize = 0; + if(node->type[0] == 0x01) allocSize = 32; // int32 + + void** params = malloc(sizeof(void*) * 2); + + char* name = node->name; + + params[0] = malloc(4); + + ((unsigned char*)params[0])[0] = (allocSize >> 24) & 0xFF; + ((unsigned char*)params[0])[1] = (allocSize >> 16) & 0xFF; + ((unsigned char*)params[0])[2] = (allocSize >> 8) & 0xFF; + ((unsigned char*)params[0])[3] = allocSize & 0xFF; + + params[1] = node->name; + + appendInstruction(block, S_ALLOC, params, 2); + + if(node->value != NULL) { + params = malloc(sizeof(void*) * 2); + params[0] = node->name; + + parseValue(params, 1, node->value); + + appendInstruction(block, PTR_SET, params, 2); + } +} + +/** + * Parses a variable modification. + * @param block the IR basic block to append to. + * @param node the AST node representing the variable. + */ +inline void parseVariableModification(IR_BASIC_BLOCK* block, AST_VARIABLE_MOD* node) { + void** params = malloc(sizeof(void*) * 2); + + params[0] = node->name; + + parseValue(params, 1, node->value); + appendInstruction(block, PTR_SET, params, 2); +} \ No newline at end of file diff --git a/src/ir/irs/variables.h b/src/ir/irs/variables.h new file mode 100644 index 0000000..f77484d --- /dev/null +++ b/src/ir/irs/variables.h @@ -0,0 +1,26 @@ +/** + * IR for variable related. + */ + +#include "../../parser/structs/variables.h" + +#include "../ir.h" + +#ifndef IR_VARIABLES_H +#define IR_VARIABLES_H + +/** + * Parses a variable declaration. + * @param block the IR basic block to append to. + * @param node the AST node representing the variable. + */ +void parseVariableDeclaration(IR_BASIC_BLOCK* block, AST_VARIABLE_DEC* node); + +/** + * Parses a variable modification. + * @param block the IR basic block to append to. + * @param node the AST node representing the variable. + */ +inline void parseVariableModification(IR_BASIC_BLOCK* block, AST_VARIABLE_MOD* node); + +#endif \ No newline at end of file diff --git a/src/ir/structs.h b/src/ir/structs.h new file mode 100644 index 0000000..1cb55f7 --- /dev/null +++ b/src/ir/structs.h @@ -0,0 +1,54 @@ +/** + * Quickfall IR Structures. + */ + +#include "../utils/hashmap.h" + +#ifndef IR_STRUCTS_H +#define IR_STRUCTS_H + +/** + * An IR instruction. + */ +typedef struct IR_INSTRUCTION { + + unsigned char opCode; + + void** params; + int paramCount; + +} IR_INSTRUCTION; + +/** + * An IR basic block. + */ +typedef struct IR_BASIC_BLOCK { + + IR_INSTRUCTION** instructions; + int instructionCount; + int allocatedSize; + +} IR_BASIC_BLOCK; + +/** + * An IR function. + */ +typedef struct IR_FUNCTION { + + int startBlock; + + unsigned char* types; + int typeCount; + +} IR_FUNCTION; + +typedef struct IR_OUTPUT { + + IR_BASIC_BLOCK** blocks; + int blockCount; + int allocatedBlockCount; + + struct Hashmap* map; +} IR_OUTPUT; + +#endif \ No newline at end of file diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index ca4c82d..1bdebec 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -79,7 +79,7 @@ LEXER_RESULT runLexer(char* string, int size) { int keywordLen = 0; - while(isalpha(c)) { + while(isalpha(c) || isdigit(c)) { buff[keywordLen] = c; buff[keywordLen + 1] = '\0'; keywordLen++; @@ -109,6 +109,9 @@ LEXER_RESULT runLexer(char* string, int size) { else if(strcmp(buff, "var") == 0) { pushToken(&result, VAR); } + else if(strcmp(buff, "int32") == 0) { + pushToken(&result, TYPE_INT32); + } else { pushToken(&result, KEYWORD); result.tokens[result.size - 1].value = buff; diff --git a/src/lexer/tokens.h b/src/lexer/tokens.h index 3917555..e21bdce 100644 --- a/src/lexer/tokens.h +++ b/src/lexer/tokens.h @@ -22,7 +22,9 @@ typedef enum { DECLARE, USE, NONE, - MATH_OP + MATH_OP, + + TYPE_INT32 } TOKEN_TYPE; /** diff --git a/src/parser/ast.c b/src/parser/ast.c deleted file mode 100644 index 4ccbfeb..0000000 --- a/src/parser/ast.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * The AST Nodes in Quickfall. - */ - -#include - -#include "./ast.h" - -/** - * Creates a new AST Node. - * @param type the AST type of the node. - */ -AST_NODE* createASTNode(AST_NODE_TYPE type) { - AST_NODE* node = malloc(sizeof(AST_NODE)); - - node->valueSize = 0; - node->type = type; - node->left = NULL; - node->right = NULL; - node->next = NULL; - - return node; -} diff --git a/src/parser/ast.h b/src/parser/ast.h index 7d4c7b1..666587c 100644 --- a/src/parser/ast.h +++ b/src/parser/ast.h @@ -1,61 +1,22 @@ /** - * The header file of AST nodes in Quickfall. + * The AST of Quickfall. */ #ifndef AST_H #define AST_H -/** - * The type of AST Node(s). - */ typedef enum { - AST_ROOT, // A root of an AST tree, can either represent the first node of the tree or a function body. - - AST_TYPE, // Represents a datatype precision in an AST Node. - AST_VARIABLE_NAME, // Represents a variable / parameter name precision in an AST Node. - AST_VARIABLE_VALUE, - - AST_VARIABLE_DECLARATION, - AST_VARIABLE_REFERENCE, - - AST_ASM_FUNCTION_DECLARATION, - - AST_FUNCTION_DECLARATION, - AST_FUNCTION_HEADER, - - AST_FUNCTION_INVOKE, - - AST_FUNCTION_ROOT, + AST_TYPE_ROOT, + AST_TYPE_FUNC_ROOT, - AST_MATH_OPERATOR, - AST_MATH_OPERATION, - AST_MATH_OP_HEADER, + AST_TYPE_FUNCTION_DECLARATION, + AST_TYPE_ASM_FUNCTION_DECLARATION, - AST_PARAMETER // A function parameter AST Node, used in function declaration. -} AST_NODE_TYPE; + AST_TYPE_VARIABLE_DECLARATION, + AST_TYPE_VARIABLE_MODIFICATION, + AST_TYPE_VALUE -/** - * An AST Node. Has a tree-ish structure. - */ -typedef struct AST_NODE { - - struct AST_NODE* left; - struct AST_NODE* right; - struct AST_NODE* next; - - AST_NODE_TYPE type; - - int valueSize; - char* value; - int endingIndex; // The index which the parsing ended - -} AST_NODE; - -/** - * Creates a new AST Node. - * @param type the AST type of the node. - */ -AST_NODE* createASTNode(AST_NODE_TYPE type); +} AST_TYPE; -#endif +#endif \ No newline at end of file diff --git a/src/parser/asts/functions.c b/src/parser/asts/functions.c index d70a500..662f83f 100644 --- a/src/parser/asts/functions.c +++ b/src/parser/asts/functions.c @@ -1,215 +1,168 @@ /** - * Function-related AST parsing. + * Parsing for function related ASTs. */ -#include +#include +#include #include -#include "./variables.h" +#include "./functions.h" + +#include "../structs/functions.h" #include "../parser.h" #include "../ast.h" -#include "../../lexer/tokens.h" #include "../../lexer/lexer.h" -#include "../../utils/logging.c" - /** - * Parse the parameters from a function definition (for example). - * @param result the lexer result. - * @param index the starting index of the parsing. + * Parses a function declaration into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. */ -AST_NODE* parseParameters(LEXER_RESULT result, int index) { - - AST_NODE* root = createASTNode(AST_PARAMETER); - AST_NODE* current = root; - - int stack = 0; - - for(; index < result.size + 1; ++index) { - TOKEN t = result.tokens[index]; - - switch(t.type) { - case COMMA: - if(stack == 0) { - return NULL; - } - - stack = 0; - current->next = createASTNode(AST_PARAMETER); - current = current->next; - break; - case NONE: - case KEYWORD: - if(stack == 2) { - return NULL; - } - - TOKEN next = result.tokens[index + 1]; - - if(next.type == NONE || next.type == KEYWORD) { - current->left = createASTNode(AST_TYPE); - current->left->value = next.value; - } - else { - current->right = createASTNode(AST_VARIABLE_NAME); - current->right->value = t.value; - } - - stack++; - break; - case PAREN_CLOSE: - root->endingIndex = index; - return root; - case PAREN_OPEN: - continue; - default: - printf("Type: %d", t.type); - return NULL; - - } - } +AST_FUNCTION_DEC* parseFunctionDeclaration(LEXER_RESULT result, int index) { + AST_FUNCTION_DEC* func = malloc(sizeof(AST_FUNCTION_DEC)); + func->returnType = malloc(1); + + func->type = AST_TYPE_FUNCTION_DECLARATION; + + int offset; + + switch(result.tokens[index + 2].type) { + case PAREN_OPEN: + if(result.tokens[index + 1].type != KEYWORD) { + printf("Error: Excepted a keyword as function name!\n"); + return NULL; + } + + func->funcName = result.tokens[index + 1].value; + func->returnType[0] = 0x00; + offset = 3; + break; + case KEYWORD: + if(result.tokens[index + 1].type != TYPE_INT32) { + printf("Error: Invalid type as function return type!\n"); + return NULL; + } + + func->funcName = result.tokens[index + 2].value; + func->returnType[0] = 0x01; + offset = 4; + break; + + default: + printf("Error: couldn't parse function declaration!\n"); + return NULL; + } + + index += offset; + + parseFunctionParameters(func, result, index); + + if(result.tokens[func->endingIndex + 1].type != BRACKETS_OPEN) { + printf("Error: Excepted function body!\n"); + return NULL; + } + + void* root = parseRoot(result, func->endingIndex + 2, AST_TYPE_FUNC_ROOT); + + if(root == NULL) { + printf("Error: couldn't parse function body!\n"); + return NULL; + } + + func->body = root; + func->endingIndex = ((AST_TREE_BRANCH*)root)->endingIndex; + + return func; } + /** - * Parses the arguments passed during a function call (for example). - * @param result the result of the lexer. - * @param index the starting index of the parsing. + * Parses an ASM function declaration into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. */ -AST_NODE* parseArguments(LEXER_RESULT result, int index) { - AST_NODE* root = NULL; - AST_NODE* current = root; - - for(; index < result.size + 1; ++index) { - TOKEN t = result.tokens[index]; - - if(t.type == PAREN_CLOSE) { - return root; - } - - AST_NODE* arg = parseVariableValue(result, index); - - if(arg == NULL) return NULL; - - index = arg->endingIndex; - - if(root == NULL) { - root = arg; - current = root; - } - else { - current->next = arg; - } - } - - return NULL; -} - -AST_NODE* parseFunctionDeclaration(LEXER_RESULT result, int index) { - - AST_NODE* node = createASTNode(AST_FUNCTION_DECLARATION); - node->left = createASTNode(AST_FUNCTION_HEADER); - - if(result.tokens[index].type != KEYWORD) { - return NULL; - } - - int off = 1; - - switch(result.tokens[index + 1].type) { - case KEYWORD: - node->left->value = result.tokens[index].value; - node->left->right = createASTNode(AST_VARIABLE_NAME); - node->left->right->value = result.tokens[index + 1].value; - ++off; - break; - case PAREN_OPEN: - node->left->value = "void"; - node->left->right = createASTNode(AST_VARIABLE_NAME); - node->left->right->value = result.tokens[index].value; - break; - default: - return NULL; - } - - AST_NODE* params = parseParameters(result, index + off); - - if(params == NULL) return NULL; - - node->left->left = params; +AST_ASM_FUNCTION_DEC* parseASMFunctionDeclaration(LEXER_RESULT result, int index) { + AST_ASM_FUNCTION_DEC* func = malloc(sizeof(AST_ASM_FUNCTION_DEC)); - node->right = parseNodes(result, params->endingIndex, AST_FUNCTION_ROOT); + if(result.tokens[index + 1].type != KEYWORD) { + printf("Error: Excepted keyword as ASM function name!\n"); + return NULL; + } - node->endingIndex = node->right->endingIndex; + func->type = AST_TYPE_ASM_FUNCTION_DECLARATION; + func->funcName = result.tokens[index + 1].value; - return node; -} - -AST_NODE* parseASMFunctionDeclaration(LEXER_RESULT result, int index) { - AST_NODE* node = createASTNode(AST_ASM_FUNCTION_DECLARATION); - - node->left = createASTNode(AST_FUNCTION_HEADER); - - if(result.tokens[index + 1].type != KEYWORD) { - return NULL; - } - - node->left->right = createASTNode(AST_VARIABLE_NAME); - node->left->right->value = result.tokens[index + 1].value; - - AST_NODE* params = parseParameters(result, index + 2); - - if(params == NULL) { - return NULL; - } - - node->left->left = params; - - index = params->endingIndex + 2; - - int buffSize = 32; - int buffIndex = 0; - uint8_t* buff = malloc(sizeof(uint8_t) * buffSize); + parseFunctionParameters((AST_FUNCTION_DEC*)func, result, index + 3); - for(; index <= result.size; ++index) { - TOKEN t = result.tokens[index]; + index = func->endingIndex; - if(t.type == BRACKETS_CLOSE) { - break; - } + if(result.tokens[index + 1].type != BRACKETS_OPEN || result.tokens[index + 2].type != STRING || result.tokens[index + 3].type != BRACKETS_CLOSE) { + printf("Error: Badly made ASM function body!\n"); + return NULL; + } - if(t.type != NUMBER) { - return NULL; - } + func->buff = result.tokens[index + 2].value; + func->buffIndex = strlen(func->buff); - buff[buffIndex] = strtol(t.value, NULL, 16); - buffIndex++; - } - - node->endingIndex = index; - - buff = realloc(buff, sizeof(uint8_t) * buffIndex); - - node->valueSize = buffIndex; - node->value = buff; - - return node; + return func; } -AST_NODE* parseFunctionInvoke(LEXER_RESULT result, int index) { - AST_NODE* node = createASTNode(AST_FUNCTION_INVOKE); - - node->value = result.tokens[index].value; - - AST_NODE* args = parseArguments(result, index + 2); - - node->endingIndex = index; - if(args != NULL) { - node->right = args; - node->endingIndex = args->endingIndex; - } - - return node; -} +/** + * Parses the parameters of a function into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. + */ +void parseFunctionParameters(AST_FUNCTION_DEC* func, LEXER_RESULT result, int index) { + int allocated = 10; + func->parameterIndex = 0; + + for(; index < result.size; ++index) { + TOKEN t = result.tokens[index]; + + switch(t.type) { + case TYPE_INT32: + if(result.tokens[index + 1].type != KEYWORD) { + printf("Error: Excepted keyword as parameter name!\n"); + return; + } + + func->parameters[func->parameterIndex].name = result.tokens[index + 1].value; + func->parameters[func->parameterIndex].type[0] = 0x01; // i32 + + func->parameterIndex++; + if(func->parameterIndex > allocated) { + allocated *= 1.25; + func->parameters = realloc(func->parameters, sizeof(AST_PARAMETER) * allocated); + } + break; + case KEYWORD: + if(result.tokens[index + 1].type != COMMA) { + printf("Error: Excepted comma after parameter!\n"); + return; + } + + if(result.tokens[index - 1].type == COMMA) { + func->parameters[func->parameterIndex].name = result.tokens[index].value; + func->parameters[func->parameterIndex].type[0] = 0x00; + func->parameterIndex++; + if(func->parameterIndex > allocated) { + allocated *= 1.25; + func->parameters = realloc(func->parameters, sizeof(AST_PARAMETER) * allocated); + } + } + + break; + + case PAREN_CLOSE: + func->endingIndex = index; + return; + + default: + printf("Error: Disallowed token type %d in parameters!\n", t.type); + return; + } + } +} \ No newline at end of file diff --git a/src/parser/asts/functions.h b/src/parser/asts/functions.h index e30cf77..22884ce 100644 --- a/src/parser/asts/functions.h +++ b/src/parser/asts/functions.h @@ -1,47 +1,33 @@ /** - * Function-related AST parsing. + * Parsing for function related ASTs. */ -#include "../../lexer/lexer.h" - -#include "../ast.h" +#include "../structs/functions.h" -#ifndef AST_FUNC_H -#define AST_FUNC_H - -/** - * Parse the parameters from a function defintition (for example). - * @param result the lexer result. - * @param index the starting index of the parsing. - */ -AST_NODE* parseParameters(LEXER_RESULT result, int index); +#include "../../lexer/lexer.h" -/** - * Parses the arguments from a function call (for example). - * @param result the lexer result. - * @param index the starting index of the parsing. - */ -AST_NODE* parseArguments(LEXER_RESULT result, int index); +#ifndef FUNCTIONS_AST_H +#define FUNCTIONS_AST_H /** - * Parses a function declaration. - * @param result the lexer result. - * @param index the starting index of the parsing. + * Parses a function declaration into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. */ -AST_NODE* parseFunctionDeclaration(LEXER_RESULT result, int index); +AST_FUNCTION_DEC* parseFunctionDeclaration(LEXER_RESULT result, int index); /** - * Parses an ASM function declaration. - * @param result the lexer result. - * @param index the starting index of the parsing. + * Parses an ASM function declaration into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. */ -AST_NODE* parseASMFunctionDeclaration(LEXER_RESULT result, int index); +AST_ASM_FUNCTION_DEC* parseASMFunctionDeclaration(LEXER_RESULT result, int index); /** - * Parses an function invocation. - * @param result the lexer result. - * @param index the starting index of the parsing. + * Parses the parameters of a function into AST. + * @param result the Lexer result. + * @param index the index of the start of the parsing. */ -AST_NODE* parseFunctionInvoke(LEXER_RESULT result, int index); +void parseFunctionParameters(AST_FUNCTION_DEC* func, LEXER_RESULT result, int index); -#endif +#endif \ No newline at end of file diff --git a/src/parser/asts/math.c b/src/parser/asts/math.c deleted file mode 100644 index b68ac3b..0000000 --- a/src/parser/asts/math.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Math ASTs for the Quickfall parser. - */ - -#include - -#include "../../lexer/lexer.h" - -#include "../ast.h" -#include "./variables.h" - -/** - * Parses the mathematical operation. - * @param result the lexer result. - * @param index the starting index. - */ -AST_NODE* parseMathematicalOpNode(LEXER_RESULT result, int index) { - AST_NODE* node = createASTNode(AST_MATH_OPERATION); - node->left = createASTNode(AST_MATH_OP_HEADER); - - node->left->left = createASTNode(AST_VARIABLE_NAME); - node->left->left->value = result.tokens[index].value; - - node->left->right = createASTNode(AST_MATH_OPERATOR); - - node->left->right->value = malloc(2); - node->left->right->value[0] = result.tokens[index + 1].value[0]; - node->left->right->value[1] = '\0'; - - node->value = malloc(1); - - if(result.size >= index + 2 && result.tokens[index + 2].type == DECLARE) { - node->value[0] = '1'; - } - - node->right = parseVariableValue(result, index + 2); - node->endingIndex = node->right->endingIndex; - - return node; -} diff --git a/src/parser/asts/math.h b/src/parser/asts/math.h deleted file mode 100644 index f69c66b..0000000 --- a/src/parser/asts/math.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Math ASTs for the Quickfall parser. - */ - -#include "../ast.h" - -#ifndef AST_MATH_H -#define AST_MATH_H - -/** - * Parses the mathematical operation. - * @param result the lexer result. - * @param index the starting index. - */ -AST_NODE* parseMathematicalOpNode(LEXER_RESULT, int index); - -#endif \ No newline at end of file diff --git a/src/parser/asts/values.c b/src/parser/asts/values.c new file mode 100644 index 0000000..317f59d --- /dev/null +++ b/src/parser/asts/values.c @@ -0,0 +1,57 @@ +/** + * Parsing for value related ASTs. + */ + +#include +#include + +#include "../structs/values.h" + +#include "../ast.h" + +#include "../../lexer/lexer.h" + +/** + * Parses an AST value on the lexer result. + * @param result the Lexer result. + * @param index the index of the start of the parsing. + */ +AST_VALUE* parseASTValue(LEXER_RESULT result, int index) { + AST_VALUE* value = malloc(sizeof(AST_VALUE)); + value->astType = AST_TYPE_VALUE; + + switch(result.tokens[index].type) { + case NUMBER: + value->valueType = malloc(1); + value->valueType[0] = 0x01; //i32 + break; + default: + printf("Error: Couldn't parse token %d as a value!\n", result.tokens[index].type); + return value; + } + + value->endingIndex = index + 1; + value->value = result.tokens[index].value; + + return value; +} + +/** + * Parses an actual expression as value instead of just one token. + * @param result the Lexer result. + * @param index the index of the start of the parsing. + */ +void* parseValueGroup(LEXER_RESULT result, int index) { + switch(result.tokens[index].type) { + case NUMBER: + if(result.tokens[index + 1].type == MATH_OP) { + //todo: parse math op. + } + + return parseASTValue(result, index); + break; + default: + printf("Error: couldn't parse value token group!\n"); + return NULL; + } +} \ No newline at end of file diff --git a/src/parser/asts/values.h b/src/parser/asts/values.h new file mode 100644 index 0000000..0c96b4e --- /dev/null +++ b/src/parser/asts/values.h @@ -0,0 +1,26 @@ +/** + * Parsing for value related ASTs. + */ + +#include "../structs/values.h" + +#include "../../lexer/lexer.h" + +#ifndef VALUES_AST_H +#define VALUES_AST_H + +/** + * Parses an AST value on the lexer result. + * @param result the Lexer result. + * @param index the index of the start of the parsing. + */ +AST_VALUE* parseASTValue(LEXER_RESULT result, int index); + +/** + * Parses an actual expression as value instead of just one token. + * @param result the Lexer result. + * @param index the index of the start of the parsing. + */ +void* parseValueGroup(LEXER_RESULT result, int index); + +#endif \ No newline at end of file diff --git a/src/parser/asts/variables.c b/src/parser/asts/variables.c index 5241d31..77e4dfb 100644 --- a/src/parser/asts/variables.c +++ b/src/parser/asts/variables.c @@ -1,72 +1,85 @@ /** - * Variable-related AST parsing. + * Parsing for variable related ASTs. */ -#include "../../lexer/lexer.h" -#include "../../lexer/tokens.h" - -#include "./math.h" - -#include "../ast.h" - -AST_NODE* parseVariableValue(LEXER_RESULT result, int index) { - TOKEN t = result.tokens[index]; - - if(t.type == NUMBER || t.type == STRING || t.type == BOOLEAN_VALUE) { - AST_NODE* node = createASTNode(AST_VARIABLE_VALUE); - node->endingIndex = index; - node->left = createASTNode(AST_TYPE); - - switch(t.type) { - case NUMBER: - if(result.size >= index + 1 && result.tokens[index + 1].type == MATH_OP) return parseMathematicalOpNode(result, index); - - node->left->value = "n"; - - case STRING: - node->left->value = "s"; - break; - default: - node->left->value = "b"; - - } +#include +#include - node->value = t.value; - return node; - } +#include "../structs/variables.h" +#include "../structs/tree.h" - if(t.type == KEYWORD) { - AST_NODE* node = createASTNode(AST_VARIABLE_REFERENCE); - node->endingIndex = index + 1; - node->value = t.value; +#include "./values.h" - return node; - } +#include "../ast.h" -} +#include "../../lexer/lexer.h" /** * Parses a variable declaration. - * @param result the lexer result. - * @param index the starting index. + * @param result the Lexer result. + * @param index the index where the parsing needs to start. */ -AST_NODE* parseVariableDeclaration(LEXER_RESULT result, int index) { - AST_NODE* node = createASTNode(AST_VARIABLE_DECLARATION); +AST_VARIABLE_DEC* parseASTVariableDeclaration(LEXER_RESULT result, int index) { + AST_VARIABLE_DEC* var = malloc(sizeof(AST_VARIABLE_DEC)); + var->astType = AST_TYPE_VARIABLE_DECLARATION; + var->type = malloc(1); + + switch(result.tokens[index].type) { + case TYPE_INT32: + var->type[0] = 0x01; + break; + case VAR: + var->type[0] = 0x00; + break; + default: + printf("Error: Disallowed token as variable type!\n"); + return NULL; + } + + if(result.tokens[index + 1].type != KEYWORD) { + printf("Error: Excepted a keyword for variable name!\n"); + return NULL; + } + + var->name = result.tokens[index + 1].value; + + if(result.tokens[index + 2].type == DECLARE) { + void* value = parseValueGroup(result, index + 3); + + if(value == NULL) { + printf("Error: Couldn't parse variable value group!\n"); + return NULL; + } + + var->endingIndex = ((AST_TREE_BRANCH*)value)->endingIndex; + + var->value = value; + } + + return var; +} - if(result.tokens[index].type == VAR) { - node->value = "none"; - } - else { - node->value = result.tokens[index].value; - } - node->left = createASTNode(AST_VARIABLE_NAME); - node->left->value = result.tokens[index + 1].value; +/** + * Parses a variable modification. + * @param result the Lexer result. + * @param index the index where the parsing needs to start. + */ +AST_VARIABLE_MOD* parseVariableModification(LEXER_RESULT result, int index) { + AST_VARIABLE_MOD* mod = malloc(sizeof(AST_VARIABLE_MOD)); + mod->type = AST_TYPE_VARIABLE_MODIFICATION; - node->right = parseVariableValue(result, index + 3); + mod->name = result.tokens[index].value; - if(node->right != NULL) node->endingIndex = node->right->endingIndex; - else node->endingIndex = index + 2; + void* value = parseValueGroup(result, index + 2); - return node; -} + if(value == NULL) { + printf("Error: Couldn't parse variable value group in redefinition!\n"); + return NULL; + } + + mod->value = value; + mod->endingIndex = ((AST_TREE_BRANCH*)value)->endingIndex; + + return mod; +} \ No newline at end of file diff --git a/src/parser/asts/variables.h b/src/parser/asts/variables.h index e05205b..ebf12ea 100644 --- a/src/parser/asts/variables.h +++ b/src/parser/asts/variables.h @@ -1,26 +1,26 @@ /** - * Variable-related AST parsing. + * Parsing for variable related ASTs. */ -#include "../ast.h" +#include "../structs/variables.h" #include "../../lexer/lexer.h" -#ifndef AST_VARIABLES_H -#define AST_VARIABLES_H +#ifndef VARIABLES_ASTS_H +#define VARIABLES_ASTS_H /** - * Parses a variable value. - * @param result the lexer result. - * @param index the starting index. + * Parses a variable declaration. + * @param result the Lexer result. + * @param index the index where the parsing needs to start. */ -AST_NODE* parseVariableValue(LEXER_RESULT result, int index); +AST_VARIABLE_DEC* parseASTVariableDeclaration(LEXER_RESULT result, int index); /** - * Parses a variable declaration. - * @param result the lexer result. - * @param index the starting index. + * Parses a variable modification. + * @param result the Lexer result. + * @param index the index where the parsing needs to start. */ -AST_NODE* parseVariableDeclaration(LEXER_RESULT result, int index); +AST_VARIABLE_MOD* parseVariableModification(LEXER_RESULT result, int index); -#endif +#endif \ No newline at end of file diff --git a/src/parser/parser.c b/src/parser/parser.c index 5c3f26d..be7ae81 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1,77 +1,112 @@ /** - * The parser of Quickfall. + * The Quickfall Parser & AST Generator. */ #include +#include -#include "../lexer/tokens.h" -#include "../lexer/lexer.h" +#include "./parser.h" #include "./ast.h" +#include "../lexer/lexer.h" + +#include "./structs/tree.h" +#include "./structs/variables.h" + #include "./asts/variables.h" #include "./asts/functions.h" + /** - * Parses the lexer tokens into nodes starting from the index. - * @param result the LexerResult provided by the lexer. - * @param index the starting index. + * Parses the Lexer result into an AST root. + * @param result the Lexer result. + * @param startingIndex the starting Index. + * @param type the output AST type. */ -AST_NODE* parseNodes(LEXER_RESULT result, int index, AST_NODE_TYPE type) { - AST_NODE* root = createASTNode(type); - AST_NODE* current = root; - - for(; index <= result.size; ++index) { - TOKEN t = result.tokens[index]; - - AST_NODE* node = NULL; - - switch(t.type) { - case BRACKETS_CLOSE: - if(type == AST_FUNCTION_ROOT) { - root->endingIndex = index; - return root; - } - break; - case FUNCTION: - node = parseFunctionDeclaration(result, index + 1); - if(node != NULL) { - current->next = node; - current = node; - index = node->endingIndex; - } - - break; - case VAR: - node = parseVariableDeclaration(result, index); - if(node != NULL) { - current->next = node; - current = node; - index = node->endingIndex; - } - break; - case ASM_FUNCTION: - node = parseASMFunctionDeclaration(result, index); - - if(node != NULL) { - current->next = node; - current = node; - index = node->endingIndex; - } - break; - case KEYWORD: - if(result.tokens[index + 1].type == PAREN_OPEN) { - node = parseFunctionInvoke(result, index); - - if(node != NULL) { - current->next = node; - current = node; - index = node->endingIndex; - } - } - - } - } - - return root; +void* parseRoot(LEXER_RESULT result, int startingIndex, AST_TYPE type) { + AST_TREE_BRANCH* root = malloc(sizeof(AST_TREE_BRANCH)); + AST_TREE_BRANCH* curr = root; + + root->type = 0x99; + + for(int i = startingIndex; i < result.size; ++i) { + TOKEN t = result.tokens[i]; + + switch(t.type) { + case TYPE_INT32: + case VAR: + void* node = parseASTVariableDeclaration(result, i); + if(node != NULL) { + curr->next = node; + curr = node; + } + i = ((AST_TREE_BRANCH*)node)->endingIndex; + break; + + case KEYWORD: + if(result.tokens[i + 1].type == DECLARE) { + void* node = parseVariableModification(result, i); + if(node != NULL) { + curr->next = node; + curr = node; + } + i = ((AST_TREE_BRANCH*)node)->endingIndex; + break; + } + break; + + case FUNCTION: + node = parseFunctionDeclaration(result, i); + if(node != NULL) { + curr->next = node; + curr = node; + } + i = ((AST_TREE_BRANCH*)node)->endingIndex; + break; + + case ASM_FUNCTION: + node = parseASMFunctionDeclaration(result, i); + if(node != NULL) { + curr->next = node; + curr = node; + } + i = ((AST_TREE_BRANCH*)node)->endingIndex; // todo: fix asmf ending index + break; + + case BRACKETS_CLOSE: + if(type == AST_TYPE_FUNC_ROOT) { + root->endingIndex = i; + return root; + } + break; + + default: + printf("Error: Unexcepted token %d!\n", t.type); + break; + } + root->endingIndex = i; + } + + curr->next = NULL; + return root; } + +/** + * Appends a new node in the AST tree. + * @param curr the current AST node. + * @param root the root of the AST tree. + * @param node the node to add to the tree. + */ +void append(AST_TREE_BRANCH* curr, AST_TREE_BRANCH* root, void* node) { + if(node == NULL) return; + + if(curr == NULL) { + root = node; + curr = root; + } + else { + curr->next = node; + curr = node; + } +} \ No newline at end of file diff --git a/src/parser/parser.h b/src/parser/parser.h index 1759e02..605bba4 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -1,19 +1,29 @@ /** - * The parser of Quickfall. + * The Quickfall Parser & AST Generator. */ -#include "../lexer/lexer.h" #include "./ast.h" +#include "./structs/tree.h" + +#include "../lexer/lexer.h" -#ifndef PARSER_2_H -#define PARSER_2_H +#ifndef PARSER_H +#define PARSER_H + +/** + * Parses the Lexer result into an AST root. + * @param result the Lexer result. + * @param startIndex the starting Index. + * @param type the output AST type. + */ +void* parseRoot(LEXER_RESULT result, int startingIndex, AST_TYPE type); /** - * Parses the lexer tokens into nodes starting from the index. - * @param result the LexerResult provided by the lexer. - * @param index the starting index. - * @param type the AST node type to return. + * Appends a new node in the AST tree. + * @param curr the current AST node. + * @param root the root of the AST tree. + * @param node the node to add to the tree. */ -AST_NODE* parseNodes(LEXER_RESULT result, int index, AST_NODE_TYPE type); +void append(AST_TREE_BRANCH* curr, AST_TREE_BRANCH* root, void* node); -#endif +#endif \ No newline at end of file diff --git a/src/parser/structs/functions.h b/src/parser/structs/functions.h new file mode 100644 index 0000000..9218d6d --- /dev/null +++ b/src/parser/structs/functions.h @@ -0,0 +1,69 @@ +/** + * AST structure definitions for function related ASTs. + */ + +#ifndef FUNCTIONS_STRUCT_H +#define FUNCTIONS_STRUCT_H + +/** + * The function parameter structure. + */ +typedef struct AST_PARAMETER { + + unsigned char* type; // The datatype in bytes. + char* name; // The name of the parameter + +} AST_PARAMETER; + + +/** + * The function declaration structure. + */ +typedef struct AST_FUNCTION_DEF { + unsigned char type; // The type of the AST node (unused.) + void* next; + int endingIndex; + + char* funcName; + + AST_PARAMETER* parameters; + int parameterIndex; + + unsigned char* returnType; + void* body; + +} AST_FUNCTION_DEC; + + +/** + * The ASM function declaration structure. + */ +typedef struct AST_ASM_FUNCTION_DEF { + unsigned char type; // The type of the AST node (unused.) + void* next; + int endingIndex; + + char* funcName; + + AST_PARAMETER* parameters; + int parameterIndex; + + char* buff; // The content buffer of the function. + int buffIndex; // The size of buff. + +} AST_ASM_FUNCTION_DEC; + + +/** + * The function invocation structure. + */ +typedef struct { + unsigned char type; + void* next; + int endingIndex; + + void* arguments; + int argumentIndex; +} AST_FUNCTION_INVOKE; + +#endif \ No newline at end of file diff --git a/src/parser/structs/tree.h b/src/parser/structs/tree.h new file mode 100644 index 0000000..72ee7bf --- /dev/null +++ b/src/parser/structs/tree.h @@ -0,0 +1,18 @@ +/** + * AST structure definitions for Tree related ASTs. + */ + +#ifndef TREE_STRUCT_H +#define TREE_STRUCT_H + +/** + * The "base" type of each AST structure. Is used to cast to gather next branch. + */ +typedef struct AST_TREE_BRANCH { + unsigned char type; // The type of the AST node type (unused.) + void* next; // The next node in the tree. + int endingIndex; // The index where the parsing of said branch ended. + +} AST_TREE_BRANCH; + +#endif \ No newline at end of file diff --git a/src/parser/structs/values.h b/src/parser/structs/values.h new file mode 100644 index 0000000..48dc56f --- /dev/null +++ b/src/parser/structs/values.h @@ -0,0 +1,20 @@ +/** + * AST structure definitions for value related ASTs. + */ + +#ifndef VALUES_STRUCTURES_H +#define VALUES_STRUCTURES_H + +/** + * The AST structure of a value. + */ +typedef struct AST_VALUE { + unsigned char astType; + void* next; + int endingIndex; + + unsigned char* valueType; + void* value; +} AST_VALUE; + +#endif \ No newline at end of file diff --git a/src/parser/structs/variables.h b/src/parser/structs/variables.h new file mode 100644 index 0000000..cc6cc67 --- /dev/null +++ b/src/parser/structs/variables.h @@ -0,0 +1,35 @@ +/** + * AST structure definitions for variable related ASTs. + */ + +#ifndef VARIABLES_STRUCT_H +#define VARIABLES_STRUCT_H + +/** + * The variable declaration structure. + */ +typedef struct AST_VARIABLE_DEC { + unsigned char astType; + void* next; + int endingIndex; + + unsigned char* type; + char* name; + + unsigned char* value; +} AST_VARIABLE_DEC; + + +/** + * The variable modification structure. + */ +typedef struct AST_VARIABLE_MOD { + unsigned char type; + void* next; + int endingIndex; + + char* name; + unsigned char* value; +} AST_VARIABLE_MOD; + +#endif \ No newline at end of file diff --git a/src/qasm/parser/parser.c b/src/qasm/parser/parser.c new file mode 100644 index 0000000..6ffccf5 --- /dev/null +++ b/src/qasm/parser/parser.c @@ -0,0 +1,256 @@ +/** + * The parser of QuickAssembly. The inline assembly of Quickfall. + */ + +#include +#include +#include + +#include "./parser.h" + +#include "./values.h" + +#include "../../parser/structs/functions.h" + +#include "../../ir/structs.h" +#include "../../ir/ir.h" +#include "../../ir/instructions.h" + +#include "../../utils/hash.h" + +/** + * Parses QuickAssembly instructions. + */ +void parseQAsmInstructions(IR_BASIC_BLOCK* block, char* buffer, int size) { + char** buff = malloc(sizeof(char*) * 10); + int buffIndex = 0; + + int secIndex = 0; + + // Creating the buffers. + for(int i = 0; i < 10; ++i) { + buff[i] = malloc(32); + } + + for(int i = 0; i < size; ++i) { + char c = buffer[i]; + + if(c == '\0') return; + + if(c == '\n') { + IR_INSTRUCTION* instruction = parseInstruction(buff, buffIndex); + + if(instruction == NULL) { + printf("Error: Coudln't parse QuickAssembly instruction named %s!\n", buff[0]); + } + else { + pushInstruction(block, instruction); + } + + secIndex = 0; + buffIndex = 0; + } + else if(c == ' ') { + ((char*)buff[buffIndex])[secIndex] = '\0'; + secIndex = 0; + buffIndex++; + } + else { + ((char*)buff[buffIndex])[secIndex] = c; + secIndex++; + } + } + + for(int i = 0; i < 10; ++i) { + free(buff[i]); + } + + free(buff); +} + +/** + * Parses a QuickAssembly instruction. + */ +IR_INSTRUCTION* parseInstruction(char** buff, int bufferSize) { + IR_INSTRUCTION* instruction = malloc(sizeof(IR_INSTRUCTION)); + + int instructionHash = hashstr(buff[0]); + + void** b; + + // Determines the instruction type based on the string hash. + switch(instructionHash) { + case 2985: + instruction->opCode = BLOCK_SWAP; + b = malloc(sizeof(void*)); + parseInt32(b, 0, buff[1]); + + instruction->params = b; + instruction->paramCount = 1; + break; + case 2987: + instruction->opCode = COND_BLOCK_SWAP; + b = malloc(sizeof(void*) * 2); + + parseInt32(b, 0, buff[1]); + parseVariableName(b, 1, buff[2]); + + instruction->params = b; + instruction->paramCount = 2; + break; + case 3275: + instruction->opCode = LOGICAL_BLOCK_SWAP; + b = malloc(sizeof(int*) * 3); + + parseInt32(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseVariableName(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1798: + instruction->opCode = S_ALLOC; + b = malloc(sizeof(void*) * 2); + + parseInt32(b, 0, buff[1]); + parseVariableName(b, 1, buff[2]); + + instruction->params = b; + instruction->paramCount = 2; + break; + case 2887: + instruction->opCode = PTR_SET; + b = malloc(sizeof(void*) * 2); + + parseInt32(b, 0, buff[1]); + parseVariableName(b, 1, buff[2]); + + instruction->params = b; + instruction->paramCount = 2; + break; + case 2472: + instruction->opCode = PTR_LOAD; + b = malloc(sizeof(void*) * 2); + + parseVariableName(b, 0, buff[1]); + parseVariableName(b, 1, buff[2]); + + instruction->params = b; + instruction->paramCount = 2; + break; + case 452: + instruction->opCode = IADD; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1508: + instruction->opCode = ISUB; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1636: + instruction->opCode = IMUL; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1284: + instruction->opCode = IDIV; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1188: + instruction->opCode = ICMP; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1350: + instruction->opCode = ICMP_H; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 1478: + instruction->opCode = ICMP_L; + b = malloc(sizeof(void*) * 3); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + parseInt32(b, 2, buff[3]); + + instruction->params = b; + instruction->paramCount = 3; + break; + case 3272: + instruction->opCode = PRM_PUSH; + b = malloc(sizeof(void*) * 2); + + parseVariableName(b, 0, buff[1]); + parseInt32(b, 1, buff[2]); + + instruction->params = b; + instruction->paramCount = 2; + break; + case 3144: + instruction->opCode = RET_PUSH; + b = malloc(sizeof(void*)); + + parseVariableName(b, 0, buff[1]); + + instruction->params = b; + instruction->paramCount = 1; + break; + case 772: + instruction->opCode = CALL; + b = malloc(sizeof(void*)); + + parseVariableName(b, 0, buff[1]); + + instruction->params = b; + instruction->paramCount = 1; + break; + case 1283: + instruction->opCode = RET; + instruction->params = NULL; + instruction->paramCount = 0; + break; + default: + printf("Error: Unknown instruction %s!\n", buff[0]); + return NULL; + } +} \ No newline at end of file diff --git a/src/qasm/parser/parser.h b/src/qasm/parser/parser.h new file mode 100644 index 0000000..8c61b49 --- /dev/null +++ b/src/qasm/parser/parser.h @@ -0,0 +1,21 @@ +/** + * The parser of QuickAssembly. The inline assembly of Quickfall. + */ + +#include "../../parser/structs/functions.h" +#include "../../ir/structs.h" + +#ifndef QASM_PARSER_H +#define QASM_PARSER_H + +/** + * Parses QuickAssembly instructions. + */ +void parseQAsmInstructions(IR_BASIC_BLOCK* block, char* buff, int size); + +/** + * Parses a QuickAssembly instruction. + */ +IR_INSTRUCTION* parseInstruction(char** buff, int size); + +#endif \ No newline at end of file diff --git a/src/qasm/parser/values.c b/src/qasm/parser/values.c new file mode 100644 index 0000000..48b3e9f --- /dev/null +++ b/src/qasm/parser/values.c @@ -0,0 +1,40 @@ +/** + * QuickAssembly Value types parsing. + */ + +#include +#include +#include + +/** + * Parses a 32-bit integer into bytes. + * @param buff the buff to append the bytes to. + * @param index the index of where to append the bytes. + * @param str the string containing the integer. + */ +void parseInt32(void** buff, int index, char* str) { + int i = atoi(str); + + buff[index] = malloc(4); + + ((unsigned char*)buff[index])[0] = (i >> 24) & 0xFF; + ((unsigned char*)buff[index])[1] = (i >> 16) & 0xFF; + ((unsigned char*)buff[index])[2] = (i >> 8) & 0xFF; + ((unsigned char*)buff[index])[3] = i & 0xFF; +} + + +/** + * Parses a variable name. + * @param buff the buff to append the bytes to. + * @param index the index of where to append the bytes. + * @param str the string containing the variable name. + */ +void parseVariableName(void** buff, int index, char* str) { + if(str[0] != '%') { + printf("Error: Variable names must start with %%! Got %s\n", str); + return; + } + + buff[index] = (str + 1); +} \ No newline at end of file diff --git a/src/qasm/parser/values.h b/src/qasm/parser/values.h new file mode 100644 index 0000000..829f5db --- /dev/null +++ b/src/qasm/parser/values.h @@ -0,0 +1,25 @@ +/** + * QuickAssembly Value types parsing. + */ + +#ifndef QASM_PARSER_VALUES_H +#define QASM_PARSER_VALUES_H + +/** + * Parses a 32-bit integer into bytes. + * @param buff the buff to append the bytes to. + * @param index the index of where to append the bytes. + * @param str the string containing the integer. + */ +void parseInt32(void** buff, int index, char* str); + + +/** + * Parses a variable name. + * @param buff the buff to append the bytes to. + * @param index the index of where to append the bytes. + * @param str the string containing the variable name. + */ +void parseVariableName(void** buff, int index, char* str); + +#endif \ No newline at end of file diff --git a/src/qasm/qasm.h b/src/qasm/qasm.h new file mode 100644 index 0000000..d4ed063 --- /dev/null +++ b/src/qasm/qasm.h @@ -0,0 +1,10 @@ +/** + * The main file of QuickAssembly (QASm). + */ + +#ifndef QASM_H +#define QASM_H + + + +#endif \ No newline at end of file diff --git a/src/qasm/writer/values.c b/src/qasm/writer/values.c new file mode 100644 index 0000000..32758a2 --- /dev/null +++ b/src/qasm/writer/values.c @@ -0,0 +1,16 @@ +#include +#include + +/** + * Writes a 32 bit integer into the file. + */ +void writeInt32(FILE* fptr, void** buff, int index) { + fprintf(fptr, " %d", (((unsigned char*)buff[index])[0] << 24) | (((unsigned char*)buff[index])[1] << 16) | (((unsigned char*)buff[index])[2] << 8) | ((unsigned char*)buff[index])[3]); +} + +/** + * Writes a variable name. + */ +int writeVarName(FILE* fptr, void** buff, int index) { + fprintf(fptr, " %%%s", buff[index]); +} \ No newline at end of file diff --git a/src/qasm/writer/values.h b/src/qasm/writer/values.h new file mode 100644 index 0000000..6e3772c --- /dev/null +++ b/src/qasm/writer/values.h @@ -0,0 +1,16 @@ +#include + +#ifndef QASM_WRITER_VALUES_H +#define QASM_WRITER_VALUES_H + +/** + * Writes a 32 bit integer into the file. + */ +void writeInt32(FILE* fptr, void** buff, int index); + +/** + * Writes a variable name. + */ +void writeVarName(FILE* fptr, void** buff, int index); + +#endif \ No newline at end of file diff --git a/src/qasm/writer/writer.c b/src/qasm/writer/writer.c new file mode 100644 index 0000000..29fd6bd --- /dev/null +++ b/src/qasm/writer/writer.c @@ -0,0 +1,70 @@ +/** + * The writer of QuickAssembly. The inline assembly of Quickfall. + */ + +#include + +#include "./values.h" + +#include "../../ir/instructions.h" +#include "../../ir/structs.h" + +const char* formatedInstructions[] = {"blck_swap", "cblk_swap", "lblck_swap", "salloc", "ptr_set", "ptr_load", "iadd", "isub", "imul", "idiv", "icmp", "icmp_h", "icmp_l", "prm_push", "ret_push", "call", "ret"}; + +/** + * Writes some standart QuickAssembly code equivalent to the parsed IR. + * @param fptr the file output. + * @param output the output of the IR convertor. + */ +void writeQASM(FILE* fptr, IR_OUTPUT* output) { + for(int i = 0; i < output->blockCount + 1; ++i) { + fprintf(fptr, "%d:", i); + for(int index = 0; index < output->blocks[i]->instructionCount; ++index) { + IR_INSTRUCTION* instruction = output->blocks[i]->instructions[index]; + + fprintf(fptr, "\n %s", formatedInstructions[instruction->opCode]); + + switch(instruction->opCode) { + case BLOCK_SWAP: + case COND_BLOCK_SWAP: + case LOGICAL_BLOCK_SWAP: + writeInt32(fptr, instruction->params, 0); + break; + + case PTR_SET: + writeVarName(fptr, instruction->params, 0); + writeInt32(fptr, instruction->params, 1); + break; + + case PTR_LOAD: + case S_ALLOC: + writeInt32(fptr, instruction->params, 0); + writeVarName(fptr, instruction->params, 1); + break; + + case IADD: + case ISUB: + case IMUL: + case IDIV: + case ICMP: + case ICMP_H: + case ICMP_L: + writeVarName(fptr, instruction->params, 0); + writeVarName(fptr, instruction->params, 1); + writeVarName(fptr, instruction->params, 2); + break; + + case PRM_PUSH: + writeVarName(fptr, instruction->params, 0); + writeInt32(fptr, instruction->params, 1); + break; + + case RET_PUSH: + writeVarName(fptr, instruction->params, 0); + break; + + } + + } + } +} \ No newline at end of file diff --git a/src/qasm/writer/writer.h b/src/qasm/writer/writer.h new file mode 100644 index 0000000..a432a38 --- /dev/null +++ b/src/qasm/writer/writer.h @@ -0,0 +1,19 @@ +/** + * The writer of QuickAssembly. The inline assembly of Quickfall. + */ + +#include + +#include "../../ir/structs.h" + +#ifndef QASM_WRITER_H +#define QASM_WRITER_H + +/** + * Writes some standart QuickAssembly code equivalent to the parsed IR. + * @param fptr the file output. + * @param output the output of the IR convertor. + */ +void writeQASM(FILE* fptr, IR_OUTPUT* output); + +#endif \ No newline at end of file