2013-11-01 02:52:18 -04:00
# include "CGenerator.h"
2013-12-22 01:34:59 -06:00
CGenerator : : CGenerator ( ) : generatorString ( " __C__ " ) {
2013-11-01 02:52:18 -04:00
tabLevel = 0 ;
2015-05-30 04:43:01 -04:00
id = 0 ;
2015-06-12 14:16:28 -04:00
function_header = " fun_ " ;
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.
2014-01-01 17:29:19 -06:00
void CGenerator : : generateCompSet ( std : : map < std : : string , NodeTree < ASTData > * > ASTs , std : : string outputName ) {
//Generate an entire set of files
2015-06-01 01:43:23 -04:00
std : : string buildString = " #!/bin/sh \n cc -g -std=c99 " ;
2014-12-30 01:22:09 -05:00
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 " ;
std : : ofstream outputCFile , outputHFile ;
outputCFile . open ( outputName + " / " + outputName + " .c " ) ;
outputHFile . open ( outputName + " / " + outputName + " .h " ) ;
if ( outputCFile . is_open ( ) | | outputHFile . is_open ( ) ) {
// Prequel common to all files
auto chPair = generateTranslationUnit ( outputName , ASTs ) ;
outputHFile < < " #include <stdbool.h> \n #include <stdlib.h> \n #include <stdio.h> \n " < < chPair . first ;
outputCFile < < " #include \" " + outputName + " .h \" \n \n " < < chPair . second ;
} 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 ( ) ;
outputHFile . close ( ) ;
2015-04-10 00:37:31 -04:00
buildString + = linkerString ;
2014-01-01 17:29:19 -06:00
buildString + = " -o " + outputName ;
std : : ofstream outputBuild ;
2014-12-30 01:22:09 -05:00
outputBuild . open ( outputName + " / " + split ( outputName , ' / ' ) . back ( ) + " .sh " ) ;
2014-01-01 17:29:19 -06:00
outputBuild < < buildString ;
outputBuild . close ( ) ;
2015-05-30 04:43:01 -04:00
std : : cout < < " DEFER DOUBLE STACK " < < deferDoubleStack . size ( ) < < std : : endl ;
2014-01-01 17:29:19 -06:00
}
2013-11-01 02:52:18 -04:00
std : : string CGenerator : : tabs ( ) {
std : : string returnTabs ;
for ( int i = 0 ; i < tabLevel ; i + + )
returnTabs + = " \t " ;
return returnTabs ;
}
2015-05-30 04:43:01 -04:00
std : : string CGenerator : : getID ( ) {
return intToString ( id + + ) ;
}
2014-07-28 01:52:15 -07:00
std : : string CGenerator : : generateClassStruct ( NodeTree < ASTData > * from ) {
auto data = from - > getData ( ) ;
auto children = from - > getChildren ( ) ;
2015-04-04 01:32:40 -04:00
std : : string objectString = " struct __struct_dummy_ " + scopePrefix ( from ) + CifyName ( data . symbol . getName ( ) ) + " __ { \n " ;
2014-07-28 01:52:15 -07:00
tabLevel + + ;
for ( int i = 0 ; i < children . size ( ) ; i + + ) {
std : : cout < < children [ i ] - > getName ( ) < < std : : endl ;
if ( children [ i ] - > getName ( ) ! = " function " )
2015-05-30 04:43:01 -04:00
objectString + = tabs ( ) + generate ( children [ i ] , nullptr ) . oneString ( ) + " \n " ;
2014-07-28 01:52:15 -07:00
}
tabLevel - - ;
objectString + = " }; " ;
return objectString ;
}
// 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 ) {
2014-07-28 01:52:15 -07:00
std : : string output ;
2015-03-11 01:58:10 -04:00
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 ) {
2015-04-04 01:32:40 -04:00
output + = " typedef " +
scopePrefix ( definition ) + CifyName ( definition - > getDataRef ( ) - > symbol . getName ( ) ) + " " +
scopePrefix ( declaration ) + CifyName ( declarationData - > symbol . getName ( ) ) + " ; \n " ;
2015-03-11 01:58:10 -04:00
// Recursively add the ones that depend on this one
output + = generateAliasChains ( ASTs , declaration ) ;
}
2014-07-28 01:52:15 -07:00
}
}
}
return output ;
}
2014-12-30 01:22:09 -05:00
bool CGenerator : : isUnderTranslationUnit ( NodeTree < ASTData > * from , NodeTree < ASTData > * node ) {
auto scope = from - > getDataRef ( ) - > scope ;
for ( auto i : scope )
for ( auto j : i . second )
if ( j = = node )
return true ;
auto upper = scope . find ( " ~enclosing_scope " ) ;
if ( upper ! = scope . end ( ) )
return isUnderTranslationUnit ( upper - > second [ 0 ] , node ) ;
return false ;
}
NodeTree < ASTData > * CGenerator : : highestScope ( NodeTree < ASTData > * node ) {
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 ;
}
// 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 ) {
// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file
2014-12-30 01:22:09 -05:00
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
2014-12-30 01:22:09 -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
2014-12-30 01:22:09 -05:00
std : : string importIncludes = " /** \n * Import Includes \n */ \n \n " ;
2015-03-24 18:29:21 -04:00
std : : string topLevelCPassthrough = " /** \n * Top Level C Passthrough \n */ \n \n " ;
2014-12-30 01:22:09 -05:00
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 " ;
2015-05-22 22:30:25 -04:00
// 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
2014-12-30 01:22:09 -05:00
Poset < NodeTree < ASTData > * > typedefPoset ;
2015-03-11 01:58:10 -04:00
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-03-11 01:58:10 -04: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
}
}
}
}
//Now generate the typedef's in the correct, topological order
for ( NodeTree < ASTData > * i : typedefPoset . getTopoSort ( ) )
classStructs + = generateClassStruct ( i ) + " \n " ;
2014-07-28 01:52:15 -07:00
2015-03-11 01:58:10 -04:00
// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations)
2014-12-30 01:22:09 -05:00
// Also, everything in all of the import's scopes
2015-03-24 18:29:21 -04:00
// Also c passthrough
2015-03-11 01:58:10 -04:00
for ( auto trans : ASTs ) {
2015-03-24 18:29:21 -04:00
// First go through and emit all the passthroughs, etc
for ( auto i : trans . second - > getChildren ( ) ) {
if ( i - > getDataRef ( ) - > type = = if_comp )
2015-05-30 04:43:01 -04:00
topLevelCPassthrough + = generate ( i , nullptr ) . oneString ( ) ;
2015-03-24 18:29:21 -04:00
}
2015-03-11 01:58:10 -04: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 :
2015-06-19 12:48:18 -04:00
{
auto parent = declaration - > getDataRef ( ) - > scope [ " ~enclosing_scope " ] [ 0 ] ;
if ( parent - > getChildren ( ) . size ( ) = = 1 )
variableDeclarations + = ValueTypeToCType ( declarationData . valueType , scopePrefix ( declaration ) + declarationData . symbol . getName ( ) ) + " ; /*identifier*/ \n " ;
else
2015-06-25 04:09:19 -04:00
variableDeclarations + = ValueTypeToCType ( declarationData . valueType , generate ( parent - > getChildren ( ) [ 0 ] , nullptr , true , nullptr ) . oneString ( ) ) + " = " + generate ( parent - > getChildren ( ) [ 1 ] , nullptr , true , nullptr ) . oneString ( ) + " ; " ;
2015-05-18 04:46:03 -04:00
variableExternDeclarations + = " extern " + ValueTypeToCType ( declarationData . valueType , declarationData . symbol . getName ( ) ) + " ; /*extern identifier*/ \n " ;
2015-03-11 01:58:10 -04:00
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-06-12 14:16:28 -04:00
functionPrototypes + = " \n " + ValueTypeToCType ( declarationData . valueType - > returnType , ( ( declarationData . symbol . getName ( ) = = " main " ) ? " " : function_header + scopePrefix ( declaration ) ) +
2015-05-18 04:46:03 -04:00
CifyName ( declarationData . symbol . getName ( ) + nameDecoration ) ) +
2015-04-04 01:32:40 -04:00
" ( " + parameters + " ); /*func*/ \n " ;
2015-03-11 01:58:10 -04:00
// generate function
2015-04-04 01:32:40 -04:00
std : : cout < < " Generating " < < 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-04-04 01:32:40 -04:00
scopePrefix ( declaration ) +
2015-05-18 04:46:03 -04:00
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_ " +
scopePrefix ( declaration ) + CifyName ( declarationData . symbol . getName ( ) ) + " __ " +
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 + + ) {
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 ;
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-05-22 22:30:25 -04:00
hOutput + = plainTypedefs + importIncludes + topLevelCPassthrough + 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 ) {
2014-12-30 01:22:09 -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 ;
2014-12-30 01:22:09 -05:00
switch ( data . type ) {
case translation_unit :
{
// Should not happen! We do this in it's own function now!
2015-03-14 02:42:07 -04:00
std : : cerr < < " Trying to normal generate a translation unit! That's a nono! ( " < < from - > getDataRef ( ) - > toString ( ) < < " ) " < < std : : endl ;
2014-12-30 01:22:09 -05:00
throw " That's not gonna work " ;
2014-05-21 13:14:16 -04:00
}
2013-11-01 02:52:18 -04:00
break ;
case interpreter_directive :
//Do nothing
break ;
case import :
2015-05-30 04:43:01 -04:00
return CCodeTriple ( " /* never reached import? */ \n " ) ;
2013-11-01 02:52:18 -04:00
case identifier :
2014-02-03 11:41:25 -05:00
{
2014-06-26 01:45:44 -07:00
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
2015-03-11 01:58:10 -04:00
if ( data . symbol . getName ( ) = = " this " ) {
2014-06-26 01:45:44 -07:00
if ( enclosingObject )
2015-05-30 04:43:01 -04:00
return CCodeTriple ( " this " ) ;
2014-06-26 01:45:44 -07:00
else
2015-03-14 02:42:07 -04:00
std : : cerr < < " Error: this used in non-object scope " < < std : : endl ;
2015-03-11 01:58:10 -04:00
}
2014-06-26 01:45:44 -07:00
//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.
2015-06-25 04:09:19 -04:00
std : : string preName ;
//std::string preName = "/*ident*/";
// check for this being a closed over variable
// first, get declaring function, if it exists
if ( enclosingFunction ) {
if ( enclosingFunction - > getDataRef ( ) - > closedVariables . size ( ) ) {
std : : cout < < " WHOH IS A CLOSER " < < std : : endl ;
if ( enclosingFunction - > getDataRef ( ) - > closedVariables . find ( from ) ! = enclosingFunction - > getDataRef ( ) - > closedVariables . end ( ) )
preName + = " /* SPECIAL CLOSED */ *closed_varibles-> " ;
}
}
2014-03-06 13:13:40 -05:00
if ( enclosingObject & & enclosingObject - > getDataRef ( ) - > scope . find ( data . symbol . getName ( ) ) ! = enclosingObject - > getDataRef ( ) - > scope . end ( ) )
2014-06-26 01:45:44 -07:00
preName + = " this-> " ;
2015-04-04 01:32:40 -04:00
// we're scope prefixing EVERYTHING
return preName + scopePrefix ( from ) + CifyName ( data . symbol . getName ( ) ) ; //Cifying does nothing if not an operator overload
2014-02-03 11:41:25 -05:00
}
2013-11-01 02:52:18 -04:00
case function :
2014-03-06 13:13:40 -05:00
{
2014-05-15 17:58:41 -04:00
if ( data . valueType - > baseType = = template_type )
return " /* template function: " + data . symbol . getName ( ) + " */ " ;
2015-05-30 04:43:01 -04:00
// we push on a new vector to hold parameters that might need a destructor call
distructDoubleStack . push_back ( std : : vector < NodeTree < ASTData > * > ( ) ) ;
2014-03-06 13:13:40 -05:00
std : : string nameDecoration , parameters ;
2015-06-25 04:09:19 -04:00
if ( data . closedVariables . size ( ) )
2015-06-26 13:29:37 -04:00
parameters + = closureStructType ( data . closedVariables ) + " *closed_varibles " ;
2014-03-06 13:13:40 -05:00
for ( int j = 0 ; j < children . size ( ) - 1 ; j + + ) {
2015-06-25 04:09:19 -04:00
if ( j > 0 | | data . closedVariables . size ( ) )
2014-03-06 13:13:40 -05:00
parameters + = " , " ;
2015-06-25 04:09:19 -04:00
parameters + = ValueTypeToCType ( children [ j ] - > getData ( ) . valueType , generate ( children [ j ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ) ;
2014-03-07 14:17:07 -05:00
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( children [ j ] - > getData ( ) . valueType ) ;
2015-05-30 04:43:01 -04:00
// add parameters to distructDoubleStack so that their destructors will be called at return (if they exist)
distructDoubleStack . back ( ) . push_back ( children [ j ] ) ;
2013-11-01 02:52:18 -04:00
}
2015-05-18 04:46:03 -04:00
// this is for using functions as values
2015-05-30 04:43:01 -04:00
if ( justFuncName ) {
2015-06-25 04:09:19 -04:00
std : : string funcName ;
if ( data . symbol . getName ( ) ! = " main " )
funcName + = function_header + scopePrefix ( from ) ;
funcName + = CifyName ( data . symbol . getName ( ) + nameDecoration ) ;
if ( from - > getDataRef ( ) - > closedVariables . size ( ) ) {
std : : string tmpStruct = " closureStruct " + getID ( ) ;
2015-06-26 13:29:37 -04:00
output . preValue + = closureStructType ( data . closedVariables ) + " " + tmpStruct + " = { " ;
bool notFirst = false ;
for ( auto var : data . closedVariables ) {
if ( notFirst )
output . preValue + = " , " ;
notFirst = true ;
output . preValue + = " . " + scopePrefix ( var ) + var - > getDataRef ( ) - > symbol . getName ( ) + " = & " + scopePrefix ( var ) + var - > getDataRef ( ) - > symbol . getName ( ) ;
}
output . preValue + = " }; \n " ;
output + = " ( " + ValueTypeToCType ( data . valueType , " " ) + " ){(void*) " + funcName + " , & " + tmpStruct + " } " ;
2015-06-25 04:09:19 -04:00
} else {
output + = " ( " + ValueTypeToCType ( data . valueType , " " ) + " ){ " + funcName + " , NULL} " ;
}
2015-05-30 04:43:01 -04:00
} else {
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-12 14:16:28 -04:00
output = " \n " + ValueTypeToCType ( data . valueType - > returnType , ( ( data . symbol . getName ( ) = = " main " ) ? " " : function_header + scopePrefix ( from ) ) +
2015-06-25 04:09:19 -04:00
CifyName ( data . symbol . getName ( ) + nameDecoration ) ) + " ( " + parameters + " ) { \n " + generate ( children [ children . size ( ) - 1 ] , enclosingObject , justFuncName , from ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = " } \n " ;
}
distructDoubleStack . pop_back ( ) ;
2013-11-01 02:52:18 -04:00
return output ;
2014-03-06 13:13:40 -05:00
}
2013-11-01 02:52:18 -04:00
case code_block :
2014-06-28 08:31:33 -07:00
{
2013-11-07 22:19:33 -05:00
output + = " { \n " ;
2014-06-28 08:31:33 -07:00
tabLevel + + ;
2015-05-30 04:43:01 -04: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-15 15:19:55 -04:00
// 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 + + )
2015-06-25 04:09:19 -04:00
output + = generate ( children [ i ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-15 15:19:55 -04:00
// we pop off the vector and go through them in reverse emitting them
for ( auto iter = deferDoubleStack . back ( ) . rbegin ( ) ; iter ! = deferDoubleStack . back ( ) . rend ( ) ; iter + + )
2015-06-25 04:09:19 -04:00
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-15 15:19:55 -04:00
deferDoubleStack . pop_back ( ) ;
2015-05-30 04:43:01 -04:00
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
distructDoubleStack . pop_back ( ) ;
2014-06-28 08:31:33 -07:00
tabLevel - - ;
2013-11-01 02:52:18 -04:00
output + = tabs ( ) + " } " ;
2015-05-30 04:43:01 -04:00
2013-11-01 02:52:18 -04:00
return output ;
2014-06-28 08:31:33 -07:00
}
case expression :
2013-11-01 02:52:18 -04:00
output + = " " + data . symbol . getName ( ) + " , " ;
case boolean_expression :
output + = " " + data . symbol . getName ( ) + " " ;
case statement :
2015-05-30 04:43:01 -04:00
{
2015-06-25 04:09:19 -04:00
CCodeTriple stat = generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) ;
2015-05-30 04:43:01 -04:00
return tabs ( ) + stat . preValue + stat . value + " ; \ n " + stat.postValue ;
}
2013-11-01 02:52:18 -04:00
case if_statement :
2015-06-25 04:09:19 -04:00
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 ) {
std : : cout < < " Then statement is a block, emitting the block not the statement so no trailing semicolon " < < std : : endl ;
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-03-16 05:59:56 -04:00
std : : cout < < " Then statement is a simple statement, regular emitting the statement so trailing semicolon " < < std : : endl ;
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
2013-11-01 02:52:18 -04:00
if ( children . size ( ) > 2 )
2015-06-25 04:09:19 -04:00
output + = " else { " + generate ( children [ 2 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " } " ;
2013-11-01 02:52:18 -04:00
return output ;
2013-12-18 18:05:21 -06:00
case while_loop :
2015-05-30 04:43:01 -04: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 > * > ( ) ) ;
2015-05-15 15:19:55 -04:00
// 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 ( ) ) ;
2015-06-25 04:09:19 -04:00
output + = " while ( " + generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) + " ) { \n \t " ;
output + = generate ( children [ 1 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = + " } " ;
distructDoubleStack . pop_back ( ) ;
loopDistructStackDepth . pop ( ) ;
2015-05-15 15:19:55 -04:00
// and pop it off again
loopDeferStackDepth . pop ( ) ;
2013-12-18 18:05:21 -06:00
return output ;
case for_loop :
2015-05-30 04:43:01 -04: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 > * > ( ) ) ;
2015-05-15 15:19:55 -04:00
// 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 ( ) ) ;
2013-12-28 21:54:22 -05:00
//The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s)
2015-06-25 04:09:19 -04:00
output + = " for ( " + strSlice ( generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) , 0 , - 3 ) + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) + " ; " + strSlice ( generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) , 0 , - 3 ) + " ) " ;
output + = " { \n \t " + generate ( children [ 3 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
output + = emitDestructors ( reverse ( distructDoubleStack . back ( ) ) , enclosingObject ) ;
output + = + " } " ;
distructDoubleStack . pop_back ( ) ;
loopDistructStackDepth . pop ( ) ;
2015-05-15 15:19:55 -04:00
// and pop it off again
loopDeferStackDepth . pop ( ) ;
2013-12-18 18:05:21 -06:00
return output ;
2013-11-01 02:52:18 -04:00
case return_statement :
2015-05-30 04:43:01 -04:00
{
2015-05-15 15:19:55 -04: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 + + )
2015-06-25 04:09:19 -04:00
output + = generate ( * iter , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2015-05-30 04:43:01 -04:00
std : : string destructors = emitDestructors ( reverse ( flatten ( distructDoubleStack ) ) , enclosingObject ) ;
if ( children . size ( ) ) {
2015-06-25 04:09:19 -04:00
CCodeTriple expr = generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) ;
2015-05-30 04:43:01 -04:00
output . preValue + = expr . preValue ;
std : : string retTemp = " ret_temp " + getID ( ) ;
output . preValue + = ValueTypeToCType ( children [ 0 ] - > getDataRef ( ) - > valueType , retTemp ) + " ; \n " ;
2015-06-05 00:34:24 -04:00
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 ( ) } ) ;
2015-05-30 04:43:01 -04:00
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-15 15:19:55 -04:00
case break_statement :
// 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 " ;
case continue_statement :
// 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 " ;
case defer_statement :
deferDoubleStack . back ( ) . push_back ( children [ 0 ] ) ;
2015-06-25 04:09:19 -04:00
return CCodeTriple ( " /*defer " + generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " */ " ) ;
2013-11-01 02:52:18 -04:00
case assignment_statement :
2015-06-25 04:09:19 -04:00
return generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " = " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) ;
2013-11-01 02:52:18 -04:00
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 ] ) ;
2014-01-07 13:14:58 -05:00
if ( children . size ( ) = = 1 )
2015-06-25 04:09:19 -04:00
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType , generate ( children [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ) + " ; " ;
2014-06-26 01:45:44 -07:00
else if ( children [ 1 ] - > getChildren ( ) . size ( ) & & children [ 1 ] - > getChildren ( ) [ 0 ] - > getChildren ( ) . size ( ) > 1
& & children [ 1 ] - > getChildren ( ) [ 0 ] - > getChildren ( ) [ 1 ] = = children [ 0 ] ) {
//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 ( ) ;
output . value + = ValueTypeToCType ( children [ 1 ] - > getData ( ) . valueType , toAssignTemp ) + " = " + toAssign . value + " ; \n " ;
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-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 ) + " ; " ;
2015-05-30 04:43:01 -04:00
}
}
2013-12-22 01:34:59 -06:00
case if_comp :
2015-04-04 01:32:40 -04:00
// Lol, this doesn't work because the string gets prefixed now
2015-06-25 04:09:19 -04:00
//if (generate(children[0], enclosingObject, enclosingFunction) == generatorString)
2015-04-04 01:32:40 -04:00
if ( children [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) = = generatorString )
2015-06-25 04:09:19 -04:00
return generate ( children [ 1 ] , enclosingObject , justFuncName , enclosingFunction ) ;
2015-05-30 04:43:01 -04:00
return CCodeTriple ( " " ) ;
2013-12-22 01:34:59 -06:00
case simple_passthrough :
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 ( ) ;
if ( in_or_out - > getDataRef ( ) - > type = = in_passthrough_params )
2015-06-19 13:28:02 -04:00
if ( assignChildren . size ( ) = = 2 )
2015-06-25 04:09:19 -04:00
pre_passthrough + = ValueTypeToCType ( assignChildren [ 0 ] - > getDataRef ( ) - > valueType , assignChildren [ 1 ] - > getDataRef ( ) - > symbol . getName ( ) ) + " = " + generate ( assignChildren [ 0 ] , enclosingObject , enclosingFunction ) . oneString ( ) + " ; \n " ;
2015-06-19 13:28:02 -04:00
else
2015-06-25 04:09:19 -04:00
pre_passthrough + = ValueTypeToCType ( assignChildren [ 0 ] - > getDataRef ( ) - > valueType , assignChildren [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) ) + " = " + generate ( assignChildren [ 0 ] , enclosingObject , enclosingFunction ) . oneString ( ) + " ; \n " ;
2015-04-10 00:37:31 -04:00
else if ( in_or_out - > getDataRef ( ) - > type = = out_passthrough_params )
2015-06-19 13:28:02 -04:00
if ( assignChildren . size ( ) = = 2 )
2015-06-25 04:09:19 -04:00
post_passthrough + = generate ( assignChildren [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " = " + assignChildren [ 1 ] - > getDataRef ( ) - > symbol . getName ( ) + " ; \n " ;
2015-06-19 13:28:02 -04:00
else
2015-06-25 04:09:19 -04:00
post_passthrough + = generate ( assignChildren [ 0 ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) + " = " + assignChildren [ 0 ] - > getDataRef ( ) - > symbol . getName ( ) + " ; \n " ;
2015-04-10 00:37:31 -04:00
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-06-25 04:09:19 -04:00
//return pre_passthrough + strSlice(generate(children.back(, enclosingFunction), enclosingObject, justFuncName).oneString(), 3, -4) + post_passthrough;
2015-06-19 12:06:27 -04:00
return pre_passthrough + strSlice ( children . back ( ) - > getDataRef ( ) - > symbol . getName ( ) , 3 , - 4 ) + post_passthrough ;
2015-04-10 00:37:31 -04:00
}
2013-11-01 02:52:18 -04:00
case function_call :
{
2013-12-27 13:05:07 -06:00
//NOTE: The first (0th) child of a function call node is the declaration of the function
2013-11-01 02:52:18 -04:00
//Handle operators specially for now. Will later replace with
//Inlined functions in the standard library
2014-02-03 11:41:25 -05:00
// 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
// 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-19 17:13:06 -04:00
//std::cout << "Doing function: " << name << std::endl;
2015-05-27 12:27:50 -04:00
//Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer
2014-02-03 11:41:25 -05:00
if ( funcType = = function ) {
if ( name = = " ++ " | | name = = " -- " )
2015-06-25 04:09:19 -04:00
return generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + name ;
2015-03-24 15:47:08 -04:00
if ( ( name = = " * " | | name = = " & " | | name = = " ! " | | name = = " - " | | name = = " + " ) & & children . size ( ) = = 2 ) //Is dereference, not multiplication, address-of, or other unary operator
2015-06-25 04:09:19 -04:00
return name + " ( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " ;
2014-05-06 13:54:53 -04:00
if ( name = = " [] " )
2015-06-25 04:09:19 -04:00
return " ( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " )[ " + generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) + " ] " ;
2014-02-03 11:41:25 -05:00
if ( name = = " + " | | name = = " - " | | name = = " * " | | name = = " / " | | name = = " == " | | name = = " >= " | | name = = " <= " | | name = = " != "
2015-06-01 01:43:23 -04:00
| | name = = " < " | | name = = " > " | | name = = " % " | | name = = " = " | | name = = " += " | | name = = " -= " | | name = = " *= " | | name = = " /= " | | name = = " || "
2015-03-16 06:24:59 -04:00
| | name = = " && " ) {
2015-06-25 04:09:19 -04:00
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + " ( " + generate ( children [ 2 ] , enclosingObject , true , enclosingFunction ) + " )) " ;
2015-03-16 06:24:59 -04:00
} else if ( name = = " . " | | name = = " -> " ) {
2014-02-03 11:41:25 -05:00
if ( children . size ( ) = = 1 )
2015-06-25 04:09:19 -04:00
return " /*dot operation with one child*/ " + generate ( children [ 0 ] , enclosingObject , true , enclosingFunction ) . oneString ( ) + " /*end one child*/ " ;
2014-02-18 21:55:00 -05:00
//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
2014-06-10 23:59:39 -07:00
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 ;
std : : vector < NodeTree < ASTData > * > functionDefChildren = children [ 2 ] - > getChildren ( ) ; //The function def is the rhs of the access operation
std : : cout < < " Decorating (in access-should be object) " < < name < < " " < < functionDefChildren . size ( ) < < std : : endl ;
for ( int i = 0 ; i < ( functionDefChildren . size ( ) > 0 ? functionDefChildren . size ( ) - 1 : 0 ) ; i + + )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( functionDefChildren [ i ] - > getData ( ) . valueType ) ;
2015-04-04 01:32:40 -04:00
// Note that we only add scoping to the object, as this specifies our member function too
2015-06-12 14:16:28 -04:00
/*HERE*/ return function_header + 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 ) + " , " ;
2014-06-10 23:59:39 -07: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 ;
2015-06-25 04:09:19 -04:00
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + functionName + " ) " ;
2014-06-10 23:59:39 -07:00
}
} else {
std : : cout < < " Is not in scope or not type " < < std : : endl ;
2015-06-25 04:09:19 -04:00
return " (( " + generate ( children [ 1 ] , enclosingObject , true , enclosingFunction ) + " ) " + name + functionName + " ) " ;
2014-02-18 21:55:00 -05:00
}
} else {
2015-06-25 04:09:19 -04: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 ) + " ) " ;
2014-02-18 21:55:00 -05:00
}
} else {
2014-03-07 14:17:07 -05:00
//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 ;
for ( int i = 0 ; i < ( functionDefChildren . size ( ) > 0 ? functionDefChildren . size ( ) - 1 : 0 ) ; i + + )
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( functionDefChildren [ i ] - > getData ( ) . valueType ) ;
2014-03-08 16:13:09 -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 ] ) ;
2015-04-04 01:32:40 -04:00
if ( isSelfObjectMethod ) {
2015-06-12 14:16:28 -04:00
output + = function_header + scopePrefix ( children [ 0 ] ) + CifyName ( enclosingObject - > getDataRef ( ) - > symbol . getName ( ) ) + " __ " ;
2015-04-04 01:32:40 -04:00
output + = CifyName ( name + nameDecoration ) + " ( " ;
2014-06-26 01:45:44 -07:00
output + = children . size ( ) > 1 ? " this, " : " this " ;
2015-04-04 01:32:40 -04:00
} else {
2015-06-12 14:16:28 -04:00
output + = function_header + scopePrefix ( children [ 0 ] ) + CifyName ( name + nameDecoration ) + " ( " ;
2015-04-04 01:32:40 -04:00
}
2014-02-03 11:41:25 -05:00
}
} else {
2014-03-07 14:17:07 -05:00
//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.
2015-06-25 04:09:19 -04:00
//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 ) ;
2015-06-14 18:13:52 -04:00
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 ) ;
2015-06-25 04:09:19 -04:00
else {
doClosureInstead = true ;
}
2014-02-03 11:41:25 -05:00
}
2015-06-25 04:09:19 -04:00
CCodeTriple parameters ;
2015-05-30 04:43:01 -04:00
// see if we should copy_construct all the parameters
for ( int i = 1 ; i < children . size ( ) ; i + + ) { //children[0] is the declaration
2015-06-05 00:34:24 -04:00
if ( methodExists ( children [ i ] - > getDataRef ( ) - > valueType , " copy_construct " , std : : vector < Type > { children [ i ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) ) {
2015-05-30 04:43:01 -04:00
std : : string tmpParamName = " param " + getID ( ) ;
2015-06-25 04:09:19 -04:00
CCodeTriple paramValue = generate ( children [ i ] , enclosingObject , true , enclosingFunction ) ;
parameters . preValue + = paramValue . preValue ;
parameters . preValue + = ValueTypeToCType ( children [ i ] - > getDataRef ( ) - > valueType , tmpParamName ) + " ; \n " ;
parameters . preValue + = generateMethodIfExists ( children [ i ] - > getDataRef ( ) - > valueType , " copy_construct " , " & " + tmpParamName + " , & " + paramValue . value , std : : vector < Type > { children [ i ] - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) } ) ;
parameters . value + = tmpParamName ;
parameters . postValue + = paramValue . postValue ;
2015-05-30 04:43:01 -04:00
} else {
2015-06-25 04:09:19 -04:00
parameters + = generate ( children [ i ] , enclosingObject , true , enclosingFunction ) ;
2015-05-30 04:43:01 -04:00
}
2013-11-01 02:52:18 -04:00
if ( i < children . size ( ) - 1 )
2015-06-25 04:09:19 -04:00
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 + " .val) { " + ( doRet ? ( retTmpName + " = " ) : " " ) + " (( " + ValueTypeToCTypeDecoration ( funcType , ClosureFunctionPointerTypeWithClosedParam ) + " ) ( " + tmpName + " .func))( " + tmpName + " .val " + ( children . size ( ) > 1 ? " , " : " " ) + parameters . value + " ); } \n "
+ " else { " + ( doRet ? ( retTmpName + " = " ) : " " ) + tmpName + " .func( " + parameters . value + " ); } \n " ,
( doRet ? retTmpName : " " ) ,
parameters . postValue + functionCallSource . postValue ) ;
} else {
output + = parameters + " ) " ;
2015-05-30 04:43:01 -04:00
}
// see if we should add a destructer call to this postValue
Type * retType = children [ 0 ] - > getDataRef ( ) - > valueType - > returnType ;
2015-06-05 00:34:24 -04:00
if ( methodExists ( retType , " destruct " , std : : vector < Type > ( ) ) ) {
2015-05-30 04:43:01 -04:00
std : : string retTempName = " return_temp " + getID ( ) ;
output . preValue + = ValueTypeToCType ( retType , retTempName ) + " = " + output . value + " ; \n " ;
output . value = retTempName ;
2015-06-05 00:34:24 -04:00
output . postValue = generateMethodIfExists ( retType , " destruct " , " & " + retTempName , std : : vector < Type > ( ) ) + " ; \n " + output . postValue ;
2015-05-30 04:43:01 -04:00
}
2013-11-01 02:52:18 -04:00
return output ;
}
case value :
2015-06-19 12:06:27 -04:00
{
// ok, we now check for it being a string and escape all returns if it is (so that multiline strings work)
if ( data . symbol . getName ( ) [ 0 ] = = ' " ' ) {
std : : string innerString = strSlice ( data . symbol . getName ( ) , 0 , 3 ) = = " \" \" \" "
? strSlice ( data . symbol . getName ( ) , 3 , - 4 )
: strSlice ( data . symbol . getName ( ) , 1 , - 2 ) ;
std : : string newStr ;
for ( auto character : innerString )
if ( character = = ' \n ' )
newStr + = " \\ n " ;
else if ( character = = ' " ' )
newStr + = " \\ \" " ;
else
newStr + = character ;
return " \" " + newStr + " \" " ;
}
2013-11-01 02:52:18 -04:00
return data . symbol . getName ( ) ;
2015-06-19 12:06:27 -04:00
}
2013-11-01 02:52:18 -04:00
default :
std : : cout < < " Nothing! " < < std : : endl ;
}
for ( int i = 0 ; i < children . size ( ) ; i + + )
2015-06-25 04:09:19 -04:00
output + = generate ( children [ i ] , enclosingObject , justFuncName , enclosingFunction ) . oneString ( ) ;
2014-02-03 11:41:25 -05:00
return output ;
}
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 > * > ( ) ) ;
2014-02-03 11:41:25 -05:00
ASTData data = from - > getData ( ) ;
2014-02-18 21:55:00 -05:00
Type enclosingObjectType = * ( enclosingObject - > getDataRef ( ) - > valueType ) ; //Copy a new type so we can turn it into a pointer if we need to
2014-05-19 20:00:35 -04:00
enclosingObjectType . increaseIndirection ( ) ;
2014-02-03 11:41:25 -05:00
std : : vector < NodeTree < ASTData > * > children = from - > getChildren ( ) ;
2014-03-07 14:17:07 -05:00
std : : string nameDecoration , parameters ;
for ( int i = 0 ; i < children . size ( ) - 1 ; i + + ) {
2015-05-30 04:43:01 -04:00
parameters + = " , " + ValueTypeToCType ( children [ i ] - > getData ( ) . valueType , generate ( children [ i ] ) . oneString ( ) ) ;
2014-03-07 14:17:07 -05:00
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( children [ i ] - > getData ( ) . valueType ) ;
2015-06-01 01:43:23 -04:00
distructDoubleStack . back ( ) . push_back ( children [ i ] ) ;
2014-03-07 14:17:07 -05:00
}
2015-06-12 14:16:28 -04:00
std : : string functionSignature = " \n " + ValueTypeToCType ( data . valueType - > returnType , function_header + scopePrefix ( from ) + CifyName ( enclosingObject - > getDataRef ( ) - > symbol . getName ( ) ) + " __ "
2015-05-18 04:46:03 -04: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 ;
output + = functionSignature + " { \n " + generate ( children [ children . size ( ) - 1 ] , enclosingObject ) . oneString ( ) ;
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 + + ) {
if ( types [ i ] ! = methodTypes [ i ] ) {
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-06-12 14:16:28 -04:00
return function_header + scopePrefix ( typeDefinition ) + CifyName ( typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ) + " __ " + 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-06-05 00:34:24 -04:00
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 ) {
auto tmp = var - > getDataRef ( ) - > valueType - > withIncreasedIndirection ( ) ;
typedefString + = ValueTypeToCType ( & tmp , scopePrefix ( var ) + var - > getDataRef ( ) - > symbol . getName ( ) ) + " ; " ;
}
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 ) {
2014-03-06 13:13:40 -05:00
std : : string return_type ;
2015-05-18 04:46:03 -04:00
bool do_ending = true ;
2014-03-06 13:13:40 -05:00
switch ( type - > baseType ) {
case none :
if ( type - > typeDefinition )
2015-04-04 01:32:40 -04:00
return_type = scopePrefix ( type - > typeDefinition ) + CifyName ( type - > typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ) ;
2014-03-06 13:13:40 -05:00
else
return_type = " none " ;
break ;
2015-05-18 04:46:03 -04:00
case function_type :
{
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 ;
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 ) ) ;
std : : string typedefStructStr = " typedef struct { " + typedefWithoutVoidID + " func; void* val; } " + typedefStructID + " ; \n " ;
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 " ;
functionTypedefString + = typedefWithoutVoidStr ;
functionTypedefString + = typedefWithVoidStr ;
functionTypedefString + = typedefStructStr ;
if ( closureSpecial = = ClosureFunctionPointerTypeWithClosedParam )
return_type = typedefWithVoidID + indr_str + declaration ;
else
return_type = typedefStructID + indr_str + declaration ;
functionTypedefMap [ * type ] = std : : make_pair ( typedefStructID , typedefWithVoidID ) ;
}
2015-05-18 04:46:03 -04:00
do_ending = false ;
}
break ;
2014-03-06 13:13:40 -05:00
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 ;
2014-05-19 20:00:35 -04:00
for ( int i = 0 ; i < type - > getIndirection ( ) ; i + + )
2015-05-18 04:46:03 -04:00
return_type + = " * " ;
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 ) {
2014-03-14 15:55:45 -04:00
std : : string operatorsToReplace [ ] = { " + " , " plus " ,
" - " , " minus " ,
" * " , " star " ,
" / " , " div " ,
" % " , " mod " ,
" ^ " , " carat " ,
" & " , " amprsd " ,
" | " , " pipe " ,
" ~ " , " tilde " ,
2015-06-08 21:47:02 -04:00
" ! " , " exlmtnpt " ,
2014-03-14 15:55:45 -04:00
" , " , " comma " ,
2015-06-08 21:47:02 -04:00
" = " , " eq " ,
" ++ " , " dbplus " ,
" -- " , " dbminus " ,
" << " , " dbleft " ,
" >> " , " dbright " ,
2014-12-30 01:22:09 -05:00
" :: " , " scopeop " ,
2015-05-18 04:46:03 -04:00
" : " , " colon " ,
2015-06-08 21:47:02 -04:00
" == " , " dbq " ,
2014-03-14 15:55:45 -04:00
" != " , " notequals " ,
" && " , " doubleamprsnd " ,
" || " , " doublepipe " ,
" += " , " plusequals " ,
" -= " , " minusequals " ,
" /= " , " divequals " ,
" %= " , " modequals " ,
" ^= " , " caratequals " ,
" &= " , " amprsdequals " ,
" |= " , " pipeequals " ,
" *= " , " starequals " ,
" <<= " , " doublerightequals " ,
2015-06-08 21:47:02 -04:00
" < " , " lt " ,
" > " , " gt " ,
2014-03-14 15:55:45 -04:00
" >>= " , " doubleleftequals " ,
2014-07-18 08:52:15 -07:00
" ( " , " openparen " ,
" ) " , " closeparen " ,
2015-06-08 21:47:02 -04:00
" [ " , " obk " ,
" ] " , " cbk " ,
2014-07-18 08:52:15 -07:00
" " , " space " ,
2015-03-11 01:58:10 -04:00
" . " , " dot " ,
2014-03-14 15:55:45 -04:00
" -> " , " 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 ;
}
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 ] ) ;
}
2014-03-14 15:55:45 -04:00