If and while (scoping coming soon)
This commit is contained in:
@@ -17,7 +17,10 @@ char* createCodegenError(char* what) {
|
||||
|
||||
ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
switch (node->type) {
|
||||
case SNT_PUTS: {
|
||||
case SNT_PUTS:
|
||||
case SNT_IF:
|
||||
case SNT_WHILE:
|
||||
case SNT_CODE_BLOCK: {
|
||||
return Error(SolsType, charptr, "Specified node does not return data");
|
||||
}
|
||||
case SNT_OP_SET: {
|
||||
@@ -560,18 +563,117 @@ ResultType(GroundProgram, charptr) generateCodeBlockNode(SolsNode* node, SolsSco
|
||||
return Success(GroundProgram, charptr, groundCreateProgram());
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateWhileNode(SolsNode* node, SolsScope* scope) {
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
|
||||
char* start_label = malloc(64);
|
||||
snprintf(start_label, 64, "__SOLS_WHILE_START_%zu", scope->tmpCounter++);
|
||||
|
||||
char* end_label = malloc(64);
|
||||
snprintf(end_label, 64, "__SOLS_WHILE_END_%zu", scope->tmpCounter++);
|
||||
|
||||
GroundInstruction start_label_inst = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&start_label_inst, groundCreateReference(LABEL, start_label));
|
||||
groundAddInstructionToProgram(&gp, start_label_inst);
|
||||
|
||||
ResultType(GroundProgram, charptr) cond_code = generateCode(&node->children.at[0], scope);
|
||||
if (cond_code.error) return cond_code;
|
||||
for (size_t i = 0; i < cond_code.as.success.size; i++) {
|
||||
groundAddInstructionToProgram(&gp, cond_code.as.success.instructions[i]);
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||
if (type.error) return Error(GroundProgram, charptr, type.as.error);
|
||||
if (type.as.success.type != STT_BOOL) {
|
||||
return Error(GroundProgram, charptr, "While condition must be a boolean");
|
||||
}
|
||||
|
||||
char* tmp_inverted_cond = malloc(64);
|
||||
snprintf(tmp_inverted_cond, 64, "__SOLS_IF_COND_NOT_%zu", scope->tmpCounter++);
|
||||
GroundInstruction not_inst = groundCreateInstruction(NOT);
|
||||
groundAddReferenceToInstruction(¬_inst, node->children.at[0].accessArg);
|
||||
groundAddReferenceToInstruction(¬_inst, groundCreateReference(DIRREF, tmp_inverted_cond));
|
||||
groundAddInstructionToProgram(&gp, not_inst);
|
||||
|
||||
GroundInstruction if_inst = groundCreateInstruction(IF);
|
||||
groundAddReferenceToInstruction(&if_inst, groundCreateReference(VALREF, tmp_inverted_cond));
|
||||
groundAddReferenceToInstruction(&if_inst, groundCreateReference(LINEREF, end_label));
|
||||
groundAddInstructionToProgram(&gp, if_inst);
|
||||
|
||||
ResultType(GroundProgram, charptr) body_code = generateCode(&node->children.at[1], scope);
|
||||
if (body_code.error) return body_code;
|
||||
for (size_t i = 0; i < body_code.as.success.size; i++) {
|
||||
groundAddInstructionToProgram(&gp, body_code.as.success.instructions[i]);
|
||||
}
|
||||
|
||||
GroundInstruction jump_inst = groundCreateInstruction(JUMP);
|
||||
groundAddReferenceToInstruction(&jump_inst, groundCreateReference(LINEREF, start_label));
|
||||
groundAddInstructionToProgram(&gp, jump_inst);
|
||||
|
||||
GroundInstruction end_label_inst = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&end_label_inst, groundCreateReference(LABEL, end_label));
|
||||
groundAddInstructionToProgram(&gp, end_label_inst);
|
||||
|
||||
return Success(GroundProgram, charptr, gp);
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateIfNode(SolsNode* node, SolsScope* scope) {
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
|
||||
ResultType(GroundProgram, charptr) cond_code = generateCode(&node->children.at[0], scope);
|
||||
if (cond_code.error) return cond_code;
|
||||
for (size_t i = 0; i < cond_code.as.success.size; i++) {
|
||||
groundAddInstructionToProgram(&gp, cond_code.as.success.instructions[i]);
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||
if (type.error) return Error(GroundProgram, charptr, type.as.error);
|
||||
if (type.as.success.type != STT_BOOL) {
|
||||
return Error(GroundProgram, charptr, "If condition must be a boolean");
|
||||
}
|
||||
|
||||
char* end_label = malloc(64);
|
||||
snprintf(end_label, 64, "__SOLS_IF_END_%zu", scope->tmpCounter++);
|
||||
|
||||
char* tmp_inverted_cond = malloc(64);
|
||||
snprintf(tmp_inverted_cond, 64, "__SOLS_IF_COND_NOT_%zu", scope->tmpCounter++);
|
||||
GroundInstruction not_inst = groundCreateInstruction(NOT);
|
||||
groundAddReferenceToInstruction(¬_inst, node->children.at[0].accessArg);
|
||||
groundAddReferenceToInstruction(¬_inst, groundCreateReference(DIRREF, tmp_inverted_cond));
|
||||
groundAddInstructionToProgram(&gp, not_inst);
|
||||
|
||||
GroundInstruction if_inst = groundCreateInstruction(IF);
|
||||
groundAddReferenceToInstruction(&if_inst, groundCreateReference(VALREF, tmp_inverted_cond));
|
||||
groundAddReferenceToInstruction(&if_inst, groundCreateReference(LINEREF, end_label));
|
||||
groundAddInstructionToProgram(&gp, if_inst);
|
||||
|
||||
ResultType(GroundProgram, charptr) body_code = generateCode(&node->children.at[1], scope);
|
||||
if (body_code.error) return body_code;
|
||||
for (size_t i = 0; i < body_code.as.success.size; i++) {
|
||||
groundAddInstructionToProgram(&gp, body_code.as.success.instructions[i]);
|
||||
}
|
||||
|
||||
GroundInstruction label_inst = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&label_inst, groundCreateReference(LABEL, end_label));
|
||||
groundAddInstructionToProgram(&gp, label_inst);
|
||||
|
||||
return Success(GroundProgram, charptr, gp);
|
||||
}
|
||||
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||
|
||||
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], scope);
|
||||
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]);
|
||||
if (node->type != SNT_IF && node->type != SNT_WHILE) {
|
||||
// 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], scope);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,6 +693,8 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
case SNT_OP_LESSER: generate(Lesser);
|
||||
case SNT_OP_EQLESSER: generate(EqLesser);
|
||||
case SNT_CODE_BLOCK: generate(CodeBlock);
|
||||
case SNT_IF: generate(If);
|
||||
case SNT_WHILE: generate(While);
|
||||
}
|
||||
return Success(GroundProgram, charptr, program);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user