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