Files

917 lines
19 KiB
C
Raw Permalink Normal View History

2025-11-17 10:28:09 +01:00
#include "class.h"
struct class * class_new() {
struct class * classInstance = malloc( sizeof( struct class ) );
return classInstance;
}
void class_reIndexLineNumbers( struct class * baseClass ) {
int maxLineNumber = 0;
struct array * methods = baseClass->methods;
int methodsCount = array_length( methods );
for (int i = 0; i < methodsCount; ++i)
{
struct method * methodInstance = array_get( methods, i );
if( methodInstance->lineNumber > maxLineNumber ) {
maxLineNumber = methodInstance->lineNumber;
}
}
maxLineNumber += 12;
for (int i = 0; i < methodsCount; ++i)
{
struct method * methodInstance = array_get( methods, i );
if( methodInstance->lineNumber == -1 ) {
methodInstance->lineNumber = maxLineNumber;
maxLineNumber += text_findNumberOfLineBreaks( methodInstance->body );
maxLineNumber += 6;
}
}
}
void class_updateThisArgument( struct array * arguments, char * baseClassName ) {
struct text * newThisArgument = text_new( "" );
text_append( newThisArgument, "struct " );
text_append( newThisArgument, baseClassName );
text_append( newThisArgument, " * this" );
array_set( arguments, 0, newThisArgument->value );
//printf("update this argument: %s %s\n ", firstArgument, methodName);
}
int class_getMethodIndexByName( struct class * classInstance, char * methodName ) {
struct array * methods = classInstance->methods;
int count = array_length( methods );
for (int i = 0; i < count; ++i)
{
struct method * currentMethod = array_get( methods, i );
if( strcmp( currentMethod->methodName, methodName ) == 0 ) {
return i;
}
}
return -1;
}
void addMethodsToBaseClass( struct class * baseClass, struct class * extendedClass ) {
struct array * methods = extendedClass->methods;
int methodsCount = array_length( methods );
for (int i = 0; i < methodsCount; ++i)
{
struct method * methodInstance = array_get( methods, i );
struct method * methodCopy = malloc( sizeof( struct method ) );
methodCopy->methodName = methodInstance->methodName;
methodCopy->body = methodInstance->body;
methodCopy->returnType = methodInstance->returnType;
methodCopy->lineNumber = -1;
methodCopy->arguments = methodInstance->arguments;
int methodIndex = class_getMethodIndexByName( baseClass, methodInstance->methodName );
if( methodIndex == -1 ) {
class_updateThisArgument( methodCopy->arguments, baseClass->className );
array_add( baseClass->methods, methodCopy );
} else {
class_updateThisArgument( methodCopy->arguments, baseClass->className );
//array_set( baseClass->methods, methodIndex, methodCopy );
}
}
}
void addPropertiesToBaseClass( struct class * baseClass, struct class * extendedClass ) {
struct array * properties = extendedClass->properties;
int propertyCount = array_length( properties );
for (int i = 0; i < propertyCount; ++i)
{
struct property * propertyInstance = array_get( properties, i );
int propertyIndex = class_getPropertyIndexByName( baseClass, propertyInstance->propertyName );
if( propertyIndex == -1 ) {
array_add( baseClass->properties, propertyInstance );
} else {
array_set( baseClass->properties, propertyIndex, propertyInstance );
}
}
//printf("processCurrent extend: %s \n\n", extendedClass->className );
}
void class_extendClass( struct class * baseClass ) {
if( baseClass->hasExtended == 1 ) {
return;
}
struct array * extends = baseClass->extends;
int extendCount = array_length( extends );
//printf("extend: %s %i \n\n\n\n\n", baseClass->className, extendCount );
for ( int i = 0; i < extendCount; ++i )
{
char * extendName = text_removeWhiteSpaces( array_get( extends, i ) );
struct class * extendedClass = application_getClassByClassName( allClasses, extendName );
if( extendedClass == NULL ) {
printf("\n\n\n\n ERROR: Class '%s' tries to extend class '%s', Class '%s' does not exist. \n\n\n\n", baseClass->className, extendName, extendName);
exit( 0 );
}
if( extendedClass->hasExtended == -1 ) {
class_extendClass( extendedClass );
}
/*
addPropertiesToBaseClass( baseClass, extendedClass );
addMethodsToBaseClass( baseClass, extendedClass );
*/
}
class_reIndexLineNumbers( baseClass );
baseClass->hasExtended = 1;
}
int class_findClassByClassNameExists( array * classesArray, char * name ) {
int count = array_length( classesArray );
for (int i = 0; i < count; ++i)
{
struct class * currentClass = array_get( classesArray, i );
//printf(" %s\n",currentClass->className );
if ( strcmp( currentClass->className, name ) == 0 ) {
return 1;
}
}
return 0;
}
void class_extractMethod( lexer * currentLexer,
char * source,
int i,
struct class * classInstance,
struct array * classesArray,
struct array * functions ) {
double key = lexer_getKey( currentLexer, i );
array * validPreviousTokens = array_new();
array_add( validPreviousTokens, "{");
array_add( validPreviousTokens, "}");
array_add( validPreviousTokens, ";");
int previousKey = lexer_findPreviouseTokenIndex( currentLexer, i, validPreviousTokens ) + 1;
struct method * methodInstance = malloc( sizeof( struct method ) );
methodInstance->isSetter = false;
methodInstance->isGetter = false;
method_extractMethodNameAndReturnType( previousKey, key, source, methodInstance );
// &(int){ 0 } create inline pointer
methodInstance->bodyOriginal = class_extractBodyFromSource( currentLexer, i, source, 0 );
methodInstance->variables = method_extractArguments( currentLexer, key, source, i, classInstance, methodInstance, classesArray );
methodInstance->lineNumber = text_countLineBreaks( source, (int) key );
array_add( classInstance->methods, methodInstance );
}
char * class_extractBodyFromSource( lexer * currentLexer, int i, char * source, int bodyCloseIndex ) {
int bodyOpenIndex = lexer_findNextTokenIndex( currentLexer, i, "{" );
int bodyOpenKey = lexer_findNextToken( currentLexer, i, "{" );
bodyCloseIndex = lexer_findBodyCloseIndex( currentLexer, bodyOpenIndex );
int bodyCloseKey = lexer_getKey( currentLexer, bodyCloseIndex );
char * bodySource = text_slice( source, bodyOpenKey + 1, bodyCloseKey - 1 );
return bodySource;
}
void class_extractProperty( lexer * currentLexer, int key, int i, char * source, struct class * classInstance ) {
char * previousToken = lexer_getToken( currentLexer, i - 1 );
int hasValue = -1;
char * propertyValue = "";
char * propertySource = "";
struct property * propertyInstance = malloc( sizeof( struct property ) );
propertyInstance->propertyName = NULL;
propertyInstance->type = "default";
// todo this can be done more effectively
//printf("previousToken: %s\n", previousToken);
int shift = 0;
if ( strcmp( previousToken, "=" ) == 0 || strcmp( previousToken, "\"" ) == 0 ) {
int IsTokenKey = lexer_findPreviousTokenIndex( currentLexer, i, "=" );
int IsKey = lexer_getKey( currentLexer, IsTokenKey );
int keyBeforeIS = lexer_getKey( currentLexer, IsTokenKey - 1 );
propertyValue = text_slice( source, IsKey + 1, key - 1 );
propertySource = text_removeWhiteSpaces( text_slice( source, keyBeforeIS + 1, IsKey - 1 ) );
hasValue = 1;
} else if ( strcmp( previousToken, ")" ) == 0 ) {
shift = 3;
int IsTokenKey = lexer_findPreviousTokenIndex( currentLexer, i, "=" );
int previousSemicolon = lexer_findPreviousTokenIndex( currentLexer, i, ";" );
if( previousSemicolon > IsTokenKey ) {
printf("\n\n\n This is an function. \n\n\n\n\n\n\n");
int afterPreviousSemicolon = lexer_getKey( currentLexer, previousSemicolon );
int openArgumentKey = lexer_findNextToken( currentLexer, previousSemicolon, "(" );
int closeArgumentKey = lexer_findNextToken( currentLexer, previousSemicolon, ")" );
char * propertyName = text_removeWhiteSpaces( text_slice( source, openArgumentKey + 1 , closeArgumentKey - 1 ) ) ;
struct array * propertyNameParts = text_split( propertyName, " \t" );
propertyInstance->propertyName = property_extractPropertyName( propertyNameParts );
printf(" function name '%s' %i %i %i \n\n",propertyInstance->propertyName, openArgumentKey, closeArgumentKey, afterPreviousSemicolon);
propertySource = text_removeWhiteSpaces( text_slice( source, (int)afterPreviousSemicolon + 1, key-1 ) );
hasValue = 0;
//propertyInstance->propertyName = "customName";
propertyInstance->type = "function";
printf("A\n\n\n");
} else {
int IsKey = lexer_getKey( currentLexer, IsTokenKey );
int keyBeforeIS = lexer_getKey( currentLexer, IsTokenKey - 1 );
propertyValue = text_slice( source, IsKey + 1, key - 1 );
propertySource = text_removeWhiteSpaces( text_slice( source, keyBeforeIS + 1, IsKey - 1 ) );
hasValue = 1;
}
} else {
int previousKey = lexer_getKey( currentLexer, i - 1 );
propertySource = text_slice( source, previousKey + 1, key - 1 );
shift = 0;
}
char * beforeShiftToken = lexer_getToken( currentLexer, i - 1 - shift );
if( strcmp( beforeShiftToken, ">" ) == 0 ) {
int templateOpenKey = lexer_getKey( currentLexer, i - 2 - shift );
int templateCloseKey = lexer_getKey( currentLexer, i - 1 - shift );
int afterCloseKey = lexer_getKey( currentLexer, i - shift );
char * templateArgument = text_slice( source, templateOpenKey + 1, templateCloseKey - 1 );
int beforeClassName = lexer_getKey( currentLexer, i - 3 - shift );
char * className = text_removeWhiteSpaces( text_slice( source, beforeClassName + 1 , templateOpenKey - 1 ) ) ;
char * afterTemplate = text_slice( source, templateCloseKey + 1, afterCloseKey - 1 );
char * classNameWithoutStruct = className;
struct array * nameParts = text_split( className, " \t" );
if( array_length( nameParts ) > 1 ) {
char * firstPart = array_get( nameParts, 0 );
if( strcmp( firstPart, "struct" ) == NULL ) {
classNameWithoutStruct = array_get( nameParts, 1 );
}
}
struct class * classInstance = application_getClassByClassName( allClasses, classNameWithoutStruct );
if( classInstance == NULL ) {
printf("Error: class with template not found: %s \n\n\n\n\n", classNameWithoutStruct );
}
if( !classInstance->usesTemplate ) {
printf("Error: This class does not have an template: %s \n\n", classInstance->className );
}
template_addArgumentValue( classInstance, templateArgument );
struct text * templateClassName = text_new( "" );
templateArgument = text_replaceAll( templateArgument, "*", "_pointer" );
templateArgument = text_removeAllWhiteSpaces( templateArgument );
text_append( templateClassName, className );
text_append( templateClassName, "_" );
text_append( templateClassName, templateArgument );
struct text * newPropertySource = text_new( "" );
text_append( newPropertySource, templateClassName->value );
text_append( newPropertySource, afterTemplate );
propertySource = newPropertySource->value;
if( hasValue == 1 ) {
char * needle = "\\b"; // "\\bTT\\b"
needle = text_concatenate( needle, className );
needle = text_concatenate( needle, "\\b" );
propertyValue = text_regexReplaceAll( propertyValue, needle, className, templateClassName->value );
}
//printf(" templateArgument: %s %s\n\n", className, templateArgument);
}
char * trimmedPropertySource = text_removeWhiteSpaces( propertySource );
//printf(" trimmedPropertySource: %s\n", propertySource);
struct array * propertyParts = text_split( trimmedPropertySource, " \t" );
int propertyPartsLength = array_length( propertyParts );
propertyInstance->isPointer = variable_isPointer( propertyParts );
propertyInstance->hasValue = hasValue;
propertyInstance->decleration = property_extractPropertyDeclaration( propertyParts, propertyInstance );
if( hasValue == 1 ) {
//printf(" propertyValue: %s\n", propertyValue);
propertyInstance->value = property_composePropertyValue( propertyValue, propertyInstance );
}
//printf("propertyName: %s\n\n\n", propertyInstance->propertyName);
if( propertyInstance->propertyName == NULL ) {
propertyInstance->propertyName = property_extractPropertyName( propertyParts );
}
propertyInstance->declerationParts = propertyParts;
array_add( classInstance->properties, (void*) propertyInstance );
//printf("decleration: %s\n\n\n", propertyInstance->decleration);
}
int class_getPropertyIndexByName( struct class * classInstance, char * propertyName ) {
struct array * properties = classInstance->properties;
int propertyCount = array_length( properties );
for (int i = 0; i < propertyCount; ++i)
{
struct property * propertyInstance = array_get( properties, i );
if( strcmp( propertyInstance->propertyName, propertyName ) == 0 ) {
return i;
}
}
return -1;
}
struct property * class_getPropertyByName( struct class * classInstance, char * propertyName ) {
struct array * properties = classInstance->properties;
int propertyCount = array_length( properties );
for (int i = 0; i < propertyCount; ++i)
{
struct property * propertyInstance = array_get( properties, i );
if( strcmp( propertyInstance->propertyName, propertyName ) == 0 ) {
return propertyInstance;
}
}
return NULL;
}
void class_composeHeader( struct class * classInstance, struct text * classHeader, char * filename ) {
char * className = classInstance->className;
if( strcmp( className, "char" ) != 0 && strcmp( className, "int" ) != 0 && strcmp( className, "void" ) != 0 ) {
class_composeStruct( classInstance, classHeader );
}
}
void class_composeTypedefStruct( struct class * classInstance, struct text * classHeader ) {
char * className = classInstance->className;
struct array * properties = classInstance->properties;
int propertyCount = array_length( properties );
text_append( classHeader, "\n\n" );
text_append( classHeader, "typedef struct " );
text_append( classHeader, className );
text_append( classHeader, " " );
text_append( classHeader, className );
text_append( classHeader, ";\n\n" );
text_append( classHeader, "\n\n" );
}
void class_composeStruct( struct class * classInstance, struct text * classHeader ) {
char * className = classInstance->className;
struct array * properties = classInstance->properties;
int propertyCount = array_length( properties );
text_append( classHeader, "typedef struct " );
text_append( classHeader, className );
text_append( classHeader, "{\n\n" );
if( classInstance->hasReflection ) {
if( strcmp( className, "window" ) != 0 && strcmp( className, "Hints" ) != 0 ) {
text_append( classHeader, " unsigned short __classIndex;\n\n" );
}
}
for ( int i = 0; i < propertyCount; ++i )
{
struct property * currentProperty = array_get( properties, i );
char * decleration = currentProperty->decleration;
text_append( classHeader, " " );
text_append( classHeader, decleration );
text_append( classHeader, ";\n\n" );
}
text_append( classHeader, "\n} " );
text_append( classHeader, className );
text_append( classHeader, ";\n\n" );
}
void class_composeMethods( struct class * classInstance, struct text * classHeader, struct array * sourceArray ) {
char * className = classInstance->className;
struct array * methods = classInstance->methods;
int length = array_length( methods );
for (int i = 0; i < length; ++i)
{
struct method * currentMethod = array_get( classInstance->methods, i );
method_compose( currentMethod, className, sourceArray, classHeader );
}
}
int class_classNameIsPrimitive( char * baseClassName ) {
// dont overload numbers because these are used for pointers
char * primitiveTypes[3] = { "int", "long", "size_t" };
int primitiveTypesCount = 3;
for (int j = 0; j < primitiveTypesCount; ++j)
{
char * primitiveType = primitiveTypes[j];
if( strcmp( baseClassName, primitiveType ) == 0 ) {
return 1;
}
}
return -1;
}
struct property * class_getClassPropertyByPropertyName( struct class * instance, char * propertyName ) {
struct array * properties = instance->properties;
int propertyLength = array_length( properties );
for (int i = 0; i < propertyLength; ++i)
{
struct property * currentProperty = array_get( properties, i );
char * currentPropertyName = currentProperty->propertyName;
if( strcmp( currentPropertyName, propertyName ) == 0 ) {
return currentProperty;
}
}
return NULL;
}
char * class_getDatatypeFromClassProperty( char * declaration, struct array * variables ) {
array * parts = text_split( declaration, "->" );
char * propertyName = array_get( parts, 1 );
char * variableName = array_get( parts, 0 );
struct variable * variableInstance = variable_getByName( variables, variableName );
if( variableInstance == NULL ) {
return "";
}
struct class * currentClass = application_getClassByClassName( allClasses, variableInstance->datatype );
if( currentClass == NULL ) {
return "";
}
struct property * propertyInstance = class_getClassPropertyByPropertyName( currentClass, propertyName );
if( propertyInstance == NULL ) {
return "";
}
return propertyInstance->datatype;
}
char * class_openingDeclarationFromBaseClassName( char * baseClassName, char * currentOperatorSymbol, int leftSideIsPointer ) {
struct class * baseClass = application_getClassByClassName( allClasses, baseClassName );
if( baseClass != NULL ) {
char * openingDeclaration;
char * operatorName = method_getOperatorNameByOperatorSymbol( currentOperatorSymbol );
struct text * fullOperatorName = text_new( "" );
text_append( fullOperatorName, "operator_" );
text_append( fullOperatorName, operatorName );
//printf("operator name: %s %s %s\n\n", baseClassName, fullOperatorName->value, operatorName);
struct method * operatorMethod = method_getMethodByMethodName( baseClass, fullOperatorName->value );
if( operatorMethod != NULL ) {
return method_composeOperatorOverloadOpeningDeclaration( baseClassName, operatorName, leftSideIsPointer );
} else {
// printf(" method not found!\n\n");
}
} else {
}
return NULL;
}
char * class_getBaseClassNameBySymbol( char * leftSideSymbol, struct array * variables, int * leftSideIsPointer ) {
if( strcmp( leftSideSymbol, "" ) == 0 ) {
return NULL;
}
if( strcmp( leftSideSymbol, "char") == 0 ) {
return "char";
}
if( strstr( leftSideSymbol, "->" ) != 0 ) {
return class_getDatatypeFromClassProperty( leftSideSymbol, variables );
}
struct variable * variableInstance = variable_getByName( variables, leftSideSymbol );
if( strcmp( variableInstance->datatype, "this_variable_is_missing" ) != 0 ) {
*leftSideIsPointer = variableInstance->isPointer;
return variableInstance->datatype;
}
struct method * methodInstance = method_extractMethodFromSymbol( leftSideSymbol );
if( methodInstance != NULL ) {
return tools_removePointerSymbolFromDatatype( methodInstance->returnType, leftSideIsPointer );
}
char * returntype = function_getReturnTypeBySymbol( leftSideSymbol, leftSideIsPointer );
if( returntype != NULL ) {
return returntype;
}
return NULL;
}