We can codegen now
This commit is contained in:
53
src/codegen/codegen.c
Normal file
53
src/codegen/codegen.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "codegen.h"
|
||||
|
||||
#include <groundvm.h>
|
||||
#include "../parser/SolsNode.h"
|
||||
#include "../include/estr.h"
|
||||
|
||||
// FIXME add proper erroring function
|
||||
char* createCodegenError(char* what) {
|
||||
Estr estr = CREATE_ESTR(what);
|
||||
APPEND_ESTR(estr, "\nthats an error");
|
||||
return estr.str;
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node) {
|
||||
// We don't even need to do anything lmao
|
||||
return Success(GroundProgram, charptr, groundCreateProgram());
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node) {
|
||||
if (node->children.count < 1) {
|
||||
return Error(GroundProgram, charptr, "puts requires arguments");
|
||||
}
|
||||
GroundInstruction inst = groundCreateInstruction(PRINTLN);
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
groundAddReferenceToInstruction(&inst, node->children.at[i].accessArg);
|
||||
}
|
||||
GroundProgram program = groundCreateProgram();
|
||||
groundAddInstructionToProgram(&program, inst);
|
||||
return Success(GroundProgram, charptr, program);
|
||||
}
|
||||
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node) {
|
||||
|
||||
GroundProgram program = groundCreateProgram();
|
||||
|
||||
// Generate code for all children before generating this node's code
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i]);
|
||||
if (generated.error) {
|
||||
return Error(GroundProgram, charptr, createCodegenError(generated.as.error));
|
||||
}
|
||||
for (size_t j = 0; j < generated.as.success.size; j++) {
|
||||
groundAddInstructionToProgram(&program, generated.as.success.instructions[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now generate code for this node
|
||||
switch (node->type) {
|
||||
case SNT_PUTS: generate(Puts);
|
||||
case SNT_LITERAL: generate(Literal);
|
||||
}
|
||||
return Success(GroundProgram, charptr, program);
|
||||
}
|
||||
28
src/codegen/codegen.h
Normal file
28
src/codegen/codegen.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CODEGEN_H
|
||||
#define CODEGEN_H
|
||||
|
||||
#include <groundvm.h>
|
||||
#include "../parser/SolsNode.h"
|
||||
|
||||
Result(GroundProgram, charptr);
|
||||
|
||||
// Generates a GroundProgram (from the Ground VM header) from
|
||||
// a provided SolsNode.
|
||||
// Returns:
|
||||
// Success: Generated GroundProgram
|
||||
// Failure: charptr detailing what happened
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node);
|
||||
|
||||
// Macro to help with code generation (and soon error handling)
|
||||
#define generate(nodetype) {\
|
||||
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node);\
|
||||
if (__result.error) {\
|
||||
return Error(GroundProgram, charptr, __result.as.error);\
|
||||
}\
|
||||
for (size_t i = 0; i < __result.as.success.size; i++) {\
|
||||
groundAddInstructionToProgram(&program, __result.as.success.instructions[i]);\
|
||||
}\
|
||||
break;\
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user