WEE WOO WEE WOO GENERICS ARE WORKING I REPEAT GENERICS ARE WORKING WEE
WOO WEE WOO
This commit is contained in:
@@ -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, ©Scope);
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user