Start work on type checker (uh oh)
This commit is contained in:
1
build.c
1
build.c
@@ -43,6 +43,7 @@ exit
|
|||||||
#include "src/parser/parser.c"
|
#include "src/parser/parser.c"
|
||||||
|
|
||||||
// -- CODEGEN --
|
// -- CODEGEN --
|
||||||
|
#include "src/codegen/SolsScope.c"
|
||||||
#include "src/codegen/codegen.c"
|
#include "src/codegen/codegen.c"
|
||||||
|
|
||||||
// -- MAIN --
|
// -- MAIN --
|
||||||
|
|||||||
21
src/codegen/SolsScope.c
Normal file
21
src/codegen/SolsScope.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "SolsScope.h"
|
||||||
|
|
||||||
|
#include "../include/uthash.h"
|
||||||
|
#include "../lexer/SolsType.h"
|
||||||
|
|
||||||
|
void addVariableToScope(SolsScope* scope, const char* name, SolsType* type) {
|
||||||
|
SolsVariable* s = malloc(sizeof(SolsVariable));
|
||||||
|
|
||||||
|
strncpy(s->id, name, sizeof(s->id) - 1);
|
||||||
|
s->id[sizeof(s->id) - 1] = '\0';
|
||||||
|
|
||||||
|
s->typeinfo = *type;
|
||||||
|
|
||||||
|
HASH_ADD_STR(scope->variables, id, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
SolsVariable* findVariable(SolsScope* scope, const char* name) {
|
||||||
|
SolsVariable* s;
|
||||||
|
HASH_FIND_STR(scope->variables, name, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
24
src/codegen/SolsScope.h
Normal file
24
src/codegen/SolsScope.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef SOLSSCOPE_H
|
||||||
|
#define SOLSSCOPE_H
|
||||||
|
|
||||||
|
#include "../include/uthash.h"
|
||||||
|
#include "../lexer/SolsType.h"
|
||||||
|
|
||||||
|
// Stores type information for variables in a UTHash table.
|
||||||
|
typedef struct SolsVariable {
|
||||||
|
char id[256];
|
||||||
|
UT_hash_handle hh;
|
||||||
|
SolsType typeinfo;
|
||||||
|
} SolsVariable;
|
||||||
|
|
||||||
|
typedef struct SolsScope {
|
||||||
|
SolsVariable* variables;
|
||||||
|
} SolsScope;
|
||||||
|
|
||||||
|
// Adds a variable to the SolsScope.
|
||||||
|
void addVariableToScope(SolsScope* scope, const char* name, SolsType* type);
|
||||||
|
|
||||||
|
// Finds a variable in the SolsScope.
|
||||||
|
SolsVariable* findVariable(SolsScope* scope, const char* name);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
|
||||||
|
#include "SolsScope.h"
|
||||||
|
|
||||||
#include <groundvm.h>
|
#include <groundvm.h>
|
||||||
|
|
||||||
#include "../parser/SolsNode.h"
|
#include "../parser/SolsNode.h"
|
||||||
#include "../include/estr.h"
|
#include "../include/estr.h"
|
||||||
|
#include "../include/uthash.h"
|
||||||
|
|
||||||
// FIXME add proper erroring function
|
// FIXME add proper erroring function
|
||||||
char* createCodegenError(char* what) {
|
char* createCodegenError(char* what) {
|
||||||
@@ -11,12 +15,12 @@ char* createCodegenError(char* what) {
|
|||||||
return estr.str;
|
return estr.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node) {
|
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node, SolsScope* scope) {
|
||||||
// We don't even need to do anything lmao
|
// We don't even need to do anything lmao
|
||||||
return Success(GroundProgram, charptr, groundCreateProgram());
|
return Success(GroundProgram, charptr, groundCreateProgram());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node) {
|
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node, SolsScope* scope) {
|
||||||
if (node->children.count < 1) {
|
if (node->children.count < 1) {
|
||||||
return Error(GroundProgram, charptr, "puts requires arguments");
|
return Error(GroundProgram, charptr, "puts requires arguments");
|
||||||
}
|
}
|
||||||
@@ -29,13 +33,13 @@ static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node
|
|||||||
return Success(GroundProgram, charptr, program);
|
return Success(GroundProgram, charptr, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node) {
|
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||||
|
|
||||||
GroundProgram program = groundCreateProgram();
|
GroundProgram program = groundCreateProgram();
|
||||||
|
|
||||||
// Generate code for all children before generating this node's code
|
// Generate code for all children before generating this node's code
|
||||||
for (size_t i = 0; i < node->children.count; i++) {
|
for (size_t i = 0; i < node->children.count; i++) {
|
||||||
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i]);
|
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i], scope);
|
||||||
if (generated.error) {
|
if (generated.error) {
|
||||||
return Error(GroundProgram, charptr, createCodegenError(generated.as.error));
|
return Error(GroundProgram, charptr, createCodegenError(generated.as.error));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
#define CODEGEN_H
|
#define CODEGEN_H
|
||||||
|
|
||||||
#include <groundvm.h>
|
#include <groundvm.h>
|
||||||
|
|
||||||
|
#include "SolsScope.h"
|
||||||
|
|
||||||
#include "../parser/SolsNode.h"
|
#include "../parser/SolsNode.h"
|
||||||
|
|
||||||
Result(GroundProgram, charptr);
|
Result(GroundProgram, charptr);
|
||||||
@@ -11,11 +14,11 @@ Result(GroundProgram, charptr);
|
|||||||
// Returns:
|
// Returns:
|
||||||
// Success: Generated GroundProgram
|
// Success: Generated GroundProgram
|
||||||
// Failure: charptr detailing what happened
|
// Failure: charptr detailing what happened
|
||||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node);
|
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope);
|
||||||
|
|
||||||
// Macro to help with code generation (and soon error handling)
|
// Macro to help with code generation (and soon error handling)
|
||||||
#define generate(nodetype) {\
|
#define generate(nodetype) {\
|
||||||
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node);\
|
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node, scope);\
|
||||||
if (__result.error) {\
|
if (__result.error) {\
|
||||||
return Error(GroundProgram, charptr, __result.as.error);\
|
return Error(GroundProgram, charptr, __result.as.error);\
|
||||||
}\
|
}\
|
||||||
|
|||||||
1137
src/include/uthash.h
Normal file
1137
src/include/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
|||||||
|
#include "SolsType.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "../include/error.h"
|
#include "../include/error.h"
|
||||||
#include "../include/estr.h"
|
#include "../include/estr.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
||||||
SolsTypeField* ptr = malloc(sizeof(SolsTypeField) * 32);
|
SolsTypeField* ptr = malloc(sizeof(SolsTypeField) * 32);
|
||||||
@@ -91,3 +93,52 @@ void freeSolsType(SolsType* type) {
|
|||||||
type->children.count = 0;
|
type->children.count = 0;
|
||||||
type->children.capacity = 0;
|
type->children.capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool compareTypes(SolsType* left, SolsType* right) {
|
||||||
|
if (left->type != right->type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (left->type) {
|
||||||
|
case STT_OBJECT: {
|
||||||
|
if (left->children.count != right->children.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < left->children.count; i++) {
|
||||||
|
if (strcmp(left->children.at[i].name, right->children.at[i].name) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (compareTypes(&left->children.at[i].type, &right->children.at[i].type) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case STT_TEMPLATE: {
|
||||||
|
if (left->children.count != right->children.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < left->children.count; i++) {
|
||||||
|
if (strcmp(left->children.at[i].name, right->children.at[i].name) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (compareTypes(&left->children.at[i].type, &right->children.at[i].type) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
case STT_FUN: {
|
||||||
|
if (left->children.count != right->children.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < left->children.count; i++) {
|
||||||
|
if (compareTypes(&left->children.at[i].type, &right->children.at[i].type) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,4 +85,7 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type);
|
|||||||
// Frees a SolsType
|
// Frees a SolsType
|
||||||
void freeSolsType(SolsType* type);
|
void freeSolsType(SolsType* type);
|
||||||
|
|
||||||
|
// Compares two SolsTypes
|
||||||
|
bool compareTypes(SolsType* left, SolsType* right);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -72,8 +72,12 @@ int main(int argc, char** argv) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SolsScope scope = {
|
||||||
|
.variables = NULL
|
||||||
|
};
|
||||||
|
|
||||||
// Do codegen on root node
|
// Do codegen on root node
|
||||||
ResultType(GroundProgram, charptr) codegen = generateCode(&parser.as.success.output);
|
ResultType(GroundProgram, charptr) codegen = generateCode(&parser.as.success.output, &scope);
|
||||||
if (codegen.error) {
|
if (codegen.error) {
|
||||||
printf("%s\n", codegen.as.error);
|
printf("%s\n", codegen.as.error);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../include/estr.h"
|
#include "../include/estr.h"
|
||||||
#include "../include/ansii.h"
|
#include "../include/ansii.h"
|
||||||
|
#include <groundvm.h>
|
||||||
|
|
||||||
SolsTokenPrecedence getPrecedence(SolsToken *token) {
|
SolsTokenPrecedence getPrecedence(SolsToken *token) {
|
||||||
switch (token->type) {
|
switch (token->type) {
|
||||||
@@ -139,6 +140,10 @@ static inline ResultType(Nothing, charptr) parseIdentifier(SolsParser* parser) {
|
|||||||
return Error(Nothing, charptr, err.str);
|
return Error(Nothing, charptr, err.str);
|
||||||
}
|
}
|
||||||
node.as.success.line = peek.as.success.line;
|
node.as.success.line = peek.as.success.line;
|
||||||
|
node.as.success.accessArg = (GroundArg) {
|
||||||
|
.type = VALREF,
|
||||||
|
.value.refName = peek.as.success.as.idName
|
||||||
|
};
|
||||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||||
return Success(Nothing, charptr, {});
|
return Success(Nothing, charptr, {});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user