#include "method.h" // todo // // method_operatorOverload.h // method_operator_processOperatorSymbols // method_operator_processOperatorSymbol // // method_chaining.h int total_libc_function = 293; char * libcFunctionNames[293] = {"abort","abs","acos","asctime","asctime_r","asin","assert","atan","atan2","atexit","atof","atoi","atol","bsearch","btowc","calloc","catclose6","catgets6","catopen6","ceil","clearerr","clock","cos","cosh","ctime","ctime64","ctime_r","ctime64_r","difftime","difftime64","div","erf","erfc","exit","exp","fabs","fclose","fdopen5","feof","ferror","fflush1","fgetc1","fgetpos1","fgets1","fgetwc6","fgetws6","fileno5","floor","fmod","fopen","fprintf","fputc1","fputs1","fputwc6","fputws6","fread","free","freopen","frexp","fscanf","fseek1","fsetpos1","ftell1","fwide6","fwprintf6","fwrite","fwscanf6","gamma","getc1","getchar1","getenv","gets","getwc6","getwchar6","gmtime","gmtime64","gmtime_r","gmtime64_r","hypot","isalnum","isalpha","isascii4","isblank","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","iswalnum4","iswalpha4","iswblank4","iswcntrl4","iswctype4","iswdigit4","iswgraph4","iswlower4","iswprint4","iswpunct4","iswspace4","iswupper4","iswxdigit4","isxdigit4","j0","j1","jn","labs","ldexp","ldiv","localeconv","localtime","localtime64","localtime_r","localtime64_r","log","log10","longjmp","malloc","mblen","mbrlen4","mbrtowc4","mbsinit4","mbsrtowcs4","mbstowcs","mbtowc","memchr","memcmp","memcpy","memmove","memset","mktime","mktime64","modf","nextafter","nextafterl","nexttoward","nexttowardl","nl_langinfo4","perror","pow","printf","putc1","putchar1","putenv","puts","putwc6","putwchar6","qsort","quantexpd32","quantexpd64","quantexpd128","quantized32","quantized64","quantized128","samequantumd32","samequantumd64","samequantumd128","raise","rand","rand_r","realloc","regcomp","regerror","regexec","regfree","remove","rename","rewind1","scanf","setbuf","setjmp","setlocale","setvbuf","signal","sin","sinh","snprintf","sprintf","sqrt","srand","sscanf","strcasecmp","strcat","strchr","strcmp","strcoll","strcpy","strcspn","strerror","strfmon4","strftime","strlen","strncasecmp","strncat","strncmp","strncpy","strpbrk","strptime4","strrchr","strspn","strstr","strtod","strtod32","strtod64","strtod128","strtof","strtok","strtok_r","strtol","strtold","strtoul","strxfrm","swprintf","swscanf","system","tan","tanh","time","time64","tmpfile","tmpnam","toascii","tolower","toupper","towctrans","towlower4","towupper4","ungetc1","ungetwc6","va_arg","va_copy","va_end","va_start","vfprintf","vfscanf","vfwprintf6","vfwscanf","vprintf","vscanf","vsprintf","vsnprintf","vsscanf","vswprintf","vswscanf","vwprintf6","vwscanf","wcrtomb4","wcscat","wcschr","wcscmp","wcscoll4","wcscpy","wcscspn","wcsftime","wcslen","wcslocaleconv","wcsncat","wcsncmp","wcsncpy","wcspbrk","wcsptime","wcsrchr","wcsrtombs4","wcsspn","wcsstr","wcstod","wcstod32","wcstod64","wcstod128","wcstof","wcstok","wcstol","wcstold","wcstombs","wcstoul","wcsxfrm4","wctob","wctomb","wctrans","wctype4","wcwidth","wmemchr","wmemcmp","wmemcpy","wmemmove","wmemset","wprintf6","wscanf6","y0","y1","yn"}; char * libcReturnTypes[293] = {"void","int","double","char","char","double","void","double","double","int","double","int","long","void","wint_t","void","int","char","nl_catd","double","void","clock_t","double","double","char","char","char","char","double","double","div_t","double","double","void","double","double","int","FILE","int","int","int","int","int","char","wint_t","wchar_t","int","double","double","FILE","int","int","int","wint_t","int","size_t","void","FILE","double","int","int","int","long","int","int","size_t","int","double","int","int","char","char","wint_t","wint_t","struct","struct","struct","struct","double","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","int","double","double","double","long","double","ldiv_t","struct","struct","struct","struct","struct","double","double","void","void","int","int","int","int","size_t","size_t","int","void","int","void","void","void","time_t","time64_t","double","double","long","double","long","char","void","double","int","int","int","int","int","wint_t","wint_t","void","_Decimal32","_Decimal64","_Decimal128","int","int","int","__bool__","__bool__","__bool__","int","int","int","void","int","size_t","int","void","int","int","void","int","void","int","char","int","void(*signal","double","double","int","int","double","void","int","int","char","char","int","int","char","size_t","char","int","size_t","size_t","int","char","int","char","char","char","char","size_t","char","double","_Decimal32","_Decimal64","_Decimal128","float","char","char","long","long","unsigned","size_t","int","int","int","double","double","time_t","time64_t","FILE","char","int","int","int","wint_t","wint_t","wint_t","int","wint_t","var_type","void","void","void","int","int","int","int","int","int","int","int","int","int","int","int","int","int","wchar_t","wchar_t","int","int","wchar_t","size_t","size_t","size_t","struct","wchar_t","int","wchar_t","wchar_t","wchar_t","wchar_t","size_t","size_t","wchar_t","double","_Decimal32","_Decimal64","_Decimal128","float","wchar_t","long","long","size_t","unsigned","size_t","int","int","wctrans_t","wctype_t","int","wchar_t","int","wchar_t","wchar_t","wchar_t","int","int","double","double","double"}; void method_sortLineNumbers( struct array * lineNumbers ) { int count = array_length( lineNumbers ); int i = 0; int j = 0; void * temp; for (i = 0; i < (count - 1); ++i) { for (j = 0; j < count - 1 - i; ++j ) { struct codeBundle * a = array_get( lineNumbers, j ); struct codeBundle * b = array_get( lineNumbers, j + 1 ); if ( a->lineNumber > b->lineNumber ) { temp = lineNumbers->items[ j + 1 ]; lineNumbers->items[ j + 1 ] = lineNumbers->items[ j ]; lineNumbers->items[ j ] = temp; } } } } char * method_getReturnTypeFromDeclerationParts( struct array * methodDeclerationParts, int methodDeclerationCount ) { struct text * returnType = text_new( "" ); //returnType[0] = '\0'; for (int i = 0; i < methodDeclerationCount - 1; ++i) { char * returnPart = ( char * ) array_get( methodDeclerationParts, i ); if( i != 0 ) { text_append( returnType, " " ); } if( strcmp( text_removeWhiteSpaces(returnPart), "*" ) == 0 ) { } else { } //printf(" ------------------------return type: %s\n", returnPart ); char * temporary = malloc(2);//text_removeWhiteSpaces(returnPart); char * cleanedReturnPart = text_removeWhiteSpaces( returnPart ); if( strlen( cleanedReturnPart ) < 3 ) { strcpy( temporary, cleanedReturnPart); } text_append( returnType, cleanedReturnPart ); } return returnType->value; } char * method_extractTemplate( lexer * currentLexer, int i, char * source ) { int closeTypeLexerIndex = lexer_findNextTokenIndex( currentLexer, i, ">" ); int closeTypeDefinition = lexer_getKey( currentLexer, closeTypeLexerIndex ); int key = lexer_getKey( currentLexer, i ); char * className = text_extractWordBeforeKey( source, key ); int keyBeforeClassName = text_getIndexBeforeWord( source, key - 1 ); struct class * classInstance = application_getClassByClassName( allClasses, className ); if( classInstance == NULL ) { //printf("Error: class with template not found: %s \n\n\n\n\n", className ); return source; } if( !classInstance->usesTemplate ) { //printf("Error: This class does not have an template: %s \n\n", classInstance->className ); return source; } char * templateArguments = text_slice( source, key + 1, closeTypeDefinition - 1 ); template_addArgumentValue( classInstance, templateArguments ); char * replaceWith = template_extractTemplateName( classInstance->template, templateArguments ); replaceWith = text_replace( replaceWith, "*", "_pointer" ); replaceWith = text_regexReplaceAll( replaceWith, "struct ", "struct ", "" ); replaceWith = text_removeAllWhiteSpaces( replaceWith ); char * newName = text_copy( classInstance->className ); newName = text_concatenate( newName, "_" ); newName = text_concatenate( newName, replaceWith ); source = text_replaceAt( keyBeforeClassName, closeTypeDefinition + 1, source, newName ); return source; } char * method_extractTemplates( char * source ) { lexer * currentLexer = lexer_new(); lexer_tokenize( currentLexer, source, "<" ); lexer_tokenize( currentLexer, source, ">" ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); if ( strcmp( token, "<" ) == 0 ) { source = method_extractTemplate( currentLexer, i, source ); } } return source; } void method_extractMethodNameAndReturnType( int previousKey, int key, char * source, struct method * methodInstance ) { char * methodDecleration = text_removeWhiteSpaces( text_slice( source, previousKey + 1, key - 1 )); struct array * methodDeclerationParts = text_split( methodDecleration, " \t" ); int methodDeclerationCount = array_length( methodDeclerationParts ); char * returnType = method_getReturnTypeFromDeclerationParts( methodDeclerationParts, methodDeclerationCount ); char * methodName = text_removeWhiteSpaces( array_get( methodDeclerationParts, methodDeclerationCount - 1 ) ); int maxOperatorNameLength = 20; int methodNameLength = strlen( methodName ); methodInstance->isOperator = -1; if( methodNameLength > 7 ) { char* methodNameStart = malloc( 8 + 1 ); strncpy( methodNameStart, methodName, 8 ); if( strcmp( methodNameStart, "operator" ) == 0 ) { //char * newMethodName = malloc( strlen( methodName ) + maxOperatorNameLength ); char * operatorFull = malloc( methodNameLength - 7 ); strncpy( operatorFull, methodName + 8, methodNameLength ); char * operator = text_removeWhiteSpaces( operatorFull ); char * operatorName = method_getOperatorNameByOperatorSymbol( operator ); text * newMethodName = text_new( "" ); text_append( newMethodName, "operator_" ); text_append( newMethodName, operatorName ); methodName = newMethodName->value; methodInstance->operator = operator; methodInstance->isOperator = 1; printf(" this is an operator: %s %s %s", methodNameStart, operator, operatorName); } } printf(" %s(){}\n", methodName ); methodInstance->returnType = text_copy( returnType ); methodInstance->methodName = methodName; if( strcmp( text_removeWhiteSpaces( methodInstance->returnType ), "set" ) == 0 ) { methodInstance->returnType = ""; methodInstance->isSetter = true; struct text * newMethodName = text_new( "" ); text_append( newMethodName, "setter_" ); text_append( newMethodName, methodName ); methodInstance->methodName = text_copy( newMethodName->value ); } //printf("methodName: %s\n\n", methodName); } void method_extractVariablesFromArguments( struct array * arguments, array * classesArray, struct array * variables ) { int argumentCount = array_length( arguments ); for ( int j = 0; j < argumentCount; ++j ) { char * argumentText = (char *) array_get( arguments, j ); struct array * argumentParts = text_split( argumentText, " \t" ); //printf("\n\n ?????????? find out if this is an variable: '%s' \n\n", argumentText); variable_getVariablesByArgumentParts( argumentParts, variables, classesArray ); } } void method_processVariadicMethodArguments( struct class * classInstance, struct method * methodInstance ) { /* char * thisExpression = malloc( 3500 ); strcat( thisExpression, ( char * ) text_copy( classInstance->className ) ); strcat( thisExpression, " * this" ); array_unshift( methodInstance->arguments, thisExpression ); */ array * arguments = methodInstance->arguments; int count = array_length( arguments ); float isVariadic = -1; for (int i = 0; i < count; ++i) { char * currentArgument = text_removeWhiteSpaces( array_get( arguments, i ) ); if( strcmp( currentArgument, "..." ) == 0 ) { isVariadic = 1; } } if( isVariadic == 1 ) { array_unshift( methodInstance->arguments, "int datatypes[]" ); array_unshift( methodInstance->arguments, "int count" ); } } void method_addThisVariableToVariables( struct class * classInstance, array * variables ) { struct variable * variableInstance = malloc( sizeof( struct variable ) ); variableInstance->variableName = "this"; variableInstance->datatype = classInstance->className; //variableInstance->isPointer = 1; array_add( variables, variableInstance ); } struct array * method_getArguments_new( lexer * currentLexer, int key, int i, char * source, struct array * variables ) { int argumentCloseIndex = 0; int count = lexer_length( currentLexer ); int depth = 1; for (int j = i + 1; j < count; ++j) { char * token = lexer_getToken( currentLexer, j ); if( strcmp( token, "(" ) == 0 ) { depth++; } if( strcmp( token, ")" ) == 0 ) { depth--; } //printf("???????????????? token %s %i \n", token, depth); if( depth == 0 ) { argumentCloseIndex = lexer_getKey( currentLexer, j ); break; } } char * argumentsText = text_removeWhiteSpaces( text_slice( source, key + 1, argumentCloseIndex - 1 )); struct array * argumentsArray = text_split( argumentsText, "," ); int argumentCount = array_length( argumentsArray ); for (int i = 0; i < argumentCount; ++i) { char * currentArgument = array_get( argumentsArray, i ); struct array * argumentParts = text_split( currentArgument, " \t" ); //char * datatype = tools_findDatatype( argumentParts ); if( text_contains( currentArgument, "<" ) ) { printf("\n\n\n\n This is a template: %s\n\n\n", currentArgument); int templateOpenKey = text_text_findFirstCharacterIndexFromIndex( currentArgument, "<", 0 ); int templateCloseKey = text_text_findFirstCharacterIndexFromIndex( currentArgument, ">", 0 ); char * templateArgument = text_slice( currentArgument, templateOpenKey + 1, templateCloseKey - 1 ); char * className = text_removeWhiteSpaces( text_slice( currentArgument, 0 , templateOpenKey - 1 ) ) ; char * classNameClean = tools_findDatatype( text_split( className, " \t" ) ); struct array * parts = text_split( currentArgument, " \t" ); char * variableName = array_get( parts, array_length( parts ) - 1 ); struct text * newVariableName = text_new( "" ); templateArgument = text_regexReplaceAll( templateArgument, "struct ", "struct ", "" ); text_removeSpaces( templateArgument ); text_append( newVariableName, classNameClean ); text_append( newVariableName, "_" ); text_append( newVariableName, templateArgument ); currentArgument = text_replaceAt( 0, templateCloseKey + 1, currentArgument, newVariableName->value ); printf("\n\n\n\n This is a template: %s\n\n\n", currentArgument); printf("\n\n\n\n %i - %i %s %s \n\n\n", templateOpenKey, templateCloseKey, templateArgument, classNameClean ); array_set( argumentsArray, i, currentArgument ); struct variable * variableInstance = malloc( sizeof( struct variable ) ); variableInstance->variableName = variableName; variableInstance->datatype = newVariableName->value; printf("\n\n\n add argument as variable: variable->variableName %s variableInstance->datatype %s\n\n\n", variableInstance->variableName, variableInstance->datatype); variableInstance->isPointer = variable_isPointer( parts ); array_add( variables, variableInstance ); } } //printf("argumentsText: %s %i\n", argumentsText, array_length(argumentsArray)); return argumentsArray; } void method_addThisVariableToMethodArguments( struct class * classInstance, struct method * methodInstance ) { struct text * thisExpression = text_new( "" ); text_append( thisExpression, classInstance->className ); text_append( thisExpression, " * this" ); array_unshift( methodInstance->arguments, thisExpression->value ); } struct array * method_addArgumentsToMethod( struct class * classInstance, struct method * methodInstance, struct array * classesArray, struct array * argumentsArray ) { method_extractVariablesFromArguments( methodInstance->arguments, classesArray, methodInstance->variables ); method_addThisVariableToVariables( classInstance, methodInstance->variables ); method_processVariadicMethodArguments( classInstance, methodInstance ); method_addThisVariableToMethodArguments( classInstance, methodInstance ); return methodInstance->variables; } struct array * method_extractArguments( lexer * currentLexer, int key, char * source, int i, struct class * classInstance, struct method * methodInstance, struct array * classesArray ) { methodInstance->arguments = array_new(); methodInstance->variables = array_new(); methodInstance->arguments = method_getArguments_new( currentLexer, key, i, source, methodInstance->variables ); methodInstance->isVariadic = method_methodIsVaradic( methodInstance->arguments ); method_addArgumentsToMethod( classInstance, methodInstance, classesArray, methodInstance->arguments ); return methodInstance->variables; } int method_checkIfSymbolIsOperator( char * functionName ) { array * functionNameParts = text_split( text_copy( functionName ), "_" ); int partsCount = array_length( functionNameParts ); if( partsCount > 1 ) { char * operatorPart = array_get( functionNameParts, 1 ); if( strcmp( operatorPart, "operator" ) == 0 ) { return 1; } } return -1; } int method_methodIsVaradic( array * arguments ) { float isVariadic = -1; int count = array_length( arguments ); for (int i = 0; i < count; ++i) { char * currentArgument = text_removeWhiteSpaces( array_get( arguments, i ) ); if( strcmp( currentArgument, "..." ) == 0 ) { isVariadic = 1; } } return isVariadic; } char * method_composeOperatorOverloadOpeningDeclaration( char * baseClassName, char * operatorName, int leftSideIsPointer ) { struct text * newMethodDecleration = text_new( "" ); text_append( newMethodDecleration, baseClassName ); text_append( newMethodDecleration, "_operator_" ); text_append( newMethodDecleration, operatorName ); text_append( newMethodDecleration, "( " ); if( leftSideIsPointer != 1 ) { text_append( newMethodDecleration, "&" ); } return newMethodDecleration->value; } char * method_getOperatorNameByOperatorSymbol( char * symbol ) { if( strcmp( symbol, "+" ) == 0 ) { return "plus"; } if( strcmp( symbol, "+=" ) == 0 ) { return "add"; } if( strcmp( symbol, "==" ) == 0 ) { return "compare"; } if( strcmp( symbol, "=" ) == 0 ) { return "is"; } return symbol; } struct method * method_extractMethodFromSymbol( char * functionName ) { struct array * nameParts = text_split( text_copy( functionName ), "_" ); int partsCount = array_length( nameParts ); char * className = array_get( nameParts, 0 ); array_delete( nameParts, 0 ); char * methodName = text_join( nameParts, "_" ); struct class * classInstance = application_getClassByClassName( allClasses, className ); if( classInstance != NULL ) { return method_getMethodByMethodName( classInstance, methodName ); } else { return NULL; } } // exists int method_findMethodByName( struct class * classInstance, char * methodName ) { struct array * methods = classInstance->methods; int count = array_length( methods ); for (int k = 0; k < count; ++k) { struct method * methodInstance = array_get( methods, k ); if( strcmp( methodInstance->methodName, methodName ) == 0 ) { return 1; } } return -1; } struct method * method_getMethodByMethodName( struct class * classInstance, char * methodName ) { struct array * methods = classInstance->methods; int count = array_length( methods ); struct array * output = array_new(); for (int i = 0; i < count; ++i) { struct method * currentMethod = array_get( methods, i ); //printf(" getMethodByName %s %s\n", currentMethod->methodName, methodName ); if( strcmp( currentMethod->methodName, methodName ) == 0 ) { return currentMethod; } } if( classInstance->hasExtended == 1 ) { return NULL; } struct array * extends = classInstance->extends; int extendCount = array_length( extends ); for ( int i = 0; i < extendCount; ++i ) { char * extendName = text_removeWhiteSpaces( array_get( extends, i ) ); struct class * extendedClass = application_getClassByClassName( allClasses, extendName ); struct method * foundMethod = method_getMethodByMethodName( extendedClass, methodName ); if( foundMethod != NULL ) { return foundMethod; } } return NULL; } void method_parseFirstNextMethodInChain( lexer * currentLexer, int i, char * body, int key, struct array * replacements ) { int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); if( body[ keyAfterMethod ] == 40 || body[keyAfterMethod + 1] == 40 ){ void * previousToken = lexer_getToken( currentLexer, i - 1 ); // ↓ // variable->method( "" )->method() if ( strcmp( previousToken, ")" ) == 0 ) { int previousKey = lexer_getKey( currentLexer, i ); int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); int argumentOpenIndex = text_text_findFirstCharacterIndexFromIndex( body, "(", keyAfterMethod -1 ); int argumentCloseIndex = text_findArgumentCloseIndex( body, (int ) keyAfterMethod - 1 ); char * methodName = text_removeWhiteSpaces( text_slice( body, key + 2, keyAfterMethod - 1 ) ); // caller current // // caller 'char_concatenate( a, b )->concatenate->( d )' int callerArgumentCloseIndex = tools_findArgumentCloseIndexReverse( body, (int ) previousKey ); int indexBeforeCaller = text_getIndexBeforeWord( body, callerArgumentCloseIndex ); char * variableName = text_removeWhiteSpaces( text_slice( body, indexBeforeCaller, previousKey ) ); char * callerFunctionName = text_removeWhiteSpaces( text_slice( body, indexBeforeCaller, callerArgumentCloseIndex -1 ) ); struct array * callerFunctionNameParts = text_split( callerFunctionName, "_" ); if( array_length( callerFunctionNameParts ) == 1 ) { // previouse "->something()" is not yet processed //printf("Previous '->something()' is not yet processed"); return; } char * callerClassName = array_get( callerFunctionNameParts, 0 ); char * callerMethodName = text_removeWhiteSpaces( text_slice( body, indexBeforeCaller + strlen(callerClassName) + 1, callerArgumentCloseIndex - 1 ) ); struct class * callerClass = application_getClassByClassName( allClasses, callerClassName ); struct method * callerMethod = method_getMethodByMethodName( callerClass, callerMethodName ); if( callerMethod == NULL ) { //printf("method not found"); } struct array * returnParts = text_split( callerMethod->returnType, " \t" ); char * returnDatatype = tools_findDatatype( returnParts ); if( strcmp( returnDatatype, "void *" ) ) { printf( ANSI_COLOR_RED " Error: you are not supposed to use void pointers within method chaining. %s()->%s() \n\n" ANSI_COLOR_RESET, callerMethodName, methodName); //exit( 0 ); } char * partToRemove = text_removeWhiteSpaces( text_slice( body, previousKey, argumentOpenIndex ) );// replace with a ',' char * argumentsText = text_slice( body, argumentOpenIndex + 1, argumentCloseIndex - 2 ); printf(" Processing chain: %s->%s() : %s %s \n", callerClassName, callerMethodName, callerMethod->returnType, variableName); char * testLastIndex = text_slice( body, (int)previousKey, argumentCloseIndex ); if( argumentCloseIndex == -1 ) { //continue; } // todo check if returnDatatype is a valid class if( strlen( text_removeWhiteSpaces( argumentsText ) ) == 0 ) { replacement_add( previousKey, argumentOpenIndex + 1, " ", replacements ); } else { replacement_add( previousKey, argumentOpenIndex + 1, ", ", replacements ); } struct text * newMethodDecleration = text_new( "" ); text_append( newMethodDecleration, returnDatatype ); text_append( newMethodDecleration, "_" ); text_append( newMethodDecleration, methodName); text_append( newMethodDecleration, "(" ); replacement_add( indexBeforeCaller, indexBeforeCaller, newMethodDecleration->value, replacements ); /* printf("---------------- newMethodDecleration = %s\n", newMethodDecleration); printf("---------------- methodName = %s\n", methodName); printf("---------------- argumentsText = %s\n", argumentsText); printf("---------------- testLastIndex = %s\n", testLastIndex); printf("---------------- partToRemove = %s\n", partToRemove); printf("---------------- returnType = %s\n", returnDatatype); printf("-------------------------**********argumentCloseIndex: %s %s %s %s \n\n", callerMethodName, callerClassName, callerFunctionName, variableName); */ } // class methodName // // char_concatenate // ↓ // char_concatenate( " " )->concatenate( " and this end." ) } } char * method_replaceMultiMethods( char * body ) { array * replacements = array_new(); lexer * currentLexer = lexer_new(); lexer_tokenize( currentLexer, body, "{"); lexer_tokenize( currentLexer, body, "}"); lexer_tokenize( currentLexer, body, "("); lexer_tokenize( currentLexer, body, ")"); lexer_tokenize( currentLexer, body, ";"); lexer_tokenize( currentLexer, body, "="); lexer_tokenize( currentLexer, body, "->"); lexer_tokenize( currentLexer, body, "."); lexer_add( currentLexer, 0, ";" ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "->" ) == 0 ) { method_parseFirstNextMethodInChain( currentLexer, i, body, key, replacements ); } if ( strcmp( token, "." ) == 0 ) { } } replacement_sort( replacements ); count = array_length( replacements ); for (int i = count - 1; i >= 0; --i){ struct replacement * a = array_get( replacements, i ); body = text_replaceAt( a->fromIndex, a->toIndex, body, a->content ); } if( count > 0 ) { body = method_replaceMultiMethods( body ); } return body; } void processCallback( int key, int i, char * body, array * variables, array * functions, array * replacements ) { int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); if( body[keyAfterMethod] != 40 ) { // this is for callbacks this->somecallback int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); int beforeMethodNameKey = text_getIndexBeforeWord( body, key ); char * variableName = text_removeWhiteSpaces( text_slice( body, beforeMethodNameKey, key -1 ) ); char * methodName = text_removeWhiteSpaces( text_slice( body, key + 2, (int) keyAfterMethod - 1 ) ); //char * test = text_removeWhiteSpaces( text_slice( body, beforeMethodNameKey, (int) keyAfterMethod - 1 ) ); struct variable * variable = variable_getByName( variables, variableName ); struct class * currentClass = application_getClassByClassName( allClasses, variable->datatype ); if( currentClass == 0 ) { return; } int isMethod = method_findMethodByName( currentClass, methodName ); //printf("Current class found! ------------------------- %s %s %s %i \n\n", currentClass->className, variableName, methodName, isMethod ); // this doesnt work yet -> replace inline callback functions // transform 'sqlite->print' to 'print' // replacement_add( (int) beforeMethodNameKey, (int) keyAfterMethod - 1, methodName, replacements ); if( isMethod == 1 ) { struct method * currentMethod = method_getMethodByMethodName( currentClass, methodName ); struct text * newName = text_new( "" ); text_append( newName, "callback_" ); text_append( newName, currentClass->className ); text_append( newName, "_" ); text_append( newName, methodName ); int functionExistsCheck = functionExists( functions, newName->value ); if( functionExistsCheck == -1 ) { cloneMethodToFunction( currentMethod, functions, newName->value ); } //printf("this is a callback replace '%s' with '%s' \n\n", variableName, currentClass->className); replacement_add( (int) beforeMethodNameKey, (int) keyAfterMethod, newName->value, replacements ); } } } void method_parseFirstChainMethodCall( lexer * currentLexer, int i, char * body, int currentKey, char * currentToken, struct array * variables, struct array * replacements, int methodSeparatorLength ) { void * nextToken = lexer_getToken( currentLexer, i + 1 ); void * previousToken = lexer_getToken( currentLexer, i - 1 ); //printf("this is a method: %s\n", nextToken); // ↓ // variable->method( "" )->method() if ( strcmp( previousToken, ")" ) == 0 ) { return; } if ( strcmp( nextToken, "(" ) == 0 ) { int nextKey = lexer_getKey( currentLexer, i + 1 ); char * methodName = text_slice( body, currentKey + methodSeparatorLength, nextKey - 1 ); char * variableName = text_extractWordBeforeKey( body, currentKey ); struct class * callerClass; int isVariadic = -1; int beforeVariableNameKey; char * datatype; int isPointer; // | // this->something->someMethod(); if( variableName[0] == 62 ) { int indexBeforeVariableName = text_getIndexBeforeWord( body, currentKey ); char * baseClassName = text_extractWordBeforeKey( body, indexBeforeVariableName-1 ); beforeVariableNameKey = text_getIndexBeforeWord( body, indexBeforeVariableName-1 ); char * propertyName = text_slice( body, indexBeforeVariableName + 1, currentKey -1 ); struct variable * variableInstance = variable_getByName( variables, baseClassName ); struct class * baseClass = application_getClassByClassName( allClasses, variableInstance->datatype ); int propertyIndex = class_getPropertyIndexByName( baseClass, propertyName ); struct property * propertyInstance = array_get( baseClass->properties, propertyIndex ); //callerClass = propertyInstance->datatype; datatype = propertyInstance->datatype; isPointer = propertyInstance->isPointer; variableName = text_slice( body, beforeVariableNameKey, currentKey -1 ); //printf("get property of class: %s %s %s %s ", variableInstance->datatype, propertyName, propertyInstance->datatype, methodName); } else { beforeVariableNameKey = text_getIndexBeforeWord( body, currentKey ); struct variable * variableInstance = variable_getByName( variables, variableName ); if( strcmp( variableInstance->datatype, "this_variable_is_missing" ) == 0 ) { printf( ANSI_COLOR_RED "Error: Variable with name '%s' is missing, You probably need to include a file containing a class associated with this variable. " ANSI_COLOR_RESET, variableName ); exit( 0 ); } if( isalpha( variableInstance->datatype[0] ) == 0 ) { printf(" this is not a datatype\n\n"); return; } isPointer = variableInstance->isPointer; datatype = variableInstance->datatype; /* if ( strcmp( variableName, "test" ) == 0 ) { datatype = "vector2"; } */ } callerClass = application_getClassByClassName( allClasses, datatype ); if( callerClass == NULL ) { printf( ANSI_COLOR_RED "ERROR: " ANSI_COLOR_RESET "Class '%s' not found, Maybe you need to include the file containing this the class '%s'. line number: ?? \n\n", datatype, datatype ); exit( 0 ); } struct method * callerMethod = method_getMethodByMethodName( callerClass, methodName ); if( callerMethod == NULL ) { printf(ANSI_COLOR_RED "ERROR: " ANSI_COLOR_RESET " Method '%s' not found. Class '%s' does not have an method called '%s'. \n\n", methodName, callerClass->className, methodName ); struct property * currentProperty = class_getPropertyByName( callerClass, methodName ); if( currentProperty == NULL ) { exit( 0 ); } else { if( strcmp( currentProperty->type, "function" ) != 0 ) { exit( 0 ); } else { printf("return\n\n\n\n\n"); // this is an function callback this->somecallback(); return; } } } else { //struct method * callerMethod = array_get( methods, 0 ); isVariadic = callerMethod->isVariadic; //printf("this method is isVariadic: %s %i %s\n\n", variableInstance->variableName, callerMethod->isVariadic, callerClass->className); } char * toReplace = text_slice( body, beforeVariableNameKey, nextKey - 1 ); struct text * newFunctionDeclaration = text_new( "" ); //char * newFunctionDeclaration = malloc(1000); text_append( newFunctionDeclaration, datatype ); text_append( newFunctionDeclaration, "_" ); text_append( newFunctionDeclaration, text_copy( methodName ) ); int openArgumentKey = lexer_findNextToken( currentLexer, i, "(" ); int closeArgumentKey = lexer_findNextToken( currentLexer, i, ")" ); char * argumentsText = text_removeWhiteSpaces( text_slice( body, openArgumentKey +1 , closeArgumentKey - 1 ) ); struct array * argumentsArray = text_splitArguments( argumentsText ); int argumentCount = array_length( argumentsArray ); struct text * newFirstArgument = text_new( "" ); text_append( newFirstArgument, " " ); if( isPointer == -1 ) { text_append( newFirstArgument, "&" ); } text_append( newFirstArgument, text_copy( variableName ) ); if( argumentCount > 0 ) { text_append( newFirstArgument, ", " ); } else { text_append( newFirstArgument, " " ); } if( isVariadic == 1 ) { //printf("----------------------------------============================================================ this method is variadic. %i \n\n\n\n", isVariadic); struct array * argumentDatatypes = argument_getArgumentDatatypes( argumentsArray, variables ); int argumentDatatypeCount = array_length( argumentDatatypes ); char * numberOfVariadicArguments = text_fromNumber( argumentDatatypeCount ); text_append( newFirstArgument, numberOfVariadicArguments ); text_append( newFirstArgument, ", " ); text_append( newFirstArgument, "(int[" ); text_append( newFirstArgument, numberOfVariadicArguments ); text_append( newFirstArgument, "]){ " ); for (int k = 0; k < argumentDatatypeCount; ++k) { uintptr_t datatypeIndex = ( uintptr_t ) array_get( argumentDatatypes, k ); if( k != 0 ) { text_append( newFirstArgument, "," ); } text_append( newFirstArgument, text_fromNumber( datatypeIndex ) ); } text_append( newFirstArgument, " }" ); text_append( newFirstArgument, ", " ); } replacement_add( beforeVariableNameKey, nextKey, newFunctionDeclaration->value, replacements ); replacement_add( (int) openArgumentKey+ 1, (int) openArgumentKey + 1, newFirstArgument->value, replacements ); } } struct property * method_getArrowRecursive( struct array * arrows, char * datatype ) { struct class * variableDatatypeClass = application_getClassByClassName( allClasses, datatype ); struct array * properties = variableDatatypeClass->properties; int propertyCount = array_length( properties ); char * secondVariableName = array_get( arrows, 0 ); array_delete( arrows, 0 ); for (int j = 0; j < propertyCount; ++j) { struct property * currentProperty = array_get( properties, j ); if ( strcmp( currentProperty->propertyName, secondVariableName ) == NULL ) { if( array_length( arrows ) > 0 ) { return method_getArrowRecursive( arrows, currentProperty->datatype ); } else { return currentProperty; } //return currentProperty->datatype; } } return NULL; } void method_replaceNewSymbol( lexer * currentLexer, int i, char * body, int currentKey, struct array * variables, struct array * replacements ) { int classOpenArgumentKey = lexer_findNextToken( currentLexer, i, "(" ); int isKey = lexer_findPreviousKeyByToken( currentLexer, i, "=" ); int previousLineBreak = text_findPreviousLineBreak( body, currentKey ); char * className = text_removeWhiteSpaces( text_slice( body, currentKey + 3 , classOpenArgumentKey - 1 ) ); if( isKey > 0 ) { isKey--; } char * defineText = text_removeWhiteSpaces( text_slice( body, previousLineBreak + 1, isKey ) ); struct array * defineParts = text_split( defineText, " \t" ); char * variableName = array_get( defineParts, array_length( defineParts ) - 1 ); char * classDefinition = array_get( defineParts, 0 ); if( strcmp( classDefinition, "struct" ) == 0 ) { classDefinition = array_get( defineParts, 1 ); } int isPointer = -1; if( array_length( defineParts ) == 1 ) { struct variable * variableInstance = variable_getByName( variables, text_removeWhiteSpaces( defineText ) ); printf("define text: %s\n", text_removeWhiteSpaces( defineText )); if( variableInstance == NULL ) { printf("this is not a global variable\n\n"); } else { printf(" This is an global variable %s %i\n\n ", variableInstance->variableName, variableInstance->isPointer); } isPointer = variableInstance->isPointer; } if( array_length( defineParts ) == 1 ) { struct array * arrows = text_split( classDefinition, "->" ); struct array * dotted = text_split( classDefinition, "." ); if( array_length( dotted ) > 1 ) { arrows = dotted; } if( array_length( arrows ) > 1 ) { char * firstVariableName = array_get( arrows, 0 ); array_delete( arrows, 0 ); struct variable * firstVariableInstance = variable_getByName( variables, firstVariableName ); char * variableDatatype = firstVariableInstance->datatype; struct property * currentProperty = method_getArrowRecursive( arrows, variableDatatype ); // arrow instance -> background int isKey = lexer_findPreviousKeyByToken( currentLexer, i, "=" ); int endOfDefinition = lexer_findNextTokenIndex( currentLexer, i, ";" ); int endOfDefinitionKey = lexer_getKey( currentLexer, endOfDefinition ) - 1; char * afterIs = text_removeWhiteSpaces( text_slice( body, isKey + 1, (endOfDefinitionKey) ) ); int from = text_indexOff( afterIs, "new", 0); int to = text_indexOff( afterIs, "(", 0); char * definedDatatype = text_removeWhiteSpaces( text_slice( text_copy(afterIs), from + 3, to -1 ) ); printf("find out between new and ( '%s' %s \n", currentProperty->datatype, definedDatatype); if( !currentProperty ) { printf(" Setter doesnt have an defined variable of the same name. %s\n", variableDatatype); } printf("arrow part: %s %s \n\n", firstVariableName, variableDatatype); classDefinition = currentProperty->datatype; isPointer = currentProperty->isPointer; if( strcmp( definedDatatype, classDefinition ) != NULL ) { classDefinition = definedDatatype; isPointer = -1; } } else { struct variable * firstVariableInstance = variable_getByName( variables, classDefinition ); classDefinition = firstVariableInstance->datatype; } printf(" find out datatype \n\n\n\n\n"); } else { isPointer = variable_isPointer( defineParts ); } className = classDefinition; char * newFunctionDeclaration = text_copy( classDefinition ); if( isPointer == -1 ) { newFunctionDeclaration = text_concatenate( newFunctionDeclaration, "_new" ); } else { newFunctionDeclaration = text_concatenate( newFunctionDeclaration, "_newPointer" ); } replacement_add( currentKey, classOpenArgumentKey, newFunctionDeclaration, replacements ); // dont save this as variable: 'somefunction( new classname() )' if( array_length( defineParts ) > 1 && strcmp( defineText, "" ) != 0 ) { struct variable * variableInstance = malloc( sizeof( struct variable ) ); printf("\n\n\n\n Error: %s %s \n\n\n", className, defineText); //className = text_regexReplaceAll( className, "*", "*", "_"); variableInstance->variableName = variableName; variableInstance->datatype = className; variableInstance->isPointer = isPointer; array_add( variables, variableInstance ); } } void parsePropertySetter( struct lexer * currentLexer, int i, int key, char * body, array * variables, struct array * replacements, int separatorWidth ) { int nextKey = lexer_getKey( currentLexer, i + 1 ); char * propertyName = text_removeWhiteSpaces( text_slice( body, key + separatorWidth, nextKey - 1 ) ); int endOfDefinition = lexer_findNextTokenIndex( currentLexer, i, ";" ); int endOfDefinitionKey = lexer_getKey( currentLexer, endOfDefinition ) - 1; char * afterIs = text_removeWhiteSpaces( text_slice( body, nextKey + 1, endOfDefinitionKey ) ); char * variableName = text_extractWordBeforeKey( body, key ); int keyBeforeVariableName = text_getIndexBeforeWord( body, key - 1 ); struct variable * variableInstance = variable_getByName( variables, variableName ); char * variableType = variableInstance->datatype; struct class * classInstance = application_getClassByClassName( allClasses, variableType ); if( classInstance == NULL ) { printf("Error: class with template not found: %s \n\n\n\n\n", variableType ); return; } struct text * newMethodName = text_new( "" ); text_append( newMethodName, "setter_" ); text_append( newMethodName, propertyName ); struct method * methodInstance = method_getMethodByMethodName( classInstance, newMethodName->value ); if( methodInstance == NULL ) { printf("method not found: %s %s \n", variableType, newMethodName->value); return; } if( !methodInstance->isSetter ) { return; } printf(" this is a setter\n\n\n"); struct text * setterCallback = text_new( "" ); text_append( setterCallback, variableInstance->datatype ); text_append( setterCallback, "_setter_" ); text_append( setterCallback, propertyName ); text_append( setterCallback, "( " ); if( variableInstance->isPointer == -1 ) { text_append( setterCallback, "&" ); } text_append( setterCallback, variableName); text_append( setterCallback, ", " ); if( methodInstance->isVariadic == 1 ) { int argumentDatatypeCount = 1; char * numberOfVariadicArguments = text_fromNumber( argumentDatatypeCount ); text_append( setterCallback, numberOfVariadicArguments ); text_append( setterCallback, ", " ); text_append( setterCallback, "(int[" ); text_append( setterCallback, numberOfVariadicArguments ); text_append( setterCallback, "]){ " ); uintptr_t datatypeIndex = ( uintptr_t ) argument_determineDatatypeOfArgument( afterIs, variables ); if( text_contains( afterIs, "(" ) ) { struct array * functionNameParts = text_split( text_copy( afterIs ), "_" ); int count = array_length(functionNameParts); if( count > 1 ) { char * className = array_get( functionNameParts, 0 ); struct class * classInstance = application_getClassByClassName( allClasses, className ); datatypeIndex = ( int )classInstance->classIndex; printf("getDatatypeof function: %s \n\n", afterIs); } } text_append( setterCallback, text_fromNumber( datatypeIndex ) ); text_append( setterCallback, " }" ); text_append( setterCallback, ", " ); } text_append( setterCallback, afterIs ); text_append( setterCallback, " );" ); replacement_add( keyBeforeVariableName, endOfDefinitionKey + 2, setterCallback->value, replacements ); //printf(" Parse property setter: %s %s %s %s %s \n\n ", variableName, propertyName, variableInstance->datatype, afterIs, setterCallback->value); } char * method_parse( char * body, struct array * variables, array * functions ) { //body = parseAndRemoveTemplateDeclaration( body ); array * replacements = array_new(); lexer * currentLexer = lexer_new(); lexer_tokenize( currentLexer, body, "{"); lexer_tokenize( currentLexer, body, "}"); lexer_tokenize( currentLexer, body, "("); lexer_tokenize( currentLexer, body, ")"); lexer_tokenize( currentLexer, body, ";"); lexer_tokenize( currentLexer, body, "="); lexer_tokenize( currentLexer, body, "->"); lexer_tokenize( currentLexer, body, "\""); // \" char * quotesWithinQuotes = malloc(3); quotesWithinQuotes[0] = 92; quotesWithinQuotes[1] = 34; quotesWithinQuotes[2] = 0; lexer_tokenize( currentLexer, body, quotesWithinQuotes); lexer_tokenize( currentLexer, body, "."); lexer_tokenize( currentLexer, body, ","); lexer_tokenizeRegex( currentLexer, body, "\\snew\\s", "new"); // operators lexer_tokenize( currentLexer, body, "+"); lexer_add( currentLexer, 0, ";" ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); for (int i = count - 1; i >= 0; --i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "=" ) == 0 ) { variable_extractFromDeclaration( currentLexer, key, i, body, variables ); } } int notWithinQuotes = 1; for ( int i = 0; i < count; ++i ) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "\"" ) == 0 ) { //int previousCharacter = body[i-1]; //if( previousCharacter != 92 ) { if( notWithinQuotes == 1 ) { notWithinQuotes = 0; } else { notWithinQuotes = 1; } //} } if ( strcmp( token, "new" ) == 0 && notWithinQuotes == 1 ) { method_replaceNewSymbol( currentLexer, i, body, key, variables, replacements ); } if ( strcmp( token, "->" ) == 0 ) { int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); char * nextToken = lexer_getToken( currentLexer, i + 1 ); // if character after methodName = a "(" // space after method name is not allowed. //body[keyAfterMethod] == 40 if( nextToken[0] == 40 ){ //printf("next token ------------------------------------------- : %i\n\n", (int) ((char *) array_get( tokens, i+1 ))[0]); method_parseFirstChainMethodCall( currentLexer, i, body, key, token, variables, replacements, 2 ); } } if ( strcmp( token, "." ) == 0 ) { method_parseFirstChainMethodCall( currentLexer, i, body, key, token, variables, replacements, 1 ); } } replacement_sort( replacements ); count = array_length(replacements); for (int i = count - 1; i >= 0; --i){ struct replacement * a = array_get( replacements, i ); body = text_replaceAt( a->fromIndex, a->toIndex, body, a->content ); } replacements = array_new(); currentLexer = lexer_new(); lexer_tokenize( currentLexer, body, "{"); lexer_tokenize( currentLexer, body, "}"); lexer_tokenize( currentLexer, body, "("); lexer_tokenize( currentLexer, body, ")"); lexer_tokenize( currentLexer, body, ";"); lexer_tokenize( currentLexer, body, "="); lexer_tokenize( currentLexer, body, "->"); lexer_tokenize( currentLexer, body, "\""); lexer_tokenize( currentLexer, body, quotesWithinQuotes); lexer_tokenize( currentLexer, body, "."); lexer_tokenize( currentLexer, body, ","); lexer_tokenizeRegex( currentLexer, body, "\\snew\\s", "new"); // operators lexer_tokenize( currentLexer, body, "+"); lexer_add( currentLexer, 0, ";" ); lexer_sortKeys( currentLexer ); count = lexer_length( currentLexer ); for ( int i = 0; i < count; ++i ) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); int keyAfterMethod = text_extractIndexAfterWord( body, key + 1 ); char * nextToken = lexer_getToken( currentLexer, i + 1 ); if ( strcmp( token, "->" ) == 0 ) { if( nextToken[0] == 61 ) { parsePropertySetter( currentLexer, i, key, body, variables, replacements, 2 ); } } if ( strcmp( token, "." ) == 0 ) { if( nextToken[0] == 61 ) { parsePropertySetter( currentLexer, i, key, body, variables, replacements, 1 ); } } } for (int i = 0; i < count; ++i) { char * token = lexer_getToken( currentLexer, i ); int key = lexer_getKey( currentLexer, i ); if ( strcmp( token, "->" ) == 0 ) { processCallback( key, i, body, variables, functions, replacements ); } } replacement_sort( replacements ); count = array_length(replacements); for (int i = count - 1; i >= 0; --i){ struct replacement * a = array_get( replacements, i ); body = text_replaceAt( a->fromIndex, a->toIndex, body, a->content ); } body = method_replaceMultiMethods( body ); body = method_overloadOperators( body, variables ); return body; } int method_processOperatorSymbols( char * body, int currentKey, char * currentToken, array * replacements, array * variables ) { char * operators[3] = { "+", "==", "+=" }; int operatorsCount = 3; for (int k = 0; k < operatorsCount; ++k) { char * operatorSymbol = operators[k]; int succeeded = method_processOperatorSymbol( operatorSymbol, body, currentKey, currentToken, replacements, variables ); if( succeeded == 1 ) { return 1; } } return -1; } char * method_findLeftSideSymbol( char * body, int currentKey, int symbolLength, int * beforeVariableNameKey, array * variables ) { char * leftSideSymbol; // Handle left side // leftside are parentheses // ↓ // '( ) + ... ' int firstCharacterBefore = text_findFirstCharacterReverse( body, currentKey-symbolLength-1 ); if( firstCharacterBefore == 41 ) { int firstCharacterBeforeIndex = text_text_findFirstCharacterIndexbackwards( body, currentKey-symbolLength - 1 ); // ↓ // '( ) + ... ' int argumentOpenIndex = tools_findArgumentCloseIndexReverse( body, ( int ) firstCharacterBeforeIndex ); int characterBeforeParenthesisOpen = text_findFirstCharacterReverse( body, argumentOpenIndex -1 ); int characterAfterPerenthesisOpen = text_findFirstNextCharacterNotWhiteSpaceNotParenthesis( body, argumentOpenIndex ); // ↓ // 'something( ( " " ) + ... ' if( isalpha( characterBeforeParenthesisOpen ) ) { int beforeKey = text_getIndexBeforeWord( body, argumentOpenIndex-1 ); leftSideSymbol = text_removeWhiteSpaces( text_slice( body, beforeKey, argumentOpenIndex-1 ) ); *beforeVariableNameKey = beforeKey; return leftSideSymbol; // ↓ // '( ( " " ) + ... ' } else if( body[ characterAfterPerenthesisOpen ] == 34 ) { printf("these are quotes\n\n"); leftSideSymbol = "char"; *beforeVariableNameKey = argumentOpenIndex; return leftSideSymbol; } leftSideSymbol = text_removeWhiteSpaces( text_extractWordBeforeKey( body, argumentOpenIndex ) ); struct array * leftSideSymbolParts = text_split( text_copy( leftSideSymbol ), "_" ); int partsCount = array_length( leftSideSymbolParts ); // partsCount = 3 // 'vector3_operator_add( ) + ... ' if( partsCount > 1 ) { *beforeVariableNameKey = text_getIndexBeforeWord( body, argumentOpenIndex ); } else { // →→→→→→→→ // ↓ ↓ // '( ( ( variable ) ) ) + ... ' int firstCharacterIndex = text_seekParenthesesLeftToRight( body, argumentOpenIndex ); int keyAfterMethod = text_extractIndexAfterWord( body, firstCharacterIndex + 1 ) ; // '( ( ( variable->property ) ) ) + ... ' if( body[ keyAfterMethod ] == 45 && body[ keyAfterMethod + 1 ] == 62 ) { int keyAfterProperty = text_extractIndexAfterWord( body, keyAfterMethod + 1 ) ; leftSideSymbol = text_removeWhiteSpaces( text_slice( body, firstCharacterIndex, keyAfterProperty ) ); // '( ( ( variable ) ) ) + ... ' } else { leftSideSymbol = text_removeWhiteSpaces( text_slice( body, firstCharacterIndex, keyAfterMethod - 1 ) ); } *beforeVariableNameKey = argumentOpenIndex; } // ↓ // leftSide is not opening parentheses '( ) + ' // but ↓ // ' someName + somename' } else { *beforeVariableNameKey = text_getIndexBeforeWord( body, currentKey ); int firstCharacterReverse = text_text_findFirstCharacterIndexbackwards( body, currentKey-symbolLength ); int beforeKey = text_getIndexBeforeWord( body, currentKey-symbolLength ); // variableName->propertyName if( body[ beforeKey ] == 62 && body[ beforeKey - 1 ] == 45 ) { int indexBeforeClassName = text_getIndexBeforeWord( body, beforeKey - 1 ); *beforeVariableNameKey = indexBeforeClassName; leftSideSymbol = text_removeWhiteSpaces( text_slice( body, indexBeforeClassName, currentKey-1 ) ); // "something" + ... } else if( body[ firstCharacterReverse ] == 34 ) { leftSideSymbol = "char"; *beforeVariableNameKey = *beforeVariableNameKey-1; //printf(" method 7\n"); } else { // printf(" -- this part "); int indexBeforeClassName = text_getIndexBeforeWord( body, currentKey - symbolLength ); *beforeVariableNameKey = indexBeforeClassName; leftSideSymbol = text_removeWhiteSpaces( text_slice( body, indexBeforeClassName, currentKey-symbolLength ) ); /* leftSideSymbol = text_removeWhiteSpaces( text_extractWordBeforeKey( body, currentKey - symbolLength - 1 ) ); */ } } return leftSideSymbol; } int method_findRightSideEndIndex( char * body, int currentKey, int symbolLength, struct array * variables ) { int firstNextCharacter = text_findFirstNextCharacterNotWhiteSpace( body, currentKey + symbolLength ); int keyAfterOperator ; // quoted text " sometext " if( body[firstNextCharacter] == 34 ) { keyAfterOperator = text_findQuoteCloseIndex( body, firstNextCharacter ); keyAfterOperator++; } else { keyAfterOperator = text_extractIndexAtWhiteSpace( body, currentKey + symbolLength ); } // if " ... + someObject->property " if( body[ keyAfterOperator ] == 45 && body[ keyAfterOperator + 1 ] == 62 ) { keyAfterOperator = text_extractIndexAtWhiteSpace( body, keyAfterOperator + 1 ); } // ↓ // if " ... + some_function_name( ... ) " if( body[ keyAfterOperator ] == 40 ) { // find ↓ // new key " ... = some_function_name( ... ) " // check if rightSideFunction is a valid type char * rightSideFunctionName = text_removeWhiteSpaces( text_slice( body, currentKey + symbolLength, keyAfterOperator - 1 ) ); struct array * functionNameParts = text_split( text_copy( rightSideFunctionName ), "_" ); int partsCount = array_length( functionNameParts ); if( partsCount == 1 ) { // find function //printf(" rightside is an function: %s\n\n\n", rightSideFunctionName); for (int i = 0; i < total_libc_function; ++i) { char * libcFunctionName = libcFunctionNames[i]; if ( strcmp( libcFunctionName, rightSideFunctionName ) == 0 ) { char * returnType = libcReturnTypes[i]; //printf("function found!! return type is %s\n\n\n", returnType); if( class_classNameIsPrimitive( returnType ) == 1 ) { //printf(" this is an number %s\n\n", returnType); return -1; } } } } keyAfterOperator = text_findArgumentCloseIndex( body, keyAfterOperator ); } // if the right side is opening parentheses " + ( ) " // ( if( body[keyAfterOperator] == 40 ) { int argumentOpenIndex = text_text_findFirstCharacterIndexFromIndex( body, "(", currentKey ); int argumentCloseIndex = text_findArgumentCloseIndex( body, ( int ) argumentOpenIndex ); keyAfterOperator = argumentCloseIndex; } char * rightSideSymbol = text_removeWhiteSpaces( text_slice( body, currentKey + symbolLength, keyAfterOperator -1 ) ); struct variable * rightsideVariable = variable_getByName( variables, rightSideSymbol ); if( class_classNameIsPrimitive( rightsideVariable->datatype ) == 1 ) { return -1; } //*rightSideIsPointer = rightsideVariable->isPointer; return keyAfterOperator; } int method_processOperatorSymbol( char * currentOperatorSymbol, char * body, int currentKey, char * currentToken, array * replacements, array * variables ) { int operatorSymbolLength = strlen( currentOperatorSymbol ); if( body[ currentKey + operatorSymbolLength ] > 48 ) { return -1; } if ( strcmp( currentToken, currentOperatorSymbol ) != 0 ) { return -1; } int rightSideIsPointer = 1; int keyAfterOperator = method_findRightSideEndIndex( body, currentKey, operatorSymbolLength, variables ); char * rightSideSymbol = text_removeWhiteSpaces( text_slice( body, currentKey + operatorSymbolLength, keyAfterOperator ) ); char * rightSideBaseClass = class_getBaseClassNameBySymbol( rightSideSymbol, variables, &rightSideIsPointer ); //printf(" RightSideSymbol: %s\n\n RightSideBase: %s %i \n\n", rightSideSymbol, rightSideBaseClass, rightSideIsPointer); if( keyAfterOperator == -1 ) { return -1; } if( operatorSymbolLength == 1 ) { if( body[ currentKey + 1 ] == 43 ) { return -1; } } int indexBeforeLeftSideSymbol; int leftSideIsPointer = 1; char * leftSideSymbol = method_findLeftSideSymbol( body, currentKey, operatorSymbolLength, &indexBeforeLeftSideSymbol, variables ); char * baseClassName = class_getBaseClassNameBySymbol( leftSideSymbol, variables, &leftSideIsPointer ); //printf(" leftSideSymbol: %-20s baseClassName: %s Operator: %s \n\n\n", leftSideSymbol, baseClassName, currentOperatorSymbol ,text_slice(body, indexBeforeLeftSideSymbol, keyAfterOperator)); //printf(" leftSide is pointer?? %i\n\n", leftSideIsPointer); if( baseClassName == NULL ) { return -1; } if( strcmp( text_copy( baseClassName ) , "char" ) == 0 ) { leftSideIsPointer = 1; } char * openingDeclaration = class_openingDeclarationFromBaseClassName( baseClassName, currentOperatorSymbol, leftSideIsPointer ); //printf(" openingDeclaration: %s \n\n", openingDeclaration); if( openingDeclaration != NULL ) { replacement_add( indexBeforeLeftSideSymbol, indexBeforeLeftSideSymbol, openingDeclaration, replacements ); if( rightSideIsPointer == 1 ) { replacement_add( (int) currentKey, (int) currentKey + operatorSymbolLength, ", ", replacements ); } else { replacement_add( (int) currentKey, (int) currentKey + operatorSymbolLength, ", &", replacements ); } replacement_add( (int) keyAfterOperator, (int) keyAfterOperator , ")", replacements ); return 1; } return -1; } char * method_overloadOperators( char * body, struct array * variables ) { lexer * currentLexer = lexer_new(); struct array * depthArray = array_new(); struct array * depthIndices = array_new(); struct array * replacements = array_new(); lexer_tokenize( currentLexer, body, "{"); lexer_tokenize( currentLexer, body, "}"); lexer_tokenize( currentLexer, body, "("); lexer_tokenize( currentLexer, body, ")"); lexer_tokenize( currentLexer, body, ";"); lexer_tokenize( currentLexer, body, "="); lexer_tokenize( currentLexer, body, "->"); lexer_tokenize( currentLexer, body, "."); lexer_tokenize( currentLexer, body, "+"); lexer_tokenize( currentLexer, body, "+="); lexer_tokenize( currentLexer, body, "=="); lexer_add( currentLexer, 0, ";" ); lexer_sortKeys( currentLexer ); int count = lexer_length( currentLexer ); intptr_t depth = 0; for ( intptr_t i = 0; i < count; ++i ) { int key = lexer_getKey( currentLexer, i ); char * token = lexer_getToken( currentLexer, i ); if( strcmp( token, "(" ) ) { depth--; } if( strcmp( token, ")" ) ) { depth++; } array_add( depthArray, ( void * ) depth ); array_add( depthIndices, ( void * ) i ); } // replace this with a lexer or something. lexer_sortKeys_separate( depthArray, depthIndices ); for (int i = count - 1; i >= 0; --i) { intptr_t depthIndex = ( intptr_t ) array_get( depthIndices, i ); int key = lexer_getKey( currentLexer, depthIndex ); void * token = lexer_getToken( currentLexer, depthIndex ); int succeeded = method_processOperatorSymbols( body, key, token, replacements, variables ); if( succeeded == 1 ) { break; } } replacement_sort( replacements ); count = array_length(replacements); for (int i = count - 1; i >= 0; --i){ struct replacement * a = array_get( replacements, i ); body = text_replaceAt( a->fromIndex, a->toIndex, body, a->content ); } if( count > 0 ) { body = method_overloadOperators( body, variables ); } return body; } void method_compose( struct method * currentMethod, char * className, struct array * sourceArray, struct text * classHeader ) { char * methodName = currentMethod->methodName; struct text * methodSource = text_new(""); if( strlen( currentMethod->returnType ) == 0 ) { text_append( methodSource, "void" ); } else { text_append( methodSource, text_removeWhiteSpaces( currentMethod->returnType ) ); } text_append( methodSource, " " ); text_append( methodSource, className ); text_append( methodSource, "_" ); text_append( methodSource, methodName ); text_append( methodSource, "( " ); int argumentsLength = array_length( currentMethod->arguments ); for (int j = 0; j < argumentsLength; ++j) { char * argumentText = text_copy( array_get( currentMethod->arguments, j ) ); if( j != 0 ) { text_append( methodSource, ", " ); } text_append( methodSource, argumentText ); } text_append( classHeader, text_copy( methodSource->value ) ); text_append( classHeader, " );\n\n" ); struct text * finalMethodCode = text_new(""); text_append( finalMethodCode, text_copy( methodSource->value ) ); text_append( finalMethodCode, " ) {" ); text_append( finalMethodCode, text_copy( currentMethod->body ) ); text_append( finalMethodCode, "}" ); struct codeBundle * code = malloc( sizeof( struct codeBundle ) ); code->lineNumber = currentMethod->lineNumber; code->sourceCode = finalMethodCode->value; array_add( sourceArray, code ); text_free( methodSource ); }