2013-11-01 02:52:18 -04:00
# include "CGenerator.h"
2016-01-28 12:20:28 -05:00
# define CLEAR_SCREEN "\033[2J\033[1;1H"
# define BOLD_GREEN "\033[1m\033[32m"
# define RESET_TXT "\033[0m"
2013-12-22 01:34:59 -06:00
CGenerator : : CGenerator ( ) : generatorString ( " __C__ " ) {
2015-11-09 13:26:02 -05:00
tabLevel = 0 ;
2015-05-30 04:43:01 -04:00
id = 0 ;
2015-06-12 14:16:28 -04:00
function_header = " fun_ " ;
2015-07-04 18:55:15 -04:00
functionTypedefString = " " ;
functionTypedefStringPre = " " ;
2013-11-01 02:52:18 -04:00
}
CGenerator : : ~ CGenerator ( ) {
}
2014-12-30 01:22:09 -05:00
// Note the use of std::pair to hold two strings - the running string for the header file and the running string for the c file.
2016-01-31 19:29:08 -05:00
int CGenerator : : generateCompSet ( std : : map < std : : string , NodeTree < ASTData > * > ASTs , std : : string outputName ) {
2015-11-09 13:26:02 -05:00
//Generate an entire set of files
std : : string buildString = " #!/bin/sh \n cc -g -O3 -std=c99 " ;
std : : cout < < " \n \n =====GENERATE PASS===== \n \n " < < std : : endl ;
2015-03-11 01:58:10 -04:00
std : : cout < < " \n \n Generate pass for: " < < outputName < < std : : endl ;
buildString + = outputName + " .c " ;
2015-11-06 03:23:55 -05:00
//std::ofstream outputCFile, outputHFile;
std : : ofstream outputCFile ;
2015-03-11 01:58:10 -04:00
outputCFile . open ( outputName + " / " + outputName + " .c " ) ;
2015-11-06 03:23:55 -05:00
//outputHFile.open(outputName + "/" + outputName + ".h");
//if (outputCFile.is_open() || outputHFile.is_open()) {
if ( outputCFile . is_open ( ) ) {
2015-03-11 01:58:10 -04:00
// Prequel common to all files
auto chPair = generateTranslationUnit ( outputName , ASTs ) ;
2015-11-06 03:23:55 -05:00
//outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first;
//outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second;
outputCFile < < " #include <stdbool.h> \n #include <stdlib.h> \n #include <stdio.h> \n " < < chPair . first < < " \n \n // C FILE BEGIN \n \n " < < chPair . second ;
2015-03-11 01:58:10 -04:00
} else {
2015-03-14 02:42:07 -04:00
std : : cerr < < " Cannot open file " < < outputName < < " .c/h " < < std : : endl ;
2015-03-11 01:58:10 -04:00
}
outputCFile . close ( ) ;
2015-11-06 03:23:55 -05:00
//outputHFile.close();
2015-03-11 01:58:10 -04:00
2015-11-09 13:26:02 -05:00
buildString + = linkerString ;
buildString + = " -o " + outputName ;
std : : ofstream outputBuild ;
2016-01-24 03:14:24 -05:00
std : : string scriptName = split ( outputName , ' / ' ) . back ( ) + " .sh " ;
outputBuild . open ( outputName + " / " + scriptName ) ;
2015-11-09 13:26:02 -05:00
outputBuild < < buildString ;
outputBuild . close ( ) ;
2016-01-28 12:20:28 -05:00
std : : cout < < CLEAR_SCREEN ;
std : : cout < < BOLD_GREEN < < " KRAKEN COMPILER DONE, CALLING C COMPILER " < < RESET_TXT < < std : : endl ;
2016-01-31 19:29:08 -05:00
return ssystem ( " cd " + outputName + " /; sh " + scriptName ) ;
2014-01-01 17:29:19 -06:00
}
2013-11-01 02:52:18 -04:00
std : : string CGenerator : : tabs ( ) {
2015-11-09 13:26:02 -05:00
std : : string returnTabs ;
for ( int i = 0 ; i < tabLevel ; i + + )
returnTabs + = " \t " ;
return returnTabs ;
2013-11-01 02:52:18 -04:00
}
2015-05-30 04:43:01 -04:00
std : : string CGenerator : : getID ( ) {
return intToString ( id + + ) ;
}
2015-08-29 21:45:55 -04:00
std : : string CGenerator : : generateTypeStruct ( NodeTree < ASTData > * from ) {
2014-07-28 01:52:15 -07:00
auto data = from - > getData ( ) ;
auto children = from - > getChildren ( ) ;
2015-11-19 16:27:36 -05:00
//std::string structString, enumString, functionString;
std : : string structString , enumString ;
2015-11-06 03:23:55 -05:00
std : : string enumName = " __enum_dummy_ " + prefixIfNeeded ( scopePrefix ( from ) , CifyName ( data . symbol . getName ( ) ) + " __ " ) ;
enumString = " enum " + enumName + " { \n " ;
structString = " struct __struct_dummy_ " ;
structString + = prefixIfNeeded ( scopePrefix ( from ) , CifyName ( data . symbol . getName ( ) ) + " __ " ) + " { \n " ;
if ( data . type = = adt_def ) {
2015-12-04 03:41:46 -05:00
structString = structString + " enum " + enumName + " flag; \n union { \n " ;
2015-11-13 15:49:00 -05:00
tabLevel + + ;
2015-11-06 03:23:55 -05:00
}
2014-07-28 01:52:15 -07:00
tabLevel + + ;
2015-11-06 03:23:55 -05:00
for ( auto child : children ) {
2015-08-06 17:38:41 -04:00
//std::cout << children[i]->getName() << std::endl;
2015-11-06 03:23:55 -05:00
if ( child - > getName ( ) ! = " function " ) {
if ( data . type = = adt_def ) {
// if this is not a plain no-data adt member (so if it is a primitive or doesn't have a reference back to)
// wait a sec, this is easier
if ( child - > getDataRef ( ) - > valueType - > typeDefinition ! = from )
2016-01-05 21:40:00 -05:00
structString + = tabs ( ) + ValueTypeToCType ( child - > getDataRef ( ) - > valueType , prefixIfNeeded ( scopePrefix ( child ) , child - > getDataRef ( ) - > symbol . getName ( ) ) ) + " ; /* adt data member */ \n " ;
2015-11-06 03:23:55 -05:00
} else {
structString + = tabs ( ) + generate ( child , nullptr ) . oneString ( ) + " \n " ;
}
2016-01-05 21:40:00 -05:00
//enumString += tabs() + data.symbol.getName() + "__" + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n");
// this was prefixing when it shouldn't have, since we prefix with the name of the adt anyway. Probs the entire thing should be prefixed, but we'll cross that bridge when we come to it
enumString + = tabs ( ) + data . symbol . getName ( ) + " __ " + child - > getDataRef ( ) - > symbol . getName ( ) + ( data . type = = adt_def ? " , \n " : " \n " ) ;
2015-11-06 03:23:55 -05:00
}
2014-07-28 01:52:15 -07:00
}
tabLevel - - ;
2015-11-06 03:23:55 -05:00
if ( data . type = = adt_def ) {
//structString += "} data; /*end union*/ \n";
2015-11-13 15:49:00 -05:00
tabLevel - - ;
2015-12-04 03:41:46 -05:00
structString + = " }; /*end union*/ \n }; " ;
2015-11-06 03:23:55 -05:00
} else {
structString + = " }; " ;
}
enumString + = " }; \n " ;
if ( data . type = = adt_def )
2015-11-19 16:27:36 -05:00
return enumString + structString ;
2015-11-06 03:23:55 -05:00
return structString ;
2014-07-28 01:52:15 -07:00
}
// This method recurseivly generates all aliases of some definition
2015-03-11 01:58:10 -04:00
std : : string CGenerator : : generateAliasChains ( std : : map < std : : string , NodeTree < ASTData > * > ASTs , NodeTree < ASTData > * definition ) {
2015-11-09 13:26:02 -05:00
std : : string output ;
for ( auto trans : ASTs ) {
for ( auto i = trans . second - > getDataRef ( ) - > scope . begin ( ) ; i ! = trans . second - > getDataRef ( ) - > scope . end ( ) ; i + + ) {
for ( auto declaration : i - > second ) {
auto declarationData = declaration - > getDataRef ( ) ;
if ( declarationData - > type = = type_def
& & declarationData - > valueType - > typeDefinition ! = declaration
& & declarationData - > valueType - > typeDefinition = = definition ) {
output + = " typedef " +
prefixIfNeeded ( scopePrefix ( definition ) , CifyName ( definition - > getDataRef ( ) - > symbol . getName ( ) ) ) + " " +
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData - > symbol . getName ( ) ) ) + " ; \n " ;
// Recursively add the ones that depend on this one
output + = generateAliasChains ( ASTs , declaration ) ;
}
2014-07-28 01:52:15 -07:00
}
}
}
2015-11-09 13:26:02 -05:00
return output ;
2015-11-06 03:23:55 -05:00
}
bool CGenerator : : isUnderNodeWithType ( NodeTree < ASTData > * from , ASTType type ) {
2015-11-09 13:26:02 -05:00
auto scope = from - > getDataRef ( ) - > scope ;
auto upper = scope . find ( " ~enclosing_scope " ) ;
if ( upper ! = scope . end ( ) ) {
if ( upper - > second [ 0 ] - > getDataRef ( ) - > type = = type )
return true ;
return isUnderNodeWithType ( upper - > second [ 0 ] , type ) ;
}
return false ;
2014-07-28 01:52:15 -07:00
}
2014-12-30 01:22:09 -05:00
bool CGenerator : : isUnderTranslationUnit ( NodeTree < ASTData > * from , NodeTree < ASTData > * node ) {
2015-11-09 13:26:02 -05:00
auto scope = from - > getDataRef ( ) - > scope ;
for ( auto i : scope )
for ( auto j : i . second )
if ( j = = node )
return true ;
2014-12-30 01:22:09 -05:00
2015-11-09 13:26:02 -05:00
auto upper = scope . find ( " ~enclosing_scope " ) ;
if ( upper ! = scope . end ( ) )
return isUnderTranslationUnit ( upper - > second [ 0 ] , node ) ;
return false ;
2014-12-30 01:22:09 -05:00
}
NodeTree < ASTData > * CGenerator : : highestScope ( NodeTree < ASTData > * node ) {
2015-11-09 13:26:02 -05:00
auto it = node - > getDataRef ( ) - > scope . find ( " ~enclosing_scope " ) ;
while ( it ! = node - > getDataRef ( ) - > scope . end ( ) ) {
node = it - > second [ 0 ] ;
it = node - > getDataRef ( ) - > scope . find ( " ~enclosing_scope " ) ;
}
return node ;
2014-12-30 01:22:09 -05:00
}
// We do translation units in their own function so they can do the pariwise h/c stuff and regualr in function body generation does not
2015-03-11 01:58:10 -04:00
std : : pair < std : : string , std : : string > CGenerator : : generateTranslationUnit ( std : : string name , std : : map < std : : string , NodeTree < ASTData > * > ASTs ) {
2015-11-09 13:26:02 -05:00
// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file
std : : string cOutput , hOutput ;
// Ok, so we've got to do this in passes to preserve mututally recursive definitions.
//
// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;".
// Also, other typedefs follow after their naming.
// Second Pass: All top level variable declarations
// Third Pass: Define all actual structs of a class, in correct order (done with posets)
// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too).
// (this includes object methods)
// Fifth Pass: Define all functions (including object methods).
2014-07-28 01:52:15 -07:00
2015-11-09 13:26:02 -05:00
// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth
// are done simultanously, but append to different strings that are then concatinated properly, in order.
2014-07-28 01:52:15 -07:00
2015-11-09 13:26:02 -05:00
std : : string importIncludes = " /** \n * Import Includes \n */ \n \n " ;
std : : string topLevelCPassthrough = " /** \n * Top Level C Passthrough \n */ \n \n " ;
std : : string variableExternDeclarations = " /** \n * Extern Variable Declarations \n */ \n \n " ;
std : : string plainTypedefs = " /** \n * Plain Typedefs \n */ \n \n " ;
std : : string variableDeclarations = " /** \n * Variable Declarations \n */ \n \n " ;
std : : string classStructs = " /** \n * Class Structs \n */ \n \n " ;
std : : string functionPrototypes = " /** \n * Function Prototypes \n */ \n \n " ;
std : : string functionDefinitions = " /** \n * Function Definitions \n */ \n \n " ;
// There also exists functionTypedefString which is a member variable that keeps
// track of utility typedefs that allow our C type generation to be more sane
// it is emitted in the h file right before functionPrototypes
2014-07-28 01:52:15 -07:00
2015-11-09 13:26:02 -05:00
Poset < NodeTree < ASTData > * > typedefPoset ;
for ( auto trans : ASTs ) {
auto children = trans . second - > getChildren ( ) ;
for ( int i = 0 ; i < children . size ( ) ; i + + ) {
if ( children [ i ] - > getDataRef ( ) - > type = = type_def ) {
// If we're an alias type, continue. We handle those differently
if ( children [ i ] - > getDataRef ( ) - > valueType - > typeDefinition ! = children [ i ] )
continue ;
2014-05-21 13:14:16 -04:00
2015-11-09 13:26:02 -05:00
typedefPoset . addVertex ( children [ i ] ) ; // We add this definition by itself just in case there are no dependencies.
// If it has dependencies, there's no harm in adding it here
// Go through every child in the class looking for declaration statements. For each of these that is not a primitive type
// we will add a dependency from this definition to that definition in the poset.
std : : vector < NodeTree < ASTData > * > classChildren = children [ i ] - > getChildren ( ) ;
for ( auto j : classChildren ) {
if ( j - > getDataRef ( ) - > type = = declaration_statement ) {
Type * decType = j - > getChildren ( ) [ 0 ] - > getDataRef ( ) - > valueType ; // Type of the declaration
if ( decType - > typeDefinition & & decType - > getIndirection ( ) = = 0 ) // If this is a custom type and not a pointer
typedefPoset . addRelationship ( children [ i ] , decType - > typeDefinition ) ; // Add a dependency
}
2014-12-30 01:22:09 -05:00
}
2015-11-09 13:26:02 -05:00
} else if ( children [ i ] - > getDataRef ( ) - > type = = adt_def ) {
typedefPoset . addVertex ( children [ i ] ) ; // We add this definition by itself just in case there are no dependencies.
2015-12-04 03:41:46 -05:00
std : : vector < NodeTree < ASTData > * > adtChildren = children [ i ] - > getChildren ( ) ;
for ( auto j : adtChildren ) {
if ( j - > getDataRef ( ) - > type = = identifier ) {
Type * decType = j - > getDataRef ( ) - > valueType ; // Type of the declaration
if ( decType - > typeDefinition = = children [ i ] )
continue ;
if ( decType - > typeDefinition & & decType - > getIndirection ( ) = = 0 ) // If this is a custom type and not a pointer
typedefPoset . addRelationship ( children [ i ] , decType - > typeDefinition ) ; // Add a dependency
}
}
2014-12-30 01:22:09 -05:00
}
}
}
2015-11-09 13:26:02 -05:00
//Now generate the typedef's in the correct, topological order
for ( NodeTree < ASTData > * i : typedefPoset . getTopoSort ( ) )
classStructs + = generateTypeStruct ( i ) + " \n " ;
2014-07-28 01:52:15 -07:00
2015-11-09 13:26:02 -05:00
// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations)
// Also, everything in all of the import's scopes
// Also c passthrough
for ( auto trans : ASTs ) {
// First go through and emit all the passthroughs, etc
for ( auto i : trans . second - > getChildren ( ) ) {
if ( i - > getDataRef ( ) - > type = = if_comp )
topLevelCPassthrough + = generate ( i , nullptr ) . oneString ( ) ;
}
2015-03-24 18:29:21 -04:00
2015-11-09 13:26:02 -05:00
for ( auto i = trans . second - > getDataRef ( ) - > scope . begin ( ) ; i ! = trans . second - > getDataRef ( ) - > scope . end ( ) ; i + + ) {
for ( auto declaration : i - > second ) {
std : : vector < NodeTree < ASTData > * > decChildren = declaration - > getChildren ( ) ;
ASTData declarationData = declaration - > getData ( ) ;
switch ( declarationData . type ) {
case identifier :
{
auto parent = declaration - > getDataRef ( ) - > scope [ " ~enclosing_scope " ] [ 0 ] ;
if ( parent - > getChildren ( ) . size ( ) = = 1 )
variableDeclarations + = ValueTypeToCType ( declarationData . valueType , prefixIfNeeded ( scopePrefix ( declaration ) , declarationData . symbol . getName ( ) ) ) + " ; /*identifier*/ \n " ;
else
variableDeclarations + = ValueTypeToCType ( declarationData . valueType , generate ( parent - > getChildren ( ) [ 0 ] , nullptr , true , nullptr ) . oneString ( ) ) + " = " + generate ( parent - > getChildren ( ) [ 1 ] , nullptr , true , nullptr ) . oneString ( ) + " ; " ;
variableExternDeclarations + = " extern " + ValueTypeToCType ( declarationData . valueType , declarationData . symbol . getName ( ) ) + " ; /*extern identifier*/ \n " ;
break ;
2015-06-19 12:48:18 -04:00
}
2015-03-11 01:58:10 -04:00
case function :
{
if ( declarationData . valueType - > baseType = = template_type )
functionPrototypes + = " /* template function " + declarationData . symbol . toString ( ) + " */ \n " ;
else if ( decChildren . size ( ) = = 0 ) //Not a real function, must be a built in passthrough
functionPrototypes + = " /* built in function: " + declarationData . symbol . toString ( ) + " */ \n " ;
else {
std : : string nameDecoration , parameters ;
2015-06-25 04:09:19 -04:00
if ( declarationData . closedVariables . size ( ) )
2015-06-26 13:29:37 -04:00
parameters + = closureStructType ( declarationData . closedVariables ) + " * " ;
2015-03-11 01:58:10 -04:00
for ( int j = 0 ; j < decChildren . size ( ) - 1 ; j + + ) {
2015-06-25 04:09:19 -04:00
if ( j > 0 | | declarationData . closedVariables . size ( ) )
2015-03-11 01:58:10 -04:00
parameters + = " , " ;
2015-05-30 04:43:01 -04:00
parameters + = ValueTypeToCType ( decChildren [ j ] - > getData ( ) . valueType , generate ( decChildren [ j ] , nullptr ) . oneString ( ) ) ;
2015-03-11 01:58:10 -04:00
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( decChildren [ j ] - > getData ( ) . valueType ) ;
}
2015-11-06 03:23:55 -05:00
std : : string funName = ( declarationData . symbol . getName ( ) = = " main " ) ? " main " :
function_header + prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) + nameDecoration ) ) ;
functionPrototypes + = " \n " + ValueTypeToCType ( declarationData . valueType - > returnType , funName ) + " ( " + parameters + " ); /*func*/ \n " ;
2015-03-11 01:58:10 -04:00
// generate function
2015-11-13 15:49:00 -05:00
//std::cout << "Generating " << prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) << std::endl;
2015-05-30 04:43:01 -04:00
functionDefinitions + = generate ( declaration , nullptr ) . oneString ( ) ;
2015-03-11 01:58:10 -04:00
}
2014-12-30 01:22:09 -05:00
}
2015-03-11 01:58:10 -04:00
break ;
case type_def :
//type
plainTypedefs + = " /*typedef " + declarationData . symbol . getName ( ) + " */ \n " ;
2014-12-30 01:22:09 -05:00
2015-03-11 01:58:10 -04:00
if ( declarationData . valueType - > baseType = = template_type ) {
plainTypedefs + = " /* non instantiated template " + declarationData . symbol . getName ( ) + " */ " ;
} else if ( declarationData . valueType - > typeDefinition ! = declaration ) {
if ( declarationData . valueType - > typeDefinition )
continue ; // Aliases of objects are done with the thing it alises
// Otherwise, we're actually a renaming of a primitive, can generate here
2015-05-18 04:46:03 -04:00
plainTypedefs + = " typedef " + ValueTypeToCType ( declarationData . valueType ,
2015-11-09 13:26:02 -05:00
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) ) ) ) + " ; \n " ;
2015-03-11 01:58:10 -04:00
plainTypedefs + = generateAliasChains ( ASTs , declaration ) ;
} else {
2015-04-04 01:32:40 -04:00
plainTypedefs + = " typedef struct __struct_dummy_ " +
2015-11-09 13:26:02 -05:00
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) ) + " __ " ) + " " +
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) ) ) + " ; \n " ;
2015-03-11 01:58:10 -04:00
functionPrototypes + = " /* Method Prototypes for " + declarationData . symbol . getName ( ) + " */ \n " ;
// We use a seperate string for this because we only include it if this is the file we're defined in
std : : string objectFunctionDefinitions = " /* Method Definitions for " + declarationData . symbol . getName ( ) + " */ \n " ;
for ( int j = 0 ; j < decChildren . size ( ) ; j + + ) {
2015-11-13 15:49:00 -05:00
//std::cout << decChildren[j]->getName() << std::endl;
2015-05-27 00:58:33 -04:00
if ( decChildren [ j ] - > getName ( ) = = " function "
& & decChildren [ j ] - > getDataRef ( ) - > valueType - > baseType ! = template_type ) //If object method and not template
2015-03-11 01:58:10 -04:00
objectFunctionDefinitions + = generateObjectMethod ( declaration , decChildren [ j ] , & functionPrototypes ) + " \n " ;
}
// Add all aliases to the plain typedefs. This will add any alias that aliases to this object, and any alias that aliases to that, and so on
plainTypedefs + = generateAliasChains ( ASTs , declaration ) ;
functionPrototypes + = " /* Done with " + declarationData . symbol . getName ( ) + " */ \n " ;
// include methods
2014-12-30 01:22:09 -05:00
functionDefinitions + = objectFunctionDefinitions + " /* Done with " + declarationData . symbol . getName ( ) + " */ \n " ;
2015-03-11 01:58:10 -04:00
}
break ;
2015-08-29 21:45:55 -04:00
case adt_def :
2015-11-09 13:26:02 -05:00
{
2015-12-04 03:41:46 -05:00
plainTypedefs + = " typedef struct __struct_dummy_ " +
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) ) + " __ " ) + " " +
prefixIfNeeded ( scopePrefix ( declaration ) , CifyName ( declarationData . symbol . getName ( ) ) ) + " ; \n " ;
2015-11-19 16:27:36 -05:00
for ( auto child : decChildren ) {
if ( child - > getName ( ) = = " function " ) {
std : : string orig_fun_name = child - > getDataRef ( ) - > symbol . getName ( ) ;
2015-11-21 15:28:57 -05:00
std : : string nameDecoration ;
for ( Type * paramType : child - > getDataRef ( ) - > valueType - > parameterTypes )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( paramType ) ;
std : : string fun_name = " fun_ " + declarationData . symbol . getName ( ) + " __ " + CifyName ( orig_fun_name + nameDecoration ) ;
2015-11-19 16:27:36 -05:00
std : : string first_param ;
2015-11-25 15:35:06 -05:00
if ( orig_fun_name = = " operator== " | | orig_fun_name = = " operator!= " | | orig_fun_name = = " copy_construct " | | orig_fun_name = = " operator= "
| | orig_fun_name = = " destruct " ) {
2015-11-21 15:28:57 -05:00
first_param = ValueTypeToCType ( declarationData . valueType - > withIncreasedIndirectionPtr ( ) , " this " ) ;
2015-11-19 16:27:36 -05:00
}
bool has_param = child - > getDataRef ( ) - > valueType - > parameterTypes . size ( ) ;
std : : string first_part = " \n " + ValueTypeToCType ( child - > getDataRef ( ) - > valueType - > returnType , fun_name ) + " ( " + first_param +
2015-11-21 15:28:57 -05:00
( has_param ? ( first_param ! = " " ? " , " : " " ) + ValueTypeToCType ( child - > getDataRef ( ) - > valueType - > parameterTypes [ 0 ] , " in " ) : " " ) + " ) " ;
2015-11-19 16:27:36 -05:00
functionPrototypes + = first_part + " ; /*adt func*/ \n " ;
functionDefinitions + = first_part + " { /*adt func*/ \n " ;
if ( orig_fun_name = = " operator== " ) {
functionDefinitions + = " /* equality woop woop */ \n " ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " bool equal = true; \n " ;
functionDefinitions + = " if (this->flag != in->flag) equal = false; \n " ;
2015-11-19 16:27:36 -05:00
for ( auto child : decChildren ) {
if ( child - > getName ( ) ! = " function " & & child - > getDataRef ( ) - > valueType - > typeDefinition ! = declaration ) {
std : : string option_name = child - > getDataRef ( ) - > symbol . getName ( ) ;
2016-01-05 21:40:00 -05:00
std : : string prefixed_option_name = prefixIfNeeded ( scopePrefix ( declaration ) , option_name ) ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " else if (this->flag == " + declarationData . symbol . getName ( ) + " __ " + option_name + " ) { \n " ;
2015-11-19 16:27:36 -05:00
NodeTree < ASTData > * method = nullptr ;
2016-01-15 19:10:52 -05:00
if ( ( method = getMethod ( child - > getDataRef ( ) - > valueType , " operator== " , std : : vector < Type > { * child - > getDataRef ( ) - > valueType } ) ) ) {
2015-11-25 15:35:06 -05:00
bool is_reference = method - > getDataRef ( ) - > valueType - > parameterTypes [ 0 ] - > is_reference ;
auto itemTypeVector = std : : vector < Type > { child - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ;
bool need_temporary = ! is_reference & & getMethod ( child - > getDataRef ( ) - > valueType , " copy_construct " , itemTypeVector ) ;
if ( need_temporary ) {
functionDefinitions + = " " + ValueTypeToCType ( child - > getDataRef ( ) - > valueType , " copy_constructTemporary " ) + " ; \n " ;
functionDefinitions + = " " + generateMethodIfExists ( child - > getDataRef ( ) - > valueType , " copy_construct " ,
2016-01-05 21:40:00 -05:00
" ©_constructTemporary, &in-> " + prefixed_option_name , itemTypeVector ) + " ; \n " ;
2015-11-25 15:35:06 -05:00
}
2016-01-05 21:40:00 -05:00
std : : string otherValue = ( is_reference ? " & " : " " ) + ( need_temporary ? " copy_constructTemporary " : " in-> " + prefixed_option_name ) ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " equal = " + generateMethodIfExists ( child - > getDataRef ( ) - > valueType , " operator== " ,
2016-01-05 21:40:00 -05:00
" &this-> " + prefixed_option_name + " , " + otherValue ,
2015-11-25 15:35:06 -05:00
std : : vector < Type > { * child - > getDataRef ( ) - > valueType } ) + " ; \n " ;
// Remember, we don't destruct copy_constructTemporary because the function will do that
functionDefinitions + = " } \n " ;
2015-11-19 16:27:36 -05:00
} else {
2016-01-22 23:59:59 -05:00
// if we're an object type but don't define an equality function (or, as is a current bug, that function is a template)
// we just say always false/unequal
if ( child - > getDataRef ( ) - > valueType - > typeDefinition )
functionDefinitions + = " equal = false; \n } \n " ;
else
functionDefinitions + = " equal = this-> " + prefixed_option_name + " == in-> " + prefixed_option_name + " ; \n } \n " ;
2015-11-19 16:27:36 -05:00
}
}
}
2015-11-25 15:35:06 -05:00
functionDefinitions + = " return equal; \n " ;
2015-11-19 16:27:36 -05:00
} else if ( orig_fun_name = = " operator!= " ) {
functionDefinitions + = " /* inequality woop woop */ \n " ;
2015-11-21 15:28:57 -05:00
std : : string adtName = declarationData . symbol . getName ( ) ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " bool equal = !fun_ " + adtName + " __ " + CifyName ( " operator== " ) + " _ " + adtName + " _space__div__star_ref_star__div__space__star_(this, in); \n " ;
functionDefinitions + = " return equal; \n " ;
} else if ( orig_fun_name = = " operator= " ) {
functionDefinitions + = " /* wopo assignment */ \n " ;
auto adtType = declaration - > getDataRef ( ) - > valueType ;
functionDefinitions + = " " + generateMethodIfExists ( adtType , " destruct " ,
" this " , std : : vector < Type > ( ) ) + " ; \n " ;
functionDefinitions + = " " + generateMethodIfExists ( adtType , " copy_construct " ,
" this, in " , std : : vector < Type > { adtType - > withIncreasedIndirection ( ) } ) + " ; \n " ;
2015-11-21 15:28:57 -05:00
} else if ( orig_fun_name = = " copy_construct " ) {
functionDefinitions + = " /* copy_construct woop woop */ \n " ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " this->flag = in->flag; \n " ;
std : : string elsePrefix = " " ;
for ( auto child : decChildren ) {
if ( child - > getName ( ) ! = " function " & & child - > getDataRef ( ) - > valueType - > typeDefinition ! = declaration ) {
std : : string option_name = child - > getDataRef ( ) - > symbol . getName ( ) ;
2016-01-05 21:40:00 -05:00
std : : string prefixed_option_name = prefixIfNeeded ( scopePrefix ( declaration ) , option_name ) ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + elsePrefix + " if (in->flag == " + declarationData . symbol . getName ( ) + " __ " + option_name + " ) { \n " ;
elsePrefix = " else " ;
NodeTree < ASTData > * method = nullptr ;
auto itemTypeVector = std : : vector < Type > { child - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ;
2016-01-15 19:10:52 -05:00
if ( ( method = getMethod ( child - > getDataRef ( ) - > valueType , " copy_construct " , itemTypeVector ) ) ) {
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + generateMethodIfExists ( child - > getDataRef ( ) - > valueType , " copy_construct " ,
2016-01-05 21:40:00 -05:00
" &this-> " + prefixed_option_name + " , &in-> " + prefixed_option_name , itemTypeVector ) + " ; \n " ;
2015-11-25 15:35:06 -05:00
} else {
2016-01-05 21:40:00 -05:00
functionDefinitions + = " this-> " + prefixed_option_name + " = in-> " + prefixed_option_name + " ; \n " ;
2015-11-25 15:35:06 -05:00
}
functionDefinitions + = " } \n " ;
}
}
2015-11-21 15:28:57 -05:00
} else if ( orig_fun_name = = " destruct " ) {
functionDefinitions + = " /* destruct woop woop */ \n " ;
2015-11-25 15:35:06 -05:00
std : : string elsePrefix = " " ;
for ( auto child : decChildren ) {
if ( child - > getName ( ) ! = " function " & & child - > getDataRef ( ) - > valueType - > typeDefinition ! = declaration ) {
std : : string option_name = child - > getDataRef ( ) - > symbol . getName ( ) ;
2016-01-21 03:18:02 -05:00
std : : string prefixed_option_name = prefixIfNeeded ( scopePrefix ( child ) , option_name ) ;
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + elsePrefix + " if (this->flag == " + declarationData . symbol . getName ( ) + " __ " + option_name + " ) { \n " ;
elsePrefix = " else " ;
NodeTree < ASTData > * method = nullptr ;
2016-01-15 19:10:52 -05:00
if ( ( method = getMethod ( child - > getDataRef ( ) - > valueType , " destruct " , std : : vector < Type > ( ) ) ) ) {
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + generateMethodIfExists ( child - > getDataRef ( ) - > valueType , " destruct " ,
2016-01-21 03:18:02 -05:00
" &this-> " + prefixed_option_name , std : : vector < Type > ( ) ) + " ; \n " ;
//"&this->" + option_name, std::vector<Type>()) + ";\n";
2015-11-25 15:35:06 -05:00
}
functionDefinitions + = " } \n " ;
}
}
2015-11-19 16:27:36 -05:00
} else {
// ok, is a constructor function
functionDefinitions + = " /* constructor woop woop */ \n " ;
functionDefinitions + = " " + declarationData . symbol . getName ( ) + " toRet; \n " ;
functionDefinitions + = " toRet.flag = " + declarationData . symbol . getName ( ) + " __ " + orig_fun_name + " ; \n " ;
2015-11-25 15:35:06 -05:00
if ( has_param ) {
NodeTree < ASTData > * method = nullptr ;
auto paramType = child - > getDataRef ( ) - > valueType - > parameterTypes [ 0 ] ;
auto itemTypeVector = std : : vector < Type > { paramType - > withIncreasedIndirection ( ) } ;
functionDefinitions + = " /* " + ValueTypeToCType ( paramType , " " ) + " */ \n " ;
2016-01-15 19:10:52 -05:00
if ( ( method = getMethod ( paramType , " copy_construct " , itemTypeVector ) ) ) {
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + generateMethodIfExists ( paramType , " copy_construct " ,
2016-01-05 21:40:00 -05:00
" &toRet. " + prefixIfNeeded ( scopePrefix ( declaration ) , orig_fun_name ) + " , &in " , itemTypeVector ) + " ; \n " ;
2015-11-25 15:35:06 -05:00
} else {
2016-01-05 21:40:00 -05:00
functionDefinitions + = " toRet. " + prefixIfNeeded ( scopePrefix ( declaration ) , orig_fun_name ) + " = in; \n " ;
2015-11-25 15:35:06 -05:00
}
2016-01-15 19:10:52 -05:00
if ( ( method = getMethod ( paramType , " destruct " , std : : vector < Type > ( ) ) ) ) {
2015-11-25 15:35:06 -05:00
functionDefinitions + = " " + generateMethodIfExists ( paramType , " destruct " ,
" &in " , std : : vector < Type > ( ) ) + " ; \n " ;
} }
2015-11-19 16:27:36 -05:00
functionDefinitions + = " return toRet; \n " ;
}
functionDefinitions + = " } \n " ;
}
}
2015-11-09 13:26:02 -05:00
break ;
}
2015-03-11 01:58:10 -04:00
default :
//std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl;
cOutput + = " /*unknown declaration named " + declaration - > getName ( ) + " */ \n " ;
hOutput + = " /*unknown declaration named " + declaration - > getName ( ) + " */ \n " ;
}
2014-12-30 01:22:09 -05:00
}
}
}
2015-07-04 18:55:15 -04:00
hOutput + = plainTypedefs + importIncludes + topLevelCPassthrough + functionTypedefStringPre + variableExternDeclarations + classStructs + functionTypedefString + functionPrototypes ;
2014-12-30 01:22:09 -05:00
cOutput + = variableDeclarations + functionDefinitions ;
return std : : make_pair ( hOutput , cOutput ) ;
}
//The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in
2015-06-25 04:09:19 -04:00
CCodeTriple CGenerator : : generate ( NodeTree < ASTData > * from , NodeTree < ASTData > * enclosingObject , bool justFuncName , NodeTree < ASTData > * enclosingFunction ) {
2015-11-09 13:26:02 -05:00
ASTData data = from - > getData ( ) ;
std : : vector < NodeTree < ASTData > * > children = from - > getChildren ( ) ;
2015-05-30 04:43:01 -04:00
//std::string output;
CCodeTriple output ;
2015-11-09 13:26:02 -05:00
switch ( data . type ) {
case translation_unit :
{
// Should not happen! We do this in it's own function now!
std : : cerr < < " Trying to normal generate a translation unit! That's a nono! ( " < < from - > getDataRef ( ) - > toString ( ) < < " ) " < < std : : endl ;
throw " That's not gonna work " ;
}
break ;
case import :
2015-05-30 04:43:01 -04:00
return CCodeTriple ( " /* never reached import? */ \n " ) ;
2015-11-09 13:26:02 -05:00
case identifier :
{
std : : string preName = " " ;
std : : string postName = " " ;
bool closed = false ;
// check for this being a closed over variable
// first, get declaring function, if it exists
if ( enclosingFunction ) {
if ( enclosingFunction - > getDataRef ( ) - > closedVariables . size ( ) ) {
2015-11-13 15:49:00 -05:00
//std::cout << "WHOH IS A CLOSER" << std::endl;
2015-11-09 13:26:02 -05:00
if ( enclosingFunction - > getDataRef ( ) - > closedVariables . find ( from ) ! = enclosingFunction - > getDataRef ( ) - > closedVariables . end ( ) ) {
preName + = " (*closed_variables-> " ;
postName + = " ) " ;
closed = true ;
}
2015-06-26 13:51:57 -04:00
}
2015-06-25 04:09:19 -04:00
}
2015-11-09 13:26:02 -05:00
// enclosing function comes first now, we might have a double closure that both close over the this pointer of an object
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
if ( data . symbol . getName ( ) = = " this " ) {
if ( enclosingObject | | enclosingFunction )
return CCodeTriple ( preName + " this " + postName ) ;
std : : cerr < < " Error: this used in non-object scope " < < std : : endl ;
throw " Error: this used in non-object scope " ;
}
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
2016-02-09 02:59:38 -05:00
//if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
// the old one would actually activate if the object even had one of the same name
if ( enclosingObject ) {
auto containing = enclosingObject - > getDataRef ( ) - > scope . find ( data . symbol . getName ( ) ) ;
if ( containing ! = enclosingObject - > getDataRef ( ) - > scope . end ( ) & & std : : find ( containing - > second . begin ( ) , containing - > second . end ( ) , from ) ! = containing - > second . end ( ) )
preName = " ( " + preName + " this)-> " ; // incase this is a closed over this that is referencing another thing (I think this happens for a.b when a is supposed to be closed over but isn't)
}
2015-11-09 13:26:02 -05:00
// dereference references, but only if inside a function and not if this is a closed over variable
if ( enclosingFunction & & data . valueType - > is_reference & & ! closed ) {
preName + = " (* " ;
postName + = " ) " ;
}
// we're scope prefixing EVERYTHING, but only if needed
return preName + prefixIfNeeded ( scopePrefix ( from ) , CifyName ( data . symbol . getName ( ) ) ) + postName ; //Cifying does nothing if not an operator overload
2015-06-25 04:09:19 -04:00
}
2015-11-09 13:26:02 -05:00
case function :
{
if ( data . valueType - > baseType = = template_type )
return " /* template function: " + data . symbol . getName ( ) + " */ " ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
// we push on a new vector to hold parameters that might need a destructor call
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
std : : string nameDecoration , parameters ;
if ( data . closedVariables . size ( ) )
parameters + = closureStructType ( data . closedVariables ) + " *closed_variables " ;
for ( int j = 0 ; j < children . size ( ) - 1 ; j + + ) {
if ( j > 0 | | data . closedVariables . size ( ) )
parameters + = " , " ;
parameters + = ValueTypeToCType ( children [ j ] - > getData ( ) . valueType , generate ( children [ j ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ) ;
2015-11-21 15:28:57 -05:00
//nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
2015-11-09 13:26:02 -05:00
// add parameters to distructDoubleStack so that their destructors will be called at return (if they exist)
distructDoubleStack . back ( ) . push_back ( children [ j ] ) ;
}
2015-11-21 15:28:57 -05:00
for ( Type * paramType : from - > getDataRef ( ) - > valueType - > parameterTypes )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( paramType ) ;
2015-11-09 13:26:02 -05:00
// this is for using functions as values
if ( justFuncName ) {
std : : string funcName ;
2015-11-19 16:27:36 -05:00
if ( data . symbol . getName ( ) ! = " main " ) {
2015-11-09 13:26:02 -05:00
funcName + = function_header + prefixIfNeeded ( scopePrefix ( from ) , CifyName ( data . symbol . getName ( ) + nameDecoration ) ) ;
2015-11-19 16:27:36 -05:00
} else {
2015-11-09 13:26:02 -05:00
funcName + = CifyName ( data . symbol . getName ( ) + nameDecoration ) ;
2015-11-19 16:27:36 -05:00
}
2015-11-09 13:26:02 -05:00
if ( from - > getDataRef ( ) - > closedVariables . size ( ) ) {
std : : string tmpStruct = " closureStruct " + getID ( ) ;
output . preValue + = closureStructType ( data . closedVariables ) + " " + tmpStruct + " = { " ;
bool notFirst = false ;
for ( auto var : data . closedVariables ) {
if ( notFirst )
output . preValue + = " , " ;
notFirst = true ;
std : : string varName = var - > getDataRef ( ) - > symbol . getName ( ) ;
std : : string preName ;
if ( enclosingObject & & enclosingObject - > getDataRef ( ) - > scope . find ( varName ) ! = enclosingObject - > getDataRef ( ) - > scope . end ( ) )
preName + = " this-> " ;
varName = ( varName = = " this " ) ? varName : prefixIfNeeded ( scopePrefix ( var ) , varName ) ;
// so that we can close over things that have been closed over by an enclosing closure
output . preValue + = " . " + varName + " = &/*woo*/ " + generate ( var , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " /*woo*/ " ;
//output.preValue += "." + varName + " = &" + preName + varName;
}
output . preValue + = " }; \n " ;
output + = " ( " + ValueTypeToCType ( data . valueType , " " ) + " ){(void*) " + funcName + " , & " + tmpStruct + " } " ;
} else {
output + = " ( " + ValueTypeToCType ( data . valueType , " " ) + " ){ " + funcName + " , NULL} " ;
2015-06-26 13:29:37 -04:00
}
2015-06-25 04:09:19 -04:00
} else {
2015-11-09 13:26:02 -05:00
// Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock
std : : string funName = ( data . symbol . getName ( ) = = " main " ) ? " main " : function_header + prefixIfNeeded ( scopePrefix ( from ) , CifyName ( data . symbol . getName ( ) + nameDecoration ) ) ;
output = " \n " + ValueTypeToCType ( data . valueType - > returnType , funName ) + " ( " + parameters + " ) { \n " +
generate ( children [ children . size ( ) - 1 ] , enclosingObject , justFuncName , from ) . oneString ( ) ;
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = " } \n " ;
2015-06-25 04:09:19 -04:00
}
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
distructDoubleStack . pop_back ( ) ;
return output ;
}
case code_block :
{
output + = " { \n " ;
tabLevel + + ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
// we push on a new vector to hold parameters that might need a destructor call
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
// we push on a new vector to hold deferred statements
deferDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
for ( int i = 0 ; i < children . size ( ) ; i + + )
output + = generate ( children [ i ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
// we pop off the vector and go through them in reverse emitting them
for ( auto iter = deferDoubleStack . back ( ) . rbegin ( ) ; iter ! = deferDoubleStack . back ( ) . rend ( ) ; iter + + )
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
deferDoubleStack . pop_back ( ) ;
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
distructDoubleStack . pop_back ( ) ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
tabLevel - - ;
output + = tabs ( ) + " } " ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
return output ;
}
2014-06-28 08:31:33 -07:00
case expression :
2015-11-09 13:26:02 -05:00
output + = " " + data . symbol . getName ( ) + " , " ;
case boolean_expression :
output + = " " + data . symbol . getName ( ) + " " ;
case statement :
2015-05-30 04:43:01 -04:00
{
2015-11-09 13:26:02 -05:00
CCodeTriple stat = generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) ;
return tabs ( ) + stat . preValue + stat . value + " ; \ n " + stat.postValue ;
2015-05-30 04:43:01 -04:00
}
2015-11-09 13:26:02 -05:00
case if_statement :
output + = " if ( " + generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) + " ) \n \t " ;
2015-03-16 05:59:56 -04:00
// We have to see if the then statement is a regular single statement or a block.
// If it's a block, because it's also a statement a semicolon will be emitted even though
// we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is.
if ( children [ 1 ] - > getChildren ( ) [ 0 ] - > getDataRef ( ) - > type = = code_block ) {
2015-06-25 04:09:19 -04:00
output + = generate ( children [ 1 ] - > getChildren ( ) [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-03-16 05:59:56 -04:00
} else {
2015-05-15 15:19:55 -04:00
// ALSO we always emit blocks now, to handle cases like defer when several statements need to be
// run in C even though it is a single Kraken statement
2015-06-25 04:09:19 -04:00
output + = " { " + generate ( children [ 1 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " } " ;
2015-03-16 05:59:56 -04:00
}
2015-05-15 15:19:55 -04:00
// Always emit blocks here too
2015-11-09 13:26:02 -05:00
if ( children . size ( ) > 2 )
output + = " else { " + generate ( children [ 2 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " } " ;
return output ;
2015-11-14 19:05:28 -05:00
case match_statement :
{
output + = " /* match_statement */ \n " ;
CCodeTriple thingToMatch = generate ( children [ 0 ] , enclosingObject , false , enclosingFunction ) ;
output . preValue + = thingToMatch . preValue ;
output . postValue + = thingToMatch . postValue ;
for ( auto case_stmt : slice ( children , 1 , - 1 ) ) {
auto case_children = case_stmt - > getChildren ( ) ;
2016-01-06 02:46:42 -05:00
// was accidntally adding in prefix when it shouldn't, though maybe it should when both option and ADT name are identical, deal with this later
//std::string option = generate(case_children[0], enclosingObject, false, enclosingFunction).oneString();
std : : string option = case_children [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ;
2016-01-21 03:18:02 -05:00
std : : string prefixed_option = prefixIfNeeded ( scopePrefix ( case_children [ 0 ] ) , option ) ;
2015-11-19 16:27:36 -05:00
std : : string parentName = case_children [ 0 ] - > getDataRef ( ) - > scope [ " ~enclosing_scope " ] [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ;
2015-11-14 19:05:28 -05:00
output + = " /* case " + option + " if " + thingToMatch . value + " */ \n " ;
2015-12-06 15:15:33 -05:00
output + = tabs ( ) + " if (( " + thingToMatch . value + " ).flag == " + parentName + " __ " + option + " ) { \n " ;
2015-11-14 19:05:28 -05:00
tabLevel + + ;
if ( case_children . size ( ) > 2 ) {
output + = tabs ( ) + ValueTypeToCType ( case_children [ 1 ] - > getData ( ) . valueType , generate ( case_children [ 1 ] , enclosingObject , false , enclosingFunction ) . oneString ( ) )
2016-01-21 03:18:02 -05:00
+ " = ( " + thingToMatch . value + " ). " + prefixed_option + " ; \n " ;
//+ " = (" + thingToMatch.value + ")." + option + ";\n";
2015-11-14 19:05:28 -05:00
output + = generate ( case_children [ 2 ] , enclosingObject , false , enclosingFunction ) . oneString ( ) ;
} else {
output + = generate ( case_children [ 1 ] , enclosingObject , false , enclosingFunction ) . oneString ( ) ;
}
tabLevel - - ;
output + = " } \n " ;
}
return output ;
}
break ;
case case_statement :
output + = " /* case_statement */ " ;
throw " case statement isn't actually used, but is generated in match " ;
break ;
2015-11-09 13:26:02 -05:00
case while_loop :
2015-06-28 14:27:48 -04:00
{
2015-11-09 13:26:02 -05:00
// we push on a new vector to hold while stuff that might need a destructor call
loopDistructStackDepth . push ( distructDoubleStack . size ( ) ) ;
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
// keep track of the current size of the deferDoubleStack so that statements that
// break or continue inside this loop can correctly emit all of the defers through
// all of the inbetween scopes
loopDeferStackDepth . push ( deferDoubleStack . size ( ) ) ;
// gotta do like this so that the preconditions can happen every loop
output + = " while (1) { \n " ;
CCodeTriple condtition = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) ;
output + = condtition . preValue ;
output + = " if (!( " + condtition . value + " )) break; \n " ;
output + = condtition . postValue ;
output + = generate ( children [ 1 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = + " } " ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
distructDoubleStack . pop_back ( ) ;
loopDistructStackDepth . pop ( ) ;
// and pop it off again
loopDeferStackDepth . pop ( ) ;
return output ;
2015-06-28 14:27:48 -04:00
}
2015-11-09 13:26:02 -05:00
case for_loop :
2015-06-28 20:25:27 -04:00
{
2015-11-09 13:26:02 -05:00
// we push on a new vector to hold for stuff that might need a destructor call
loopDistructStackDepth . push ( distructDoubleStack . size ( ) ) ;
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
// keep track of the current size of the deferDoubleStack so that statements that
// break or continue inside this loop can correctly emit all of the defers through
// all of the inbetween scopes
loopDeferStackDepth . push ( deferDoubleStack . size ( ) ) ;
//The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s)
2015-06-28 20:25:27 -04:00
2015-11-09 13:26:02 -05:00
std : : string doUpdateName = " do_update " + getID ( ) ;
// INITIALIZER
output + = " { " ;
output + = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) ;
output + = " bool " + doUpdateName + " = false; \n " ;
output + = " for (;;) { " ;
// UPDATE
output + = " if ( " + doUpdateName + " ) { " ;
output + = generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) ;
output + = " } \n " ;
output + = doUpdateName + " = true; \n " ;
// CONDITION
// note that the postValue happens whether or not we break
CCodeTriple condition = generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) ;
output + = condition . preValue ;
output + = " if (!( " + condition . value + " )) { \n " ;
output + = condition . postValue ;
output + = " break; \n } " ;
output + = condition . postValue ;
// BODY
output + = generate ( children [ 3 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = " } " ;
output + = " } " ;
distructDoubleStack . pop_back ( ) ;
loopDistructStackDepth . pop ( ) ;
// and pop it off again
loopDeferStackDepth . pop ( ) ;
return output ;
2015-06-28 20:25:27 -04:00
}
2015-11-09 13:26:02 -05:00
case return_statement :
2015-05-30 04:43:01 -04:00
{
2015-11-09 13:26:02 -05:00
// we pop off the vector and go through them in reverse emitting them, going
// through all of both arrays, as return will go through all scopes
for ( auto topItr = deferDoubleStack . rbegin ( ) ; topItr ! = deferDoubleStack . rend ( ) ; topItr + + )
for ( auto iter = ( * topItr ) . rbegin ( ) ; iter ! = ( * topItr ) . rend ( ) ; iter + + )
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
2015-11-09 13:26:02 -05:00
std : : string destructors = emitDestructors ( reverse ( flatten ( distructDoubleStack ) ) , enclosingObject ) ;
if ( children . size ( ) ) {
CCodeTriple expr = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) ;
output . preValue + = expr . preValue ;
std : : string retTemp = " ret_temp " + getID ( ) ;
// use the function's return value so we do the right thing with references
output . preValue + = ValueTypeToCType ( enclosingFunction - > getDataRef ( ) - > valueType - > returnType , retTemp ) + " ; \n " ;
if ( enclosingFunction - > getDataRef ( ) - > valueType - > returnType - > is_reference )
output . preValue + = retTemp + " = & " + expr . value + " ; \n " ;
else if ( methodExists ( children [ 0 ] - > getDataRef ( ) - > valueType , " copy_construct " , std : : vector < Type > { children [ 0 ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) )
output . preValue + = generateMethodIfExists ( children [ 0 ] - > getDataRef ( ) - > valueType , " copy_construct " , " & " + retTemp + " , & " + expr . value , std : : vector < Type > { children [ 0 ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) ;
else
output . preValue + = retTemp + " = " + expr . value + " ; \n " ;
// move expr post to before return
output . value + = expr . postValue ;
output . value + = destructors ;
output . value + = " return " + retTemp ;
} else {
output . value + = destructors ;
output + = " return " ;
}
return output ;
2015-05-30 04:43:01 -04:00
}
2015-11-09 13:26:02 -05:00
case break_statement :
2015-05-15 15:19:55 -04:00
// handle everything that's been deferred all the way back to the loop's scope
for ( int i = deferDoubleStack . size ( ) - 1 ; i > = loopDeferStackDepth . top ( ) ; i - - )
for ( auto iter = deferDoubleStack [ i ] . rbegin ( ) ; iter ! = deferDoubleStack [ i ] . rend ( ) ; iter + + )
2015-06-25 04:09:19 -04:00
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
// ok, emit destructors to where the loop ends
output + = emitDestructors ( reverse ( flatten ( slice ( distructDoubleStack , loopDistructStackDepth . top ( ) , - 1 ) ) ) , enclosingObject ) ;
2015-05-15 15:19:55 -04:00
return output + " break " ;
2015-11-09 13:26:02 -05:00
case continue_statement :
2015-05-15 15:19:55 -04:00
// handle everything that's been deferred all the way back to the loop's scope
for ( int i = deferDoubleStack . size ( ) - 1 ; i > = loopDeferStackDepth . top ( ) ; i - - )
for ( auto iter = deferDoubleStack [ i ] . rbegin ( ) ; iter ! = deferDoubleStack [ i ] . rend ( ) ; iter + + )
2015-06-25 04:09:19 -04:00
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
// ok, emit destructors to where the loop ends
output + = emitDestructors ( reverse ( flatten ( slice ( distructDoubleStack , loopDistructStackDepth . top ( ) , - 1 ) ) ) , enclosingObject ) ;
2015-05-15 15:19:55 -04:00
return output + " continue " ;
2015-11-09 13:26:02 -05:00
case defer_statement :
2015-05-15 15:19:55 -04:00
deferDoubleStack . back ( ) . push_back ( children [ 0 ] ) ;
2015-06-25 04:09:19 -04:00
return CCodeTriple ( " /*defer " + generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " */ " ) ;
2015-11-09 13:26:02 -05:00
case assignment_statement :
return generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " = " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) ;
case declaration_statement :
2015-05-30 04:43:01 -04:00
// adding declaration to the distructDoubleStack so that we can call their destructors when leaving scope (}, return, break, continue)
// but only if we're inside an actual doublestack
if ( ( distructDoubleStack . size ( ) ) )
distructDoubleStack . back ( ) . push_back ( children [ 0 ] ) ;
2015-11-09 13:26:02 -05:00
if ( children . size ( ) = = 1 )
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType , generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ) + " ; " ;
else if ( children [ 1 ] - > getChildren ( ) . size ( ) & & children [ 1 ] - > getChildren ( ) [ 0 ] - > getChildren ( ) . size ( ) > 1
& & children [ 1 ] - > getChildren ( ) [ 0 ] - > getChildren ( ) [ 1 ] = = children [ 0 ] ) {
2014-06-26 01:45:44 -07:00
//That is, if we're a declaration with an init position call (Object a.construct())
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
2015-06-01 01:43:23 -04:00
// be sure to end value by passing oneString true
2015-06-25 04:09:19 -04:00
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType , generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ) + " ; " + generate(children[1], enclosingObject, true, enclosingFunction).oneString(true) + " /*Init Position Call*/ " ;
2015-05-30 04:43:01 -04:00
} else {
2015-06-07 19:54:08 -04:00
// copy constructor if exists (even for non same types)
if ( methodExists ( children [ 0 ] - > getDataRef ( ) - > valueType , " copy_construct " , std : : vector < Type > { children [ 1 ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) ) {
2015-06-25 04:09:19 -04:00
CCodeTriple toAssign = generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) ;
std : : string assignedTo = generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
output . value = toAssign . preValue ;
output . value + = ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType , assignedTo ) + " ; \n " ;
2015-06-07 19:54:08 -04:00
// we put the thing about to be copy constructed in a variable so we can for sure take its address
std : : string toAssignTemp = " copy_construct_param " + getID ( ) ;
2015-07-15 13:56:57 -04:00
output . value + = ValueTypeToCType ( children [ 1 ] - > getData ( ) . valueType - > withoutReference ( ) , toAssignTemp ) + " = " + toAssign . value + " ; \n " ;
2015-06-07 19:54:08 -04:00
output . value + = generateMethodIfExists ( children [ 0 ] - > getDataRef ( ) - > valueType , " copy_construct " , " & " + assignedTo + " , & " + toAssignTemp , std : : vector < Type > { children [ 1 ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) + " ; \n " + output . postValue ;
2015-05-30 04:43:01 -04:00
output . value + = toAssign . postValue ;
return output ;
} else {
2015-07-07 00:46:00 -04:00
// we might use this address in the right hand side (recursive closures), so split it up
std : : string assignTo = generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
output . preValue = ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType , assignTo ) + " ; \n " ;
output + = assignTo + " = " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ; " ;
return output ;
2015-05-30 04:43:01 -04:00
}
}
2015-11-09 13:26:02 -05:00
case if_comp :
2015-04-04 01:32:40 -04:00
// Lol, this doesn't work because the string gets prefixed now
2015-11-09 13:26:02 -05:00
//if (generate(children[0], enclosingObject, enclosingFunction) == generatorString)
if ( children [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) = = generatorString )
return generate ( children [ 1 ] , enclosingObject , justFuncName , enclosingFunction ) ;
return CCodeTriple ( " " ) ;
case simple_passthrough :
2015-04-10 00:37:31 -04:00
{
2015-11-06 03:23:55 -05:00
std : : string pre_end_dec , end_assign ;
2015-04-10 00:37:31 -04:00
// Stuff is bit more interesting now! XXX
std : : string pre_passthrough , post_passthrough ;
// Handle input/output parameters
if ( children . front ( ) - > getDataRef ( ) - > type = = passthrough_params ) {
auto optParamAssignLists = children . front ( ) - > getChildren ( ) ;
for ( auto in_or_out : optParamAssignLists ) {
for ( auto assign : in_or_out - > getChildren ( ) ) {
auto assignChildren = assign - > getChildren ( ) ;
2015-11-06 03:23:55 -05:00
if ( in_or_out - > getDataRef ( ) - > type = = in_passthrough_params ) {
std : : string currentName = generate ( assignChildren [ 0 ] , enclosingObject , enclosingFunction ) . oneString ( ) ;
std : : string toName ;
2015-06-19 13:28:02 -04:00
if ( assignChildren . size ( ) = = 2 )
2015-11-06 03:23:55 -05:00
toName = assignChildren [ 1 ] - > getDataRef ( ) - > symbol . getName ( ) ;
2015-06-19 13:28:02 -04:00
else
2015-11-06 03:23:55 -05:00
toName = assignChildren [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ;
if ( currentName ! = toName )
pre_passthrough + = ValueTypeToCType ( assignChildren [ 0 ] - > getDataRef ( ) - > valueType , toName ) + " = " + currentName + " ; \n " ;
} else if ( in_or_out - > getDataRef ( ) - > type = = out_passthrough_params ) {
std : : string currentName = generate ( assignChildren [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
std : : string toName ;
2015-06-19 13:28:02 -04:00
if ( assignChildren . size ( ) = = 2 )
2015-11-06 03:23:55 -05:00
toName = assignChildren [ 1 ] - > getDataRef ( ) - > symbol . getName ( ) ;
2015-06-19 13:28:02 -04:00
else
2015-11-06 03:23:55 -05:00
toName + = assignChildren [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ;
std : : string trans_dec_name = currentName + " _end_assign " ;
pre_end_dec + = ValueTypeToCType ( assignChildren [ 0 ] - > getDataRef ( ) - > valueType , trans_dec_name ) + " ; \n " ;
post_passthrough + = trans_dec_name + " = " + toName + " ; \n " ;
end_assign + = currentName + " = " + trans_dec_name + " ; \n " ;
} else
2015-06-25 04:09:19 -04:00
linkerString + = " " + strSlice ( generate ( in_or_out , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) , 1 , - 2 ) + " " ;
2015-04-10 00:37:31 -04:00
}
}
}
// The actual passthrough string is the last child now, as we might
// have passthrough_params be the first child
2015-06-19 12:06:27 -04:00
// we don't generate, as that will escape the returns and we don't want that. We'll just grab the string
2015-11-06 03:23:55 -05:00
// we don't want the scope stuff if we're at top level for an include, etc....
if ( isUnderNodeWithType ( from , function ) )
return pre_end_dec + " { " + pre_passthrough + strSlice ( children . back ( ) - > getDataRef ( ) - > symbol . getName ( ) , 3 , - 4 ) + post_passthrough + " } \n " + end_assign ;
else
return strSlice ( children . back ( ) - > getDataRef ( ) - > symbol . getName ( ) , 3 , - 4 ) ;
2015-04-10 00:37:31 -04:00
}
2015-11-09 13:26:02 -05:00
case function_call :
{
//NOTE: The first (0th) child of a function call node is the declaration of the function
2013-12-27 13:05:07 -06:00
2015-11-09 13:26:02 -05:00
//Handle operators specially for now. Will later replace with
//Inlined functions in the standard library
// std::string name = data.symbol.getName();
// std::cout << name << " == " << children[0]->getData().symbol.getName() << std::endl;
std : : string name = children [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ;
ASTType funcType = children [ 0 ] - > getDataRef ( ) - > type ;
2015-06-25 04:09:19 -04:00
2015-11-09 13:26:02 -05:00
// UGLLLLYYYY
// But we have these here because some stuff has to be moved out of the giant nested blocks below and this is the way to do it
CCodeTriple functionCallSource ;
bool doClosureInstead = false ;
2015-06-25 04:09:19 -04:00
2015-11-09 13:26:02 -05:00
//std::cout << "Doing function: " << name << std::endl;
//Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer
if ( funcType = = function ) {
if ( name = = " ++ " | | name = = " -- " )
return generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + name ;
if ( ( name = = " * " | | name = = " & " | | name = = " ! " | | name = = " - " | | name = = " + " ) & & children . size ( ) = = 2 ) //Is dereference, not multiplication, address-of, or other unary operator
return name + " ( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " ;
if ( name = = " [] " )
return " ( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " )[ " + generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) + " ] " ;
if ( name = = " + " | | name = = " - " | | name = = " * " | | name = = " / " | | name = = " == " | | name = = " >= " | | name = = " <= " | | name = = " != "
| | name = = " < " | | name = = " > " | | name = = " % " | | name = = " = " | | name = = " += " | | name = = " -= " | | name = = " *= " | | name = = " /= " ) {
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + " ( " + generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) + " )) " ;
} else if ( name = = " && " | | name = = " || " ) {
// b/c short circuiting, these have to be done seperately
CCodeTriple lhs = generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) ;
CCodeTriple rhs = generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) ;
output . preValue = lhs . preValue ;
std : : string shortcircuit_result = " shortcircuit_result " + getID ( ) ;
output . preValue + = " bool " + shortcircuit_result + " = " + lhs . value + " ; \n " ;
output . preValue + = lhs . postValue ;
output . preValue + = " if ( " + std : : string ( name = = " || " ? " ! " : " " ) + shortcircuit_result + " ) { \n " ;
output . preValue + = rhs . preValue ;
output . preValue + = shortcircuit_result + " = " + rhs . value + " ; \n " ;
output . preValue + = rhs . postValue ;
output . preValue + = " } \n " ;
output . value = shortcircuit_result ;
return output ;
} else if ( name = = " . " | | name = = " -> " ) {
if ( children . size ( ) = = 1 )
return " /*dot operation with one child*/ " + generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) + " /*end one child*/ " ;
//If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method
if ( children [ 2 ] - > getDataRef ( ) - > type = = function ) {
std : : string functionName = children [ 2 ] - > getDataRef ( ) - > symbol . getName ( ) ;
NodeTree < ASTData > * possibleObjectType = children [ 1 ] - > getDataRef ( ) - > valueType - > typeDefinition ;
//If is an object method, generate it like one. Needs extension/modification for inheritence
if ( possibleObjectType ) {
NodeTree < ASTData > * unaliasedTypeDef = getMethodsObjectType ( possibleObjectType , functionName ) ;
if ( unaliasedTypeDef ) { //Test to see if the function's a member of this type_def, or if this is an alias, of the original type. Get this original type if it exists.
std : : string nameDecoration ;
2015-11-21 15:28:57 -05:00
NodeTree < ASTData > * functionDef = children [ 2 ] ; //The function def is the rhs of the access operation
//std::vector<NodeTree<ASTData>*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation
2015-11-09 13:26:02 -05:00
//std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
2015-11-21 15:28:57 -05:00
for ( Type * paramType : functionDef - > getDataRef ( ) - > valueType - > parameterTypes )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( paramType ) ;
//for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
//nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
2015-11-09 13:26:02 -05:00
// Note that we only add scoping to the object, as this specifies our member function too
2015-11-25 15:35:06 -05:00
return function_header + prefixIfNeeded ( scopePrefix ( unaliasedTypeDef ) , CifyName ( unaliasedTypeDef - > getDataRef ( ) - > symbol . getName ( ) ) ) + " __ " +
2015-06-25 04:09:19 -04:00
CifyName ( functionName + nameDecoration ) + " ( " + ( name = = " . " ? " & " : " " ) + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " , " ;
2015-11-09 13:26:02 -05:00
//The comma lets the upper function call know we already started the param list
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
} else {
//std::cout << "Is not in scope or not type" << std::endl;
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + functionName + " ) " ;
}
2014-06-10 23:59:39 -07:00
} else {
2015-11-09 13:26:02 -05:00
//std::cout << "Is not in scope or not type" << std::endl;
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + functionName + " ) " ;
2014-06-10 23:59:39 -07:00
}
} else {
2015-11-09 13:26:02 -05:00
//return "((" + generate(children[1], enclosingObject, enclosingFunction) + ")" + name + generate(children[2], enclosingObject, enclosingFunction) + ")";
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + generate ( children [ 2 ] , nullptr , true , enclosingFunction ) + " ) " ;
}
2015-07-05 02:34:45 -04:00
} else {
2015-11-09 13:26:02 -05:00
// this could a closure literal. sigh, I know.
if ( children [ 0 ] - > getDataRef ( ) - > closedVariables . size ( ) ) {
functionCallSource = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) ;
doClosureInstead = true ;
} else {
//It's a normal function call, not a special one or a method or anything. Name decorate.
std : : vector < NodeTree < ASTData > * > functionDefChildren = children [ 0 ] - > getChildren ( ) ;
//std::cout << "Decorating (none-special)" << name << " " << functionDefChildren.size() << std::endl;
std : : string nameDecoration ;
2015-11-21 15:28:57 -05:00
for ( Type * paramType : children [ 0 ] - > getDataRef ( ) - > valueType - > parameterTypes )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( paramType ) ;
//for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
//nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
2015-11-09 13:26:02 -05:00
// it is possible that this is an object method from inside a closure
// in which case, recover the enclosing object from this
bool addClosedOver = false ;
if ( enclosingFunction & & enclosingFunction - > getDataRef ( ) - > closedVariables . size ( ) ) {
for ( auto closedVar : enclosingFunction - > getDataRef ( ) - > closedVariables ) {
if ( closedVar - > getDataRef ( ) - > symbol . getName ( ) = = " this " ) {
enclosingObject = closedVar - > getDataRef ( ) - > valueType - > typeDefinition ;
addClosedOver = true ;
}
2015-07-05 02:34:45 -04:00
}
2015-06-27 18:06:02 -04:00
}
2015-11-09 13:26:02 -05:00
//Check to see if we're inside of an object and this is a method call
bool isSelfObjectMethod = enclosingObject & & contains ( enclosingObject - > getChildren ( ) , children [ 0 ] ) ;
if ( isSelfObjectMethod ) {
output + = function_header + prefixIfNeeded ( scopePrefix ( children [ 0 ] ) , CifyName ( enclosingObject - > getDataRef ( ) - > symbol . getName ( ) ) ) + " __ " ;
output + = CifyName ( name + nameDecoration ) + " ( " ;
output + = std : : string ( addClosedOver ? " (*closed_variables->this) " : " this " ) + ( children . size ( ) > 1 ? " , " : " " ) ;
} else {
2015-11-19 16:27:36 -05:00
// ha, I think this is the normal function call one. Had a little trouble finding it
// darned if we don't have to special case ADT psudo-constructors
auto possibleParentADTVector = children [ 0 ] - > getDataRef ( ) - > scope [ " ~enclosing_scope " ] ;
NodeTree < ASTData > * possibleParentADT = possibleParentADTVector . size ( ) ? possibleParentADTVector [ 0 ] : nullptr ;
std : : string adtAdditional = " " ;
if ( possibleParentADT & & possibleParentADT - > getDataRef ( ) - > type = = adt_def )
adtAdditional = possibleParentADT - > getDataRef ( ) - > symbol . getName ( ) + " __ " ;
output + = function_header + prefixIfNeeded ( scopePrefix ( children [ 0 ] ) , CifyName ( adtAdditional + name + nameDecoration ) ) + " ( " ;
2015-11-09 13:26:02 -05:00
}
2015-07-05 02:34:45 -04:00
}
2015-04-04 01:32:40 -04:00
}
2015-11-09 13:26:02 -05:00
} else {
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
//It's probabally the result of an access function call (. or ->) to access an object method.
//OR a function value!
//
//THIS IS UUUUUGLLYYY too. We moved the closure part out to after the generation of the params becuase it needs to use them twice
functionCallSource = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) ;
if ( functionCallSource . value [ functionCallSource . value . size ( ) - 1 ] = = ' , ' ) //If it's a member method, it's already started the parameter list.
output + = children . size ( ) > 1 ? functionCallSource : CCodeTriple ( functionCallSource . preValue , functionCallSource . value . substr ( 0 , functionCallSource . value . size ( ) - 1 ) , functionCallSource . postValue ) ;
else {
doClosureInstead = true ;
}
2015-06-25 04:09:19 -04:00
}
2015-11-09 13:26:02 -05:00
CCodeTriple parameters ;
// see if we should copy_construct / referencize all the parameters
for ( int i = 1 ; i < children . size ( ) ; i + + ) { //children[0] is the declaration
Type * func_param_type = children [ 0 ] - > getDataRef ( ) - > valueType - > parameterTypes [ i - 1 ] ;
// ok, if our param is a reference returned by another function, we don't actually want this type to be a reference if it is now.
Type * param_type = children [ i ] - > getDataRef ( ) - > valueType - > withoutReference ( ) ;
// don't copy_construct references
if ( func_param_type - > is_reference ) {
2015-07-14 22:42:25 -04:00
parameters + = " & " + generate ( children [ i ] , enclosingObject , true , enclosingFunction ) ;
2015-11-09 13:26:02 -05:00
} else if ( methodExists ( children [ i ] - > getDataRef ( ) - > valueType , " copy_construct " , std : : vector < Type > { param_type - > withIncreasedIndirection ( ) } ) ) {
std : : string tmpParamName = " param " + getID ( ) ;
CCodeTriple paramValue = generate ( children [ i ] , enclosingObject , true , enclosingFunction ) ;
parameters . preValue + = paramValue . preValue ;
parameters . preValue + = ValueTypeToCType ( param_type , tmpParamName ) + " ; \n " ;
parameters . preValue + = generateMethodIfExists ( param_type , " copy_construct " , " & " + tmpParamName + " , & " + paramValue . value , std : : vector < Type > { children [ i ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) ;
parameters . value + = tmpParamName ;
parameters . postValue + = paramValue . postValue ;
} else {
parameters + = generate ( children [ i ] , enclosingObject , true , enclosingFunction ) ;
}
if ( i < children . size ( ) - 1 )
parameters + = " , " ;
}
if ( doClosureInstead ) {
Type * funcType = children [ 0 ] - > getDataRef ( ) - > valueType ;
Type * retType = funcType - > returnType ;
bool doRet = retType - > baseType ! = void_type | | retType - > getIndirection ( ) ;
std : : string tmpName = " functionValueTmp " + getID ( ) ;
std : : string retTmpName = " closureRetTemp " + getID ( ) ;
output + = CCodeTriple ( parameters . preValue + functionCallSource . preValue + ValueTypeToCType ( funcType , tmpName ) + " = " + functionCallSource . value + " ; \n "
+ ( doRet ? ValueTypeToCType ( retType , retTmpName ) + " ; \n " : " " )
+ " if ( " + tmpName + " .data) { " + ( doRet ? ( retTmpName + " = " ) : " " ) + " (( " + ValueTypeToCTypeDecoration ( funcType , ClosureFunctionPointerTypeWithClosedParam ) + " ) ( " + tmpName + " .func))( " + tmpName + " .data " + ( children . size ( ) > 1 ? " , " : " " ) + parameters . value + " ); } \n "
+ " else { " + ( doRet ? ( retTmpName + " = " ) : " " ) + " (( " + ValueTypeToCTypeDecoration ( funcType , ClosureFunctionPointerTypeWithoutClosedParam ) + " ) ( " + tmpName + " .func))( " + parameters . value + " ); } \n " ,
( doRet ? retTmpName : " " ) ,
parameters . postValue + functionCallSource . postValue ) ;
2015-05-30 04:43:01 -04:00
} else {
2015-11-09 13:26:02 -05:00
output + = parameters + " ) " ;
2015-05-30 04:43:01 -04:00
}
2015-11-09 13:26:02 -05:00
// see if we should add a destructer call to this postValue
Type * retType = children [ 0 ] - > getDataRef ( ) - > valueType - > returnType ;
if ( retType - > baseType ! = void_type ) {
// we always use return temps now :( (for psudo-pod objects that still have methods called on them, like range(1,3).for_each(...)
std : : string retTempName = " return_temp " + getID ( ) ;
output . preValue + = ValueTypeToCType ( retType , retTempName ) + " = " + output . value + " ; \n " ;
output . value = retTempName ;
if ( retType - > is_reference )
output . value = " (* " + output . value + " ) " ;
else if ( methodExists ( retType , " destruct " , std : : vector < Type > ( ) ) ) {
output . postValue = generateMethodIfExists ( retType , " destruct " , " & " + retTempName , std : : vector < Type > ( ) ) + " ; \n " + output . postValue ;
}
2015-06-28 20:25:27 -04:00
}
2015-11-09 13:26:02 -05:00
return output ;
2015-05-30 04:43:01 -04:00
}
2015-11-09 13:26:02 -05:00
case value :
{
// ok, we now check for it being a multiline string and escape all returns if it is (so that multiline strings work)
if ( data . symbol . getName ( ) [ 0 ] = = ' " ' & & strSlice ( data . symbol . getName ( ) , 0 , 3 ) = = " \" \" \" " ) {
std : : string innerString = strSlice ( data . symbol . getName ( ) , 3 , - 4 ) ;
std : : string newStr ;
for ( auto character : innerString )
if ( character = = ' \n ' )
newStr + = " \\ n " ;
else if ( character = = ' " ' )
newStr + = " \\ \" " ;
else
newStr + = character ;
return " \" " + newStr + " \" " ;
}
return data . symbol . getName ( ) ;
2015-06-19 12:06:27 -04:00
}
2013-11-01 02:52:18 -04:00
2015-11-09 13:26:02 -05:00
default :
std : : cout < < " Nothing! " < < std : : endl ;
}
for ( int i = 0 ; i < children . size ( ) ; i + + )
output + = generate ( children [ i ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2014-02-03 11:41:25 -05:00
2015-11-09 13:26:02 -05:00
return output ;
2014-02-03 11:41:25 -05:00
}
2014-06-10 23:59:39 -07:00
NodeTree < ASTData > * CGenerator : : getMethodsObjectType ( NodeTree < ASTData > * scope , std : : string functionName ) {
//check the thing
while ( scope ! = scope - > getDataRef ( ) - > valueType - > typeDefinition ) //type is an alias, follow it to the definition
scope = scope - > getDataRef ( ) - > valueType - > typeDefinition ;
return ( scope - > getDataRef ( ) - > scope . find ( functionName ) ! = scope - > getDataRef ( ) - > scope . end ( ) ) ? scope : NULL ;
}
2014-07-28 01:52:15 -07:00
// Returns the function prototype in the out param and the full definition normally
std : : string CGenerator : : generateObjectMethod ( NodeTree < ASTData > * enclosingObject , NodeTree < ASTData > * from , std : : string * functionPrototype ) {
2015-06-01 01:43:23 -04:00
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
2015-11-09 13:26:02 -05:00
ASTData data = from - > getData ( ) ;
Type enclosingObjectType = * ( enclosingObject - > getDataRef ( ) - > valueType ) ; //Copy a new type so we can turn it into a pointer if we need to
enclosingObjectType . increaseIndirection ( ) ;
std : : vector < NodeTree < ASTData > * > children = from - > getChildren ( ) ;
std : : string nameDecoration , parameters ;
2015-06-28 14:27:48 -04:00
if ( ! children . size ( ) ) {
//problem
std : : cerr < < " no children " < < std : : endl ;
}
2015-11-09 13:26:02 -05:00
for ( int i = 0 ; i < children . size ( ) - 1 ; i + + ) {
parameters + = " , " + ValueTypeToCType ( children [ i ] - > getData ( ) . valueType , generate ( children [ i ] ) . oneString ( ) ) ;
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( children [ i ] - > getData ( ) . valueType ) ;
2015-06-01 01:43:23 -04:00
distructDoubleStack . back ( ) . push_back ( children [ i ] ) ;
2015-11-09 13:26:02 -05:00
}
2015-11-06 03:23:55 -05:00
std : : string functionSignature = " \n " + ValueTypeToCType ( data . valueType - > returnType , function_header +
prefixIfNeeded ( scopePrefix ( from ) , CifyName ( enclosingObject - > getDataRef ( ) - > symbol . getName ( ) ) ) + " __ " +
2015-11-09 13:26:02 -05:00
CifyName ( data . symbol . getName ( ) ) + nameDecoration ) + " ( " + ValueTypeToCType ( & enclosingObjectType , " this " ) + parameters + " ) " ;
2014-07-28 01:52:15 -07:00
* functionPrototype + = functionSignature + " ; \n " ;
2015-05-27 12:27:50 -04:00
// Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock
2015-06-01 01:43:23 -04:00
//
std : : string output ;
2015-07-15 00:53:53 -04:00
output + = functionSignature + " { \n " + generate ( children . back ( ) , enclosingObject , false , from ) . oneString ( ) ;
2015-06-01 01:43:23 -04:00
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = " } \n " ; //Pass in the object so we can properly handle access to member stuff
distructDoubleStack . pop_back ( ) ;
return output ;
2015-05-30 04:43:01 -04:00
}
2015-06-05 00:34:24 -04:00
NodeTree < ASTData > * CGenerator : : getMethod ( Type * type , std : : string method , std : : vector < Type > types ) {
2015-05-30 04:43:01 -04:00
if ( type - > getIndirection ( ) )
return nullptr ;
NodeTree < ASTData > * typeDefinition = type - > typeDefinition ;
if ( typeDefinition ) {
auto definitionItr = typeDefinition - > getDataRef ( ) - > scope . find ( method ) ;
2015-06-05 00:34:24 -04:00
if ( definitionItr ! = typeDefinition - > getDataRef ( ) - > scope . end ( ) ) {
for ( auto method : definitionItr - > second ) {
bool methodFits = true ;
std : : vector < Type > methodTypes = dereferenced ( method - > getDataRef ( ) - > valueType - > parameterTypes ) ;
if ( types . size ( ) ! = methodTypes . size ( ) )
continue ;
for ( int i = 0 ; i < types . size ( ) ; i + + ) {
2015-07-15 00:53:53 -04:00
// don't care about references
if ( ! types [ i ] . test_equality ( methodTypes [ i ] , false ) ) {
2015-06-05 00:34:24 -04:00
methodFits = false ;
break ;
}
}
if ( methodFits )
return method ;
}
}
2015-05-30 04:43:01 -04:00
}
return nullptr ;
}
2015-06-05 00:34:24 -04:00
bool CGenerator : : methodExists ( Type * type , std : : string method , std : : vector < Type > types ) {
return getMethod ( type , method , types ) ! = nullptr ;
2015-05-30 04:43:01 -04:00
}
2015-06-05 00:34:24 -04:00
std : : string CGenerator : : generateMethodIfExists ( Type * type , std : : string method , std : : string parameter , std : : vector < Type > methodTypes ) {
NodeTree < ASTData > * methodDef = getMethod ( type , method , methodTypes ) ;
2015-05-30 04:43:01 -04:00
if ( methodDef ) {
2015-06-05 00:34:24 -04:00
NodeTree < ASTData > * typeDefinition = type - > typeDefinition ;
2015-05-30 04:43:01 -04:00
std : : string nameDecoration ;
for ( Type * paramType : methodDef - > getDataRef ( ) - > valueType - > parameterTypes )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( paramType ) ;
2015-11-19 16:27:36 -05:00
return function_header + prefixIfNeeded ( scopePrefix ( typeDefinition ) , CifyName ( typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ) ) + " __ " + CifyName ( method ) + nameDecoration + " ( " + parameter + " ); \n " ;
2015-05-30 04:43:01 -04:00
}
return " " ;
}
std : : string CGenerator : : emitDestructors ( std : : vector < NodeTree < ASTData > * > identifiers , NodeTree < ASTData > * enclosingObject ) {
std : : string destructorString = " " ;
for ( auto identifier : identifiers )
2015-07-14 22:42:25 -04:00
if ( ! identifier - > getDataRef ( ) - > valueType - > is_reference )
destructorString + = tabs ( ) + generateMethodIfExists ( identifier - > getDataRef ( ) - > valueType , " destruct " , " & " + generate ( identifier , enclosingObject ) . oneString ( ) , std : : vector < Type > ( ) ) ;
2015-05-30 04:43:01 -04:00
return destructorString ;
2013-11-01 02:52:18 -04:00
}
2015-06-26 13:29:37 -04:00
std : : string CGenerator : : closureStructType ( std : : set < NodeTree < ASTData > * > closedVariables ) {
auto it = closureStructMap . find ( closedVariables ) ;
if ( it ! = closureStructMap . end ( ) )
return it - > second ;
std : : string typedefString = " typedef struct { " ;
// note the increased indirection b/c we're using references to what we closed over
for ( auto var : closedVariables ) {
2015-06-28 14:27:48 -04:00
// unfortunatly we can't just do it with increased indirection b/c closing over function values
// will actually change the underlying function's type. We cheat and just add a *
//auto tmp = var->getDataRef()->valueType->withIncreasedIndirection();
2015-06-27 18:06:02 -04:00
std : : string varName = var - > getDataRef ( ) - > symbol . getName ( ) ;
2015-11-06 03:23:55 -05:00
varName = ( varName = = " this " ) ? varName : prefixIfNeeded ( scopePrefix ( var ) , varName ) ;
2015-08-04 14:57:56 -04:00
typedefString + = ValueTypeToCType ( var - > getDataRef ( ) - > valueType - > withoutReference ( ) , " * " + varName ) + " ; " ;
2015-06-26 13:29:37 -04:00
}
std : : string structName = " closureStructType " + getID ( ) ;
typedefString + = " } " + structName + " ; \n " ;
functionTypedefString + = typedefString ;
closureStructMap [ closedVariables ] = structName ;
return structName ;
}
2015-03-11 01:58:10 -04:00
2015-06-25 04:09:19 -04:00
std : : string CGenerator : : ValueTypeToCType ( Type * type , std : : string declaration , ClosureTypeSpecialType closureSpecial ) { return ValueTypeToCTypeThingHelper ( type , " " + declaration , closureSpecial ) ; }
std : : string CGenerator : : ValueTypeToCTypeDecoration ( Type * type , ClosureTypeSpecialType closureSpecial ) { return CifyName ( ValueTypeToCTypeThingHelper ( type , " " , closureSpecial ) ) ; }
std : : string CGenerator : : ValueTypeToCTypeThingHelper ( Type * type , std : : string declaration , ClosureTypeSpecialType closureSpecial ) {
2015-11-09 13:26:02 -05:00
std : : string return_type ;
2015-05-18 04:46:03 -04:00
bool do_ending = true ;
2015-11-09 13:26:02 -05:00
switch ( type - > baseType ) {
case none :
if ( type - > typeDefinition )
return_type = prefixIfNeeded ( scopePrefix ( type - > typeDefinition ) , CifyName ( type - > typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ) ) ;
else
return_type = " none " ;
break ;
case function_type :
2015-05-18 04:46:03 -04:00
{
std : : string indr_str ;
for ( int i = 0 ; i < type - > getIndirection ( ) ; i + + )
indr_str + = " * " ;
2015-06-25 04:09:19 -04:00
auto it = functionTypedefMap . find ( * type ) ;
if ( it ! = functionTypedefMap . end ( ) ) {
if ( closureSpecial = = ClosureFunctionPointerTypeWithClosedParam )
return_type = it - > second . second + declaration ;
2015-07-04 18:55:15 -04:00
else if ( closureSpecial = = ClosureFunctionPointerTypeWithoutClosedParam )
return_type = it - > second . third + declaration ;
2015-06-25 04:09:19 -04:00
else
return_type = it - > second . first + declaration ;
} else {
std : : string typedefWithoutVoidStr = " typedef " ;
std : : string typedefWithVoidStr = " typedef " ;
std : : string typedefWithoutVoidID = " ID_novoid_ " + CifyName ( type - > toString ( false ) ) ;
std : : string typedefWithVoidID = " ID_withvoid_ " + CifyName ( type - > toString ( false ) ) ;
std : : string typedefStructID = " ID_struct_ " + CifyName ( type - > toString ( false ) ) ;
2015-07-04 18:55:15 -04:00
// How I wish the world were this kind. Because of C name resolution not looking ahead, this definition needs to be BEFORE
// the object definitions. So to prevent circular dependencies, I'm making this take in a void pointer and we'll simply
// cast in both cases, whether or not there's a data pointer. Sigh.
//std::string typedefStructStr = "typedef struct {" + typedefWithoutVoidID + " func; void* val; } " + typedefStructID + ";\n";
std : : string typedefStructStr = " typedef struct { void* func; void* data; } " + typedefStructID + " ; \n " ;
2015-06-25 04:09:19 -04:00
typedefWithoutVoidStr + = ValueTypeToCTypeThingHelper ( type - > returnType , " " , closureSpecial ) ;
typedefWithVoidStr + = ValueTypeToCTypeThingHelper ( type - > returnType , " " , closureSpecial ) ;
typedefWithoutVoidStr + = " (* " + typedefWithoutVoidID + " )( " ;
typedefWithVoidStr + = " (* " + typedefWithVoidID + " )( " ;
typedefWithVoidStr + = " void* " ;
if ( type - > parameterTypes . size ( ) = = 0 )
typedefWithoutVoidStr + = " void " ;
else
for ( int i = 0 ; i < type - > parameterTypes . size ( ) ; i + + ) {
typedefWithoutVoidStr + = ( i ! = 0 ? " , " : " " ) + ValueTypeToCTypeThingHelper ( type - > parameterTypes [ i ] , " " , closureSpecial ) ;
typedefWithVoidStr + = " , " + ValueTypeToCTypeThingHelper ( type - > parameterTypes [ i ] , " " , closureSpecial ) ;
}
typedefWithoutVoidStr + = " ); \n " ;
typedefWithVoidStr + = " ); \n " ;
2015-07-04 18:55:15 -04:00
// again, sigh
2015-06-25 04:09:19 -04:00
functionTypedefString + = typedefWithoutVoidStr ;
functionTypedefString + = typedefWithVoidStr ;
2015-07-04 18:55:15 -04:00
functionTypedefStringPre + = typedefStructStr ;
//functionTypedefString += typedefStructStr;
2015-06-25 04:09:19 -04:00
if ( closureSpecial = = ClosureFunctionPointerTypeWithClosedParam )
return_type = typedefWithVoidID + indr_str + declaration ;
else
return_type = typedefStructID + indr_str + declaration ;
2015-07-04 18:55:15 -04:00
functionTypedefMap [ * type ] = make_triple ( typedefStructID , typedefWithVoidID , typedefWithoutVoidID ) ;
2015-06-25 04:09:19 -04:00
}
2015-05-18 04:46:03 -04:00
do_ending = false ;
}
2015-11-09 13:26:02 -05:00
break ;
case void_type :
return_type = " void " ;
break ;
case boolean :
return_type = " bool " ;
break ;
case integer :
return_type = " int " ;
break ;
case floating :
return_type = " float " ;
break ;
case double_percision :
return_type = " double " ;
break ;
case character :
return_type = " char " ;
break ;
default :
return_type = " unknown_ValueType " ;
break ;
}
2015-05-18 04:46:03 -04:00
if ( ! do_ending )
return return_type ;
2015-11-09 13:26:02 -05:00
for ( int i = 0 ; i < type - > getIndirection ( ) ; i + + )
return_type + = " * " ;
2015-11-25 15:35:06 -05:00
if ( type - > is_reference ) {
2015-11-09 13:26:02 -05:00
return_type + = " /*ref*/ * " ;
2015-11-25 15:35:06 -05:00
}
2015-05-18 04:46:03 -04:00
return return_type + declaration ;
2014-03-06 13:13:40 -05:00
}
2014-03-07 14:17:07 -05:00
2014-05-10 19:28:36 -04:00
std : : string CGenerator : : CifyName ( std : : string name ) {
2015-11-09 13:26:02 -05:00
std : : string operatorsToReplace [ ] = { " + " , " plus " ,
" - " , " minus " ,
" * " , " star " ,
" / " , " div " ,
" % " , " mod " ,
" ^ " , " carat " ,
" & " , " amprsd " ,
" | " , " pipe " ,
" ~ " , " tilde " ,
" ! " , " exlmtnpt " ,
" , " , " comma " ,
" = " , " eq " ,
" ++ " , " dbplus " ,
" -- " , " dbminus " ,
" << " , " dbleft " ,
" >> " , " dbright " ,
" :: " , " scopeop " ,
" : " , " colon " ,
" == " , " dbq " ,
" != " , " notequals " ,
" && " , " doubleamprsnd " ,
" || " , " doublepipe " ,
" += " , " plusequals " ,
" -= " , " minusequals " ,
" /= " , " divequals " ,
" %= " , " modequals " ,
" ^= " , " caratequals " ,
" &= " , " amprsdequals " ,
" |= " , " pipeequals " ,
" *= " , " starequals " ,
" <<= " , " doublerightequals " ,
" < " , " lt " ,
" > " , " gt " ,
" >>= " , " doubleleftequals " ,
" ( " , " openparen " ,
" ) " , " closeparen " ,
" [ " , " obk " ,
" ] " , " cbk " ,
" " , " space " ,
" . " , " dot " ,
" -> " , " arrow " } ;
int length = sizeof ( operatorsToReplace ) / sizeof ( std : : string ) ;
//std::cout << "Length is " << length << std::endl;
for ( int i = 0 ; i < length ; i + = 2 ) {
size_t foundPos = name . find ( operatorsToReplace [ i ] ) ;
while ( foundPos ! = std : : string : : npos ) {
name = strSlice ( name , 0 , foundPos ) + " _ " + operatorsToReplace [ i + 1 ] + " _ " + strSlice ( name , foundPos + operatorsToReplace [ i ] . length ( ) , - 1 ) ;
foundPos = name . find ( operatorsToReplace [ i ] ) ;
}
}
return name ;
2014-03-14 15:55:45 -04:00
}
2015-04-04 01:32:40 -04:00
// Generate the scope prefix, that is "file_class_" for a method, etc
// What do we still need to handle? Packages! But we don't have thoes yet....
std : : string CGenerator : : scopePrefix ( NodeTree < ASTData > * from ) {
//return "";
std : : string suffix = " _scp_ " ;
ASTData data = from - > getData ( ) ;
if ( data . type = = translation_unit )
return CifyName ( data . symbol . getName ( ) ) + suffix ;
// so we do prefixing for stuff that c doesn't already scope:
// different files. That's it for now. Methods are already lowered correctly with their parent object,
// that parent object will get scoped. When we add a package system, we'll have to then add their scoping here
return scopePrefix ( from - > getDataRef ( ) - > scope [ " ~enclosing_scope " ] [ 0 ] ) ;
}
2015-11-06 03:23:55 -05:00
std : : string CGenerator : : prefixIfNeeded ( std : : string prefix , std : : string name ) {
return simpleComplexName ( name , prefix + name ) ;
}
std : : string CGenerator : : simpleComplexName ( std : : string simpleName , std : : string complexName ) {
auto already = simpleComplexNameMap . find ( complexName ) ;
if ( already ! = simpleComplexNameMap . end ( ) )
return already - > second ;
if ( usedNameSet . find ( simpleName ) = = usedNameSet . end ( ) ) {
usedNameSet . insert ( simpleName ) ;
simpleComplexNameMap [ complexName ] = simpleName ;
return simpleName ;
}
usedNameSet . insert ( complexName ) ;
simpleComplexNameMap [ complexName ] = complexName ;
return complexName ;
}
2014-03-14 15:55:45 -04:00