'new' keyword

This commit is contained in:
2026-04-09 19:00:40 +10:00
parent 9b55b509f5
commit a2fc138ba1
5 changed files with 129 additions and 16 deletions

View File

@@ -41,7 +41,8 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
case SNT_PUTS: case SNT_PUTS:
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);
} }

View File

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

View File

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

View File

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

View File

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