Start work on type checker (uh oh)

This commit is contained in:
2026-02-24 21:01:30 +11:00
parent 0613fcd957
commit 48206c2f50
10 changed files with 1260 additions and 7 deletions

View File

@@ -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
View 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
View 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

View File

@@ -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));
} }

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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, {});
} }