forked from solstice/solstice
'new' keyword
This commit is contained in:
@@ -42,6 +42,7 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
|||||||
case SNT_IF:
|
case SNT_IF:
|
||||||
case SNT_WHILE:
|
case SNT_WHILE:
|
||||||
case SNT_CODE_BLOCK:
|
case SNT_CODE_BLOCK:
|
||||||
|
case SNT_STRUCT:
|
||||||
case SNT_RETURN: {
|
case SNT_RETURN: {
|
||||||
return Error(SolsType, charptr, "Specified node does not return data");
|
return Error(SolsType, charptr, "Specified node does not return data");
|
||||||
}
|
}
|
||||||
@@ -229,6 +230,25 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
|||||||
case SNT_EXPR_IN_PAREN: {
|
case SNT_EXPR_IN_PAREN: {
|
||||||
return getNodeType(&node->children.at[node->children.count - 1], scope);
|
return getNodeType(&node->children.at[node->children.count - 1], scope);
|
||||||
}
|
}
|
||||||
|
case SNT_NEW: {
|
||||||
|
SolsType type;
|
||||||
|
if (node->as.type.typeIsKnown) {
|
||||||
|
type = node->as.type;
|
||||||
|
} else {
|
||||||
|
SolsVariable* var = findSolsVariable(scope, node->as.type.identifierType);
|
||||||
|
if (var == NULL) {
|
||||||
|
Estr estr = CREATE_ESTR("Unable to find variable ");
|
||||||
|
APPEND_ESTR(estr, node->as.type.identifierType);
|
||||||
|
return Error(SolsType, charptr, estr.str);
|
||||||
|
}
|
||||||
|
type = var->typeinfo;
|
||||||
|
}
|
||||||
|
if (type.type == STT_OBJECT) {
|
||||||
|
return Error(SolsType, charptr, "Cannot use initialized type on new");
|
||||||
|
}
|
||||||
|
type.type = STT_OBJECT;
|
||||||
|
return Success(SolsType, charptr, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Error(SolsType, charptr, "Not yet implemented");
|
return Error(SolsType, charptr, "Not yet implemented");
|
||||||
}
|
}
|
||||||
@@ -724,14 +744,14 @@ ResultType(GroundProgram, charptr) generateLambdaNode(SolsNode* node, SolsScope*
|
|||||||
node->accessArg = groundCreateReference(VALREF, lambdaId);
|
node->accessArg = groundCreateReference(VALREF, lambdaId);
|
||||||
|
|
||||||
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, lambdaId));
|
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, lambdaId));
|
||||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType);
|
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType, scope);
|
||||||
if (arg.error) {
|
if (arg.error) {
|
||||||
return Error(GroundProgram, charptr, arg.as.error);
|
return Error(GroundProgram, charptr, arg.as.error);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&signature, arg.as.success);
|
groundAddReferenceToInstruction(&signature, arg.as.success);
|
||||||
for (size_t i = 0; i < node->as.type.children.count; i++) {
|
for (size_t i = 0; i < node->as.type.children.count; i++) {
|
||||||
// Add type
|
// Add type
|
||||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type.children.at[i].type);
|
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type.children.at[i].type, scope);
|
||||||
if (arg.error) {
|
if (arg.error) {
|
||||||
return Error(GroundProgram, charptr, arg.as.error);
|
return Error(GroundProgram, charptr, arg.as.error);
|
||||||
}
|
}
|
||||||
@@ -793,14 +813,14 @@ ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* sc
|
|||||||
node->accessArg = groundCreateReference(VALREF, fnName);
|
node->accessArg = groundCreateReference(VALREF, fnName);
|
||||||
|
|
||||||
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, fnName));
|
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, fnName));
|
||||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType);
|
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType, scope);
|
||||||
if (arg.error) {
|
if (arg.error) {
|
||||||
return Error(GroundProgram, charptr, arg.as.error);
|
return Error(GroundProgram, charptr, arg.as.error);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&signature, arg.as.success);
|
groundAddReferenceToInstruction(&signature, arg.as.success);
|
||||||
for (size_t i = 0; i < node->as.type.children.count; i++) {
|
for (size_t i = 0; i < node->as.type.children.count; i++) {
|
||||||
// Add type
|
// Add type
|
||||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type.children.at[i].type);
|
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type.children.at[i].type, scope);
|
||||||
if (arg.error) {
|
if (arg.error) {
|
||||||
return Error(GroundProgram, charptr, arg.as.error);
|
return Error(GroundProgram, charptr, arg.as.error);
|
||||||
}
|
}
|
||||||
@@ -1035,13 +1055,34 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
|||||||
return Success(GroundProgram, charptr, constants);
|
return Success(GroundProgram, charptr, constants);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultType(GroundProgram, charptr) generateNewNode(SolsNode* node, SolsScope* scope) {
|
||||||
|
GroundProgram program = groundCreateProgram();
|
||||||
|
GroundInstruction inst = groundCreateInstruction(INIT);
|
||||||
|
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type, scope);
|
||||||
|
if (arg.error) {
|
||||||
|
return Error(GroundProgram, charptr, arg.as.error);
|
||||||
|
}
|
||||||
|
char* tmpId = malloc(sizeof(char) * 64);
|
||||||
|
if (tmpId == NULL) {
|
||||||
|
return Error(GroundProgram, charptr, "Failed to allocate memory for tmp identifier");
|
||||||
|
}
|
||||||
|
snprintf(tmpId, 64, "__SOLS_TMP_NEW_%zu", scope->tmpCounter++);
|
||||||
|
node->accessArg = groundCreateReference(VALREF, tmpId);
|
||||||
|
groundAddReferenceToInstruction(&inst, groundCreateReference(DIRREF, tmpId));
|
||||||
|
groundAddReferenceToInstruction(&inst, arg.as.success);
|
||||||
|
groundAddInstructionToProgram(&program, inst);
|
||||||
|
return Success(GroundProgram, charptr, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||||
|
|
||||||
GroundProgram program = groundCreateProgram();
|
GroundProgram program = groundCreateProgram();
|
||||||
|
|
||||||
SolsScope backupScope = {NULL, 0};
|
SolsScope backupScope = {NULL, 0};
|
||||||
|
|
||||||
if (node->type != SNT_IF && node->type != SNT_WHILE && node->type != SNT_LAMBDA && node->type != SNT_DEF && node->type != SNT_STRUCT) {
|
if (node->type != SNT_IF && node->type != SNT_WHILE && node->type != SNT_LAMBDA &&
|
||||||
|
node->type != SNT_DEF && node->type != SNT_STRUCT && node->type != SNT_NEW) {
|
||||||
if (node->type == SNT_CODE_BLOCK) {
|
if (node->type == SNT_CODE_BLOCK) {
|
||||||
backupScope = *scope;
|
backupScope = *scope;
|
||||||
SolsScope newScope = copySolsScope(scope);
|
SolsScope newScope = copySolsScope(scope);
|
||||||
@@ -1089,6 +1130,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
|||||||
case SNT_USE: generate(Use);
|
case SNT_USE: generate(Use);
|
||||||
case SNT_GROUND: generate(InlineGround);
|
case SNT_GROUND: generate(InlineGround);
|
||||||
case SNT_STRUCT: generate(Struct);
|
case SNT_STRUCT: generate(Struct);
|
||||||
|
case SNT_NEW: generate(New);
|
||||||
}
|
}
|
||||||
return Success(GroundProgram, charptr, program);
|
return Success(GroundProgram, charptr, program);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,37 @@ ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
|||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return Error(SolsType, charptr, "Couldn't allocate memory (in createSolsType() function)");
|
return Error(SolsType, charptr, "Couldn't allocate memory (in createSolsType() function)");
|
||||||
}
|
}
|
||||||
SolsType type = { .type = in, .children.capacity = 32, .children.at = ptr };
|
SolsType type = {
|
||||||
|
.type = in,
|
||||||
|
.identifierType = NULL,
|
||||||
|
.returnType = NULL,
|
||||||
|
.children.capacity = 32,
|
||||||
|
.children.count = 0,
|
||||||
|
.children.at = ptr,
|
||||||
|
.typeIsKnown = true,
|
||||||
|
.needsGroundStruct = false
|
||||||
|
};
|
||||||
return Success(SolsType, charptr, type);
|
return Success(SolsType, charptr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultType(SolsType, charptr) createIdentifiedSolsType(char* in) {
|
||||||
|
char* copy = malloc(strlen(in) + 1);
|
||||||
|
if (copy == NULL) {
|
||||||
|
return Error(SolsType, charptr, "Couldn't allocate memory (in createIdentifiedSolsType() function)");
|
||||||
|
}
|
||||||
|
strcpy(copy, in);
|
||||||
|
return Success(SolsType, charptr, ((SolsType) {
|
||||||
|
.type = STT_UNKNOWN,
|
||||||
|
.identifierType = copy,
|
||||||
|
.returnType = NULL,
|
||||||
|
.children.capacity = 0,
|
||||||
|
.children.count = 0,
|
||||||
|
.children.at = NULL,
|
||||||
|
.typeIsKnown = false,
|
||||||
|
.needsGroundStruct = false
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
||||||
SolsType ret = { .type = type->type, .children.count = type->children.count, .children.capacity = type->children.capacity};
|
SolsType ret = { .type = type->type, .children.count = type->children.count, .children.capacity = type->children.capacity};
|
||||||
|
|
||||||
@@ -144,7 +171,7 @@ bool compareTypes(SolsType* left, SolsType* right) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type) {
|
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope) {
|
||||||
switch (type->type) {
|
switch (type->type) {
|
||||||
case STT_INT: {
|
case STT_INT: {
|
||||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "int"));
|
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "int"));
|
||||||
@@ -168,8 +195,20 @@ ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type) {
|
|||||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "struct"));
|
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "struct"));
|
||||||
}
|
}
|
||||||
case STT_OBJECT: {
|
case STT_OBJECT: {
|
||||||
// FIXME Do this later
|
if (!type->needsGroundStruct) {
|
||||||
return Error(GroundArg, charptr, "FIXME");
|
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||||
|
} else {
|
||||||
|
// FIXME do this later
|
||||||
|
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case STT_UNKNOWN: {
|
||||||
|
if (!type->needsGroundStruct) {
|
||||||
|
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||||
|
} else {
|
||||||
|
// FIXME do this later
|
||||||
|
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Error(GroundArg, charptr, "How did we get here?");
|
return Error(GroundArg, charptr, "How did we get here?");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "../include/nothing.h"
|
#include "../include/nothing.h"
|
||||||
|
|
||||||
typedef enum SolsTypeType {
|
typedef enum SolsTypeType {
|
||||||
STT_INT, STT_STRING, STT_DOUBLE, STT_BOOL, STT_CHAR, STT_FUN, STT_TEMPLATE, STT_OBJECT
|
STT_INT, STT_STRING, STT_DOUBLE, STT_BOOL, STT_CHAR, STT_FUN, STT_TEMPLATE, STT_OBJECT, STT_UNKNOWN
|
||||||
} SolsTypeType;
|
} SolsTypeType;
|
||||||
|
|
||||||
// Definition of charptr for Result() and ResultType() macros
|
// Definition of charptr for Result() and ResultType() macros
|
||||||
@@ -53,6 +53,12 @@ typedef struct SolsType {
|
|||||||
// For use when type is identified with a name
|
// For use when type is identified with a name
|
||||||
char* identifierType;
|
char* identifierType;
|
||||||
|
|
||||||
|
// If type is identified with a name, record whether we have found the actual type
|
||||||
|
bool typeIsKnown;
|
||||||
|
|
||||||
|
// If using anonymous struct, record whether we need to generate a Ground struct
|
||||||
|
bool needsGroundStruct;
|
||||||
|
|
||||||
// For use in functions
|
// For use in functions
|
||||||
struct SolsType* returnType;
|
struct SolsType* returnType;
|
||||||
|
|
||||||
@@ -80,6 +86,10 @@ Result(SolsType, charptr);
|
|||||||
// Failure: char* detailing what went wrong (usually memory failure)
|
// Failure: char* detailing what went wrong (usually memory failure)
|
||||||
ResultType(SolsType, charptr) createSolsType(SolsTypeType in);
|
ResultType(SolsType, charptr) createSolsType(SolsTypeType in);
|
||||||
|
|
||||||
|
// Creates a SolsType which is identified by a name.
|
||||||
|
// The type details are not known yet, so the type is marked as unknown.
|
||||||
|
ResultType(SolsType, charptr) createIdentifiedSolsType(char* in);
|
||||||
|
|
||||||
Result(Nothing, charptr);
|
Result(Nothing, charptr);
|
||||||
|
|
||||||
// Adds a child SolsType to a given SolsType.
|
// Adds a child SolsType to a given SolsType.
|
||||||
@@ -93,8 +103,10 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type);
|
|||||||
|
|
||||||
Result(GroundArg, charptr);
|
Result(GroundArg, charptr);
|
||||||
|
|
||||||
|
struct SolsScope;
|
||||||
|
|
||||||
// Represents a SolsType as a GroundArg (in typeref form)
|
// Represents a SolsType as a GroundArg (in typeref form)
|
||||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type);
|
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope);
|
||||||
|
|
||||||
// Frees a SolsType
|
// Frees a SolsType
|
||||||
void freeSolsType(SolsType* type);
|
void freeSolsType(SolsType* type);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
|||||||
{"use", STT_KW_USE},
|
{"use", STT_KW_USE},
|
||||||
{"struct", STT_KW_STRUCT},
|
{"struct", STT_KW_STRUCT},
|
||||||
{"ground", STT_KW_GROUND},
|
{"ground", STT_KW_GROUND},
|
||||||
|
{"new", STT_KW_NEW},
|
||||||
{"{", STT_OPEN_CURLY},
|
{"{", STT_OPEN_CURLY},
|
||||||
{"}", STT_CLOSE_CURLY},
|
{"}", STT_CLOSE_CURLY},
|
||||||
{"(", STT_OPEN_PAREN},
|
{"(", STT_OPEN_PAREN},
|
||||||
|
|||||||
@@ -1193,7 +1193,7 @@ static inline ResultType(Nothing, charptr) parseLambda(SolsParser* parser) {
|
|||||||
if (next.as.success.type == STT_TYPE) {
|
if (next.as.success.type == STT_TYPE) {
|
||||||
tmpType = next.as.success.as.type;
|
tmpType = next.as.success.as.type;
|
||||||
} else if (next.as.success.type == STT_IDENTIFIER) {
|
} else if (next.as.success.type == STT_IDENTIFIER) {
|
||||||
tmpType.identifierType = next.as.success.as.idName;
|
tmpType = createIdentifiedSolsType(next.as.success.as.idName).as.success;
|
||||||
} else {
|
} else {
|
||||||
return Error(Nothing, charptr, "Expecting a type or identifier of type in lambda argument list");
|
return Error(Nothing, charptr, "Expecting a type or identifier of type in lambda argument list");
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1244,7 @@ static inline ResultType(Nothing, charptr) parseLambda(SolsParser* parser) {
|
|||||||
if (type.as.success.returnType == NULL) {
|
if (type.as.success.returnType == NULL) {
|
||||||
return Error(Nothing, charptr, "Failed to allocate memory for type");
|
return Error(Nothing, charptr, "Failed to allocate memory for type");
|
||||||
}
|
}
|
||||||
type.as.success.returnType->identifierType = retType.as.success.as.idName;
|
*type.as.success.returnType = createIdentifiedSolsType(retType.as.success.as.idName).as.success;
|
||||||
} else {
|
} else {
|
||||||
return Error(Nothing, charptr, "Expecting return type or identifier of type after lambda argument list");
|
return Error(Nothing, charptr, "Expecting return type or identifier of type after lambda argument list");
|
||||||
}
|
}
|
||||||
@@ -1338,7 +1338,7 @@ static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
|
|||||||
if (next.as.success.type == STT_TYPE) {
|
if (next.as.success.type == STT_TYPE) {
|
||||||
tmpType = next.as.success.as.type;
|
tmpType = next.as.success.as.type;
|
||||||
} else if (next.as.success.type == STT_IDENTIFIER) {
|
} else if (next.as.success.type == STT_IDENTIFIER) {
|
||||||
tmpType.identifierType = next.as.success.as.idName;
|
tmpType = createIdentifiedSolsType(next.as.success.as.idName).as.success;
|
||||||
} else {
|
} else {
|
||||||
return Error(Nothing, charptr, "Expecting a type or identifier of type in def argument list");
|
return Error(Nothing, charptr, "Expecting a type or identifier of type in def argument list");
|
||||||
}
|
}
|
||||||
@@ -1389,7 +1389,7 @@ static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
|
|||||||
if (type.as.success.returnType == NULL) {
|
if (type.as.success.returnType == NULL) {
|
||||||
return Error(Nothing, charptr, "Failed to allocate memory for type");
|
return Error(Nothing, charptr, "Failed to allocate memory for type");
|
||||||
}
|
}
|
||||||
type.as.success.returnType->identifierType = retType.as.success.as.idName;
|
*type.as.success.returnType = createIdentifiedSolsType(retType.as.success.as.idName).as.success;
|
||||||
} else {
|
} else {
|
||||||
return Error(Nothing, charptr, "Expecting return type or identifier of type after def argument list");
|
return Error(Nothing, charptr, "Expecting return type or identifier of type after def argument list");
|
||||||
}
|
}
|
||||||
@@ -1805,6 +1805,24 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
|||||||
return Success(Nothing, charptr, {});
|
return Success(Nothing, charptr, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultType(Nothing, charptr) parseNew(SolsParser* parser) {
|
||||||
|
ResultType(SolsNode, charptr) newNode = createSolsNode(SNT_NEW);
|
||||||
|
if (newNode.error) {
|
||||||
|
return Error(Nothing, charptr, newNode.as.error);
|
||||||
|
}
|
||||||
|
ResultType(SolsToken, Nothing) nameTok = parserConsume(parser);
|
||||||
|
if (nameTok.error || !(nameTok.as.success.type == STT_IDENTIFIER || nameTok.as.success.type == STT_TYPE)) {
|
||||||
|
return Error(Nothing, charptr, "Expecting identifier after 'new'");
|
||||||
|
}
|
||||||
|
if (nameTok.as.success.type == STT_IDENTIFIER) {
|
||||||
|
newNode.as.success.as.type = createIdentifiedSolsType(nameTok.as.success.as.idName).as.success;
|
||||||
|
} else if (nameTok.as.success.type == STT_TYPE) {
|
||||||
|
newNode.as.success.as.type = nameTok.as.success.as.type;
|
||||||
|
}
|
||||||
|
addChildToSolsNode(parser->currentParent, newNode.as.success);
|
||||||
|
return Success(Nothing, charptr, {});
|
||||||
|
}
|
||||||
|
|
||||||
ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
||||||
parser->currentParent = &parser->output;
|
parser->currentParent = &parser->output;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1822,6 +1840,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
|||||||
case STT_KW_LAMBDA: PARSER_HANDLE(Lambda);
|
case STT_KW_LAMBDA: PARSER_HANDLE(Lambda);
|
||||||
case STT_KW_RETURN: PARSER_HANDLE(Return);
|
case STT_KW_RETURN: PARSER_HANDLE(Return);
|
||||||
case STT_KW_STRUCT: PARSER_HANDLE(Struct);
|
case STT_KW_STRUCT: PARSER_HANDLE(Struct);
|
||||||
|
case STT_KW_NEW: PARSER_HANDLE(New);
|
||||||
case STT_KW_USE: PARSER_HANDLE(Use);
|
case STT_KW_USE: PARSER_HANDLE(Use);
|
||||||
case STT_KW_DEF: PARSER_HANDLE(Def);
|
case STT_KW_DEF: PARSER_HANDLE(Def);
|
||||||
case STT_OP_SET: PARSER_HANDLE(Set);
|
case STT_OP_SET: PARSER_HANDLE(Set);
|
||||||
|
|||||||
Reference in New Issue
Block a user