Variables (polish notation for now)
This commit is contained in:
@@ -3,18 +3,21 @@
|
||||
#include "../include/uthash.h"
|
||||
#include "../lexer/SolsType.h"
|
||||
|
||||
void addVariableToScope(SolsScope* scope, const char* name, SolsType* type) {
|
||||
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;
|
||||
s->typeinfo = type;
|
||||
|
||||
HASH_ADD_STR(scope->variables, id, s);
|
||||
}
|
||||
|
||||
SolsVariable* findVariable(SolsScope* scope, const char* name) {
|
||||
SolsVariable* findSolsVariable(SolsScope* scope, const char* name) {
|
||||
if (scope == NULL || scope->variables == NULL || name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
SolsVariable* s;
|
||||
HASH_FIND_STR(scope->variables, name, s);
|
||||
return s;
|
||||
|
||||
@@ -16,9 +16,9 @@ typedef struct SolsScope {
|
||||
} SolsScope;
|
||||
|
||||
// Adds a variable to the SolsScope.
|
||||
void addVariableToScope(SolsScope* scope, const char* name, SolsType* type);
|
||||
void addVariableToScope(SolsScope* scope, const char* name, SolsType type);
|
||||
|
||||
// Finds a variable in the SolsScope.
|
||||
SolsVariable* findVariable(SolsScope* scope, const char* name);
|
||||
SolsVariable* findSolsVariable(SolsScope* scope, const char* name);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,54 @@ char* createCodegenError(char* what) {
|
||||
return estr.str;
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
switch (node->type) {
|
||||
case SNT_PUTS: {
|
||||
return Error(SolsType, charptr, "Specified node does not return data");
|
||||
}
|
||||
case SNT_OP_SET: {
|
||||
if (node->children.count < 2) {
|
||||
return Error(SolsType, charptr, "Not enough children to determine type");
|
||||
}
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||
if (type.error) {
|
||||
return Error(SolsType, charptr, type.as.error);
|
||||
}
|
||||
return Success(SolsType, charptr, type.as.success);
|
||||
}
|
||||
case SNT_LITERAL: {
|
||||
switch (node->as.literal.type) {
|
||||
case SLT_INT: {
|
||||
return Success(SolsType, charptr, {STT_INT});
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
return Success(SolsType, charptr, {STT_DOUBLE});
|
||||
}
|
||||
case SLT_STRING: {
|
||||
return Success(SolsType, charptr, {STT_STRING});
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
return Success(SolsType, charptr, {STT_BOOL});
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
return Success(SolsType, charptr, {STT_CHAR});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SNT_IDENTIFIER: {
|
||||
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||
if (var == NULL) {
|
||||
Estr estr = CREATE_ESTR("Unable to find variable ");
|
||||
APPEND_ESTR(estr, node->as.idName);
|
||||
return Error(SolsType, charptr, estr.str);
|
||||
}
|
||||
return Success(SolsType, charptr, var->typeinfo);
|
||||
}
|
||||
}
|
||||
return Error(SolsType, charptr, "Not yet implemented");
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node, SolsScope* scope) {
|
||||
// We don't even need to do anything lmao
|
||||
return Success(GroundProgram, charptr, groundCreateProgram());
|
||||
@@ -34,11 +82,37 @@ static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node, SolsScope* scope) {
|
||||
if (node->children.count <= 2) {
|
||||
if (node->children.count < 2) {
|
||||
return Error(GroundProgram, charptr, "set requires arguments");
|
||||
}
|
||||
return Error(GroundProgram, charptr, "WIP");
|
||||
addVariableToScope(scope, node->children.at[0].as.idName, NULL);
|
||||
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
||||
return Error(GroundProgram, charptr, "set requires an identifier before '='");
|
||||
}
|
||||
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope);
|
||||
if (type.error) {
|
||||
return Error(GroundProgram, charptr, type.as.error);
|
||||
}
|
||||
if (var == NULL) {
|
||||
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
||||
} else {
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||
if (type.error) {
|
||||
return Error(GroundProgram, charptr, type.as.error);
|
||||
}
|
||||
if (compareTypes(&var->typeinfo, &type.as.success) == false) {
|
||||
return Error(GroundProgram, charptr, "Type of variable cannot be changed");
|
||||
}
|
||||
}
|
||||
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
||||
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
GroundInstruction gi = groundCreateInstruction(SET);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].as.idName));
|
||||
groundAddReferenceToInstruction(&gi, node->children.at[1].accessArg);
|
||||
groundAddInstructionToProgram(&gp, gi);
|
||||
|
||||
return Success(GroundProgram, charptr, gp);
|
||||
}
|
||||
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||
|
||||
@@ -16,6 +16,9 @@ Result(GroundProgram, charptr);
|
||||
// Failure: charptr detailing what happened
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope);
|
||||
|
||||
// Gets the type of a node generated by the parser for the type checker.
|
||||
ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope);
|
||||
|
||||
// Macro to help with code generation (and soon error handling)
|
||||
#define generate(nodetype) {\
|
||||
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node, scope);\
|
||||
|
||||
Reference in New Issue
Block a user