#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; }