Variables (polish notation for now)
This commit is contained in:
@@ -3,18 +3,21 @@
|
|||||||
#include "../include/uthash.h"
|
#include "../include/uthash.h"
|
||||||
#include "../lexer/SolsType.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));
|
SolsVariable* s = malloc(sizeof(SolsVariable));
|
||||||
|
|
||||||
strncpy(s->id, name, sizeof(s->id) - 1);
|
strncpy(s->id, name, sizeof(s->id) - 1);
|
||||||
s->id[sizeof(s->id) - 1] = '\0';
|
s->id[sizeof(s->id) - 1] = '\0';
|
||||||
|
|
||||||
s->typeinfo = *type;
|
s->typeinfo = type;
|
||||||
|
|
||||||
HASH_ADD_STR(scope->variables, id, s);
|
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;
|
SolsVariable* s;
|
||||||
HASH_FIND_STR(scope->variables, name, s);
|
HASH_FIND_STR(scope->variables, name, s);
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ typedef struct SolsScope {
|
|||||||
} SolsScope;
|
} SolsScope;
|
||||||
|
|
||||||
// Adds a variable to the 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.
|
// Finds a variable in the SolsScope.
|
||||||
SolsVariable* findVariable(SolsScope* scope, const char* name);
|
SolsVariable* findSolsVariable(SolsScope* scope, const char* name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,54 @@ char* createCodegenError(char* what) {
|
|||||||
return estr.str;
|
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) {
|
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());
|
||||||
@@ -34,11 +82,37 @@ static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node, SolsScope* scope) {
|
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, "set requires arguments");
|
||||||
}
|
}
|
||||||
return Error(GroundProgram, charptr, "WIP");
|
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
||||||
addVariableToScope(scope, node->children.at[0].as.idName, NULL);
|
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) {
|
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ Result(GroundProgram, charptr);
|
|||||||
// Failure: charptr detailing what happened
|
// Failure: charptr detailing what happened
|
||||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope);
|
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)
|
// Macro to help with code generation (and soon error handling)
|
||||||
#define generate(nodetype) {\
|
#define generate(nodetype) {\
|
||||||
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node, scope);\
|
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node, scope);\
|
||||||
|
|||||||
Reference in New Issue
Block a user