WEE WOO WEE WOO GENERICS ARE WORKING I REPEAT GENERICS ARE WORKING WEE

WOO WEE WOO
This commit is contained in:
2026-05-17 21:19:08 +10:00
parent 246a212cb9
commit 3c36e92261

View File

@@ -54,6 +54,11 @@ static ResultType(SolsType, charptr) resolveValueType(SolsType* type, SolsScope*
return Error(SolsType, charptr, "Type is null");
}
if (type->identifierType == NULL) {
if (type->type == STT_TEMPLATE && !type->metadata.isGenericStruct) {
SolsType resolved = *type;
resolved.type = STT_OBJECT;
return Success(SolsType, charptr, resolved);
}
return Success(SolsType, charptr, *type);
}
@@ -66,6 +71,13 @@ static ResultType(SolsType, charptr) resolveValueType(SolsType* type, SolsScope*
return Success(SolsType, charptr, *type);
}
// If this identified type already has concrete children (from generic
// resolution), don't re-resolve from the scope — the caller already has
// the concrete version.
if (type->children.count > 0) {
return Success(SolsType, charptr, *type);
}
SolsVariable* var = findSolsVariable(scope, type->identifierType);
if (var == NULL) {
Estr estr = CREATE_ESTR("Unable to find type ");
@@ -73,11 +85,16 @@ static ResultType(SolsType, charptr) resolveValueType(SolsType* type, SolsScope*
return Error(SolsType, charptr, estr.str);
}
SolsType resolved = var->typeinfo;
ResultType(SolsType, charptr) resolvedResult = copySolsType(&var->typeinfo);
if (resolvedResult.error) {
return Error(SolsType, charptr, resolvedResult.as.error);
}
SolsType resolved = resolvedResult.as.success;
if (resolved.type == STT_TEMPLATE) {
resolved.type = STT_OBJECT;
// Decrement to ignore constructor
resolved.children.count--;
if (resolved.children.count > 0) {
resolved.children.count--;
}
}
resolved.identifierType = type->identifierType;
@@ -299,7 +316,8 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
case SNT_DEF:
case SNT_CONSTRUCTOR:
case SNT_DESTRUCTOR:
case SNT_DUPLICATOR: {
case SNT_DUPLICATOR:
case SNT_STRUCT_AS: {
return Success(SolsType, charptr, node->as.type);
}
case SNT_FUNCTION_CALL: {
@@ -559,6 +577,40 @@ static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* n
return Success(GroundProgram, charptr, groundCreateProgram());
}
static void renameTypeReferences(SolsType* type, char* oldName, char* newName) {
if (type == NULL) return;
if (type->identifierType != NULL && strcmp(type->identifierType, oldName) == 0) {
type->identifierType = strdup(newName);
}
for (size_t i = 0; i < type->children.count; i++) {
renameTypeReferences(&type->children.at[i].type, oldName, newName);
}
if (type->returnType != NULL && type->returnType->type != STT_NONE) {
renameTypeReferences(type->returnType, oldName, newName);
}
}
static void renameNodeTypeReferences(SolsNode* node, char* oldName, char* newName) {
if (node == NULL) return;
switch (node->type) {
case SNT_TYPE:
case SNT_LAMBDA:
case SNT_DEF:
case SNT_CONSTRUCTOR:
case SNT_DESTRUCTOR:
case SNT_DUPLICATOR:
case SNT_NEW:
case SNT_STRUCT_AS:
renameTypeReferences(&node->as.type, oldName, newName);
break;
default:
break;
}
for (size_t i = 0; i < node->children.count; i++) {
renameNodeTypeReferences(&node->children.at[i], oldName, newName);
}
}
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node, SolsScope* scope) {
if (node->children.count < 1) {
return Error(GroundProgram, charptr, "puts requires arguments");
@@ -1641,13 +1693,41 @@ ResultType(Nothing, charptr) handleGenericStructNode(SolsNode* node, SolsScope*
addChildToSolsType(&genericType, childType.as.success, "constructor");
break;
}
// 'as T {}' needs to be generated based on the inputted types,
// it cannot be resolved here.
case SNT_STRUCT_AS: {
ResultType(SolsType, charptr) childType = getNodeType(child, &copyScope);
if (childType.error) {
return Error(Nothing, charptr, childType.as.error);
}
Estr methodName = CREATE_ESTR("");
SolsType* asType = &child->children.at[0].as.type;
if (asType->identifierType != NULL) {
methodName = CREATE_ESTR(asType->identifierType);
} else {
switch (asType->type) {
case STT_INT: methodName = CREATE_ESTR("int"); break;
case STT_STRING: methodName = CREATE_ESTR("string"); break;
case STT_DOUBLE: methodName = CREATE_ESTR("double"); break;
case STT_BOOL: methodName = CREATE_ESTR("bool"); break;
case STT_CHAR: methodName = CREATE_ESTR("char"); break;
default:
return Error(Nothing, charptr, "FIXME anonymous types not yet implemented in generic struct");
}
}
APPEND_ESTR(methodName, "_SOLS_AS");
childType.as.success.metadata.isPrivate = private;
childType.as.success.metadata.isProtected = protected;
addChildToSolsType(&genericType, childType.as.success, methodName.str);
break;
}
}
}
// Mark nested references to generic parameters so resolveValueType
// short-circuits instead of trying to look them up in the scope.
for (size_t i = 0; i < node->children.at[0].children.count; i++) {
markAsGenericField(&genericType, node->children.at[0].children.at[i].as.idName);
}
addVariableToScope(scope, node->as.idName, genericType);
return Success(Nothing, charptr, {});
}
@@ -1978,7 +2058,9 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
ResultType(Nothing, charptr) resolveGeneric(char* genericName, SolsType* oldType, SolsType newType);
ResultType(Nothing, charptr) resolveGeneric(char* genericName, SolsType* oldType, SolsType newType) {
if ((oldType->type == STT_UNKNOWN || oldType->type == STT_GENERIC)
if ((oldType->type == STT_UNKNOWN
|| oldType->type == STT_GENERIC
|| (oldType->type == STT_TEMPLATE && oldType->metadata.isGenericField))
&& oldType->identifierType != NULL
&& strcmp(oldType->identifierType, genericName) == 0)
{
@@ -2016,7 +2098,6 @@ ResultType(Nothing, charptr) resolveNodeGeneric(char* genericName, SolsNode* nod
case SNT_TYPE:
case SNT_LAMBDA:
case SNT_DEF:
case SNT_OP_SET:
case SNT_CONSTRUCTOR:
case SNT_DESTRUCTOR:
case SNT_DUPLICATOR:
@@ -2107,6 +2188,10 @@ ResultType(GroundProgram, charptr) generateGenericInitNode(SolsNode* node, SolsS
}
}
// Rename type references from the short name to the mangled concrete name
// so that resolveValueType finds the concrete instance in the scope
renameNodeTypeReferences(&concreteStructNode, genericStructNode->as.idName, typeName.str);
// Now run struct codegen on the patched copy
// (renaming it first so it gets a unique type name in Ground)
concreteStructNode.as.idName = typeName.str;