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 ;
}
CGenerator : : ~ CGenerator ( ) {
}
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
std : : string buildString = " #!/bin/sh \n cc -std=c99 " ;
for ( auto i = ASTs . begin ( ) ; i ! = ASTs . end ( ) ; i + + ) {
buildString + = i - > first + " .c " ;
std : : ofstream outputCFile ;
outputCFile . open ( i - > first + " .c " ) ;
if ( outputCFile . is_open ( ) ) {
outputCFile < < generate ( i - > second ) ;
} else {
std : : cout < < " Cannot open file " < < i - > first < < " .c " < < std : : endl ;
}
outputCFile . close ( ) ;
}
buildString + = " -o " + outputName ;
std : : ofstream outputBuild ;
outputBuild . open ( outputName + " .sh " ) ;
outputBuild < < buildString ;
outputBuild . close ( ) ;
}
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 ;
}
2014-02-03 11:41:25 -05:00
//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
std : : string CGenerator : : generate ( NodeTree < ASTData > * from , NodeTree < ASTData > * enclosingObject ) {
2013-11-01 02:52:18 -04:00
ASTData data = from - > getData ( ) ;
std : : vector < NodeTree < ASTData > * > children = from - > getChildren ( ) ;
2014-02-03 11:41:25 -05:00
std : : string output = " " ;
2013-11-01 02:52:18 -04:00
switch ( data . type ) {
case translation_unit :
2014-01-07 13:14:58 -05:00
//Do here because we may need the typedefs before the declarations of variables
2014-05-21 12:01:45 -04:00
//Note that we need to be careful of the order, though, as some declarations depend on others.
//What is this then? It's a poset! Wooo posets!
2014-05-21 13:14:16 -04:00
{
Poset < NodeTree < ASTData > * > typedefPoset ;
for ( int i = 0 ; i < children . size ( ) ; i + + ) {
if ( children [ i ] - > getDataRef ( ) - > type = = type_def ) {
2014-06-26 01:45:44 -07:00
typedefPoset . addVertex ( children [ i ] ) ; //We add this definition by itthis just in case there are no dependencies.
2014-05-21 13:14:16 -04:00
//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-07-18 08:52:15 -07:00
//In case there are pointer dependencies. We don't do this if this is an alias type
if ( children [ i ] - > getDataRef ( ) - > valueType - > typeDefinition = = children [ i ] )
2014-05-21 13:14:16 -04:00
output + = " struct " + CifyName ( children [ i ] - > getDataRef ( ) - > symbol . getName ( ) ) + " ; \n " ;
2014-06-10 23:59:39 -07:00
else {
Type * aliasType = children [ i ] - > getDataRef ( ) - > valueType ;
2014-07-18 08:52:15 -07:00
if ( aliasType - > typeDefinition & & ! aliasType - > templateDefinition ) //Isn't uninstantiated template or 0 parameter class, so must be alias. if typeDefinition isn't null, then it's an alias of a custom, not a primitive, type.
2014-06-10 23:59:39 -07:00
typedefPoset . addRelationship ( children [ i ] , children [ i ] - > getDataRef ( ) - > valueType - > typeDefinition ) ; //An alias typedef depends on the type it aliases being declared before it
}
}
2014-05-21 13:14:16 -04:00
}
//Now generate the typedef's in the correct, topological order
for ( NodeTree < ASTData > * i : typedefPoset . getTopoSort ( ) )
output + = generate ( i , enclosingObject ) + " \n " ;
2013-12-27 13:05:07 -06:00
//Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations)
for ( auto i = data . scope . begin ( ) ; i ! = data . scope . end ( ) ; i + + ) {
2014-03-06 13:13:40 -05:00
for ( auto overloadedMembers : i - > second ) {
NodeTree < ASTData > * declaration = overloadedMembers ;
std : : vector < NodeTree < ASTData > * > decChildren = declaration - > getChildren ( ) ;
ASTData declarationData = declaration - > getData ( ) ;
switch ( declarationData . type ) {
case identifier :
output + = ValueTypeToCType ( declarationData . valueType ) + " " + declarationData . symbol . getName ( ) + " ; /*identifier*/ \n " ;
break ;
case function :
{
2014-06-10 00:53:30 -07:00
if ( declarationData . valueType - > baseType = = template_type )
2014-05-19 20:00:35 -04:00
output + = " /* template function " + declarationData . symbol . toString ( ) + " */ \n " ;
else if ( decChildren . size ( ) = = 0 ) //Not a real function, must be a built in passthrough
output + = " /* built in function: " + declarationData . symbol . toString ( ) + " */ \n " ;
else {
output + = " \n " + ValueTypeToCType ( declarationData . valueType ) + " " ;
std : : string nameDecoration , parameters ;
for ( int j = 0 ; j < decChildren . size ( ) - 1 ; j + + ) {
if ( j > 0 )
parameters + = " , " ;
parameters + = ValueTypeToCType ( decChildren [ j ] - > getData ( ) . valueType ) + " " + generate ( decChildren [ j ] , enclosingObject ) ;
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( decChildren [ j ] - > getData ( ) . valueType ) ;
}
2014-06-10 00:53:30 -07:00
output + = CifyName ( declarationData . symbol . getName ( ) + nameDecoration ) + " ( " + parameters + " ); /*func*/ \n " ;
2014-03-06 13:13:40 -05:00
}
2014-02-03 11:41:25 -05:00
}
2014-05-19 20:00:35 -04:00
break ;
2014-03-06 13:13:40 -05:00
case type_def :
//type
output + = " /*typedef " + declarationData . symbol . getName ( ) + " */ \n " ;
break ;
default :
//std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl;
output + = " /*unknown declaration named " + declaration - > getName ( ) + " */ \n " ;
}
2013-12-27 13:05:07 -06:00
}
}
2014-01-07 13:14:58 -05:00
//Do here because we need the newlines
for ( int i = 0 ; i < children . size ( ) ; i + + )
if ( children [ i ] - > getDataRef ( ) - > type ! = type_def )
2014-02-03 11:41:25 -05:00
output + = generate ( children [ i ] , enclosingObject ) + " \n " ;
2014-01-07 13:14:58 -05:00
return output ;
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 :
2013-12-22 01:34:59 -06:00
return " /* would import \" " + data . symbol . getName ( ) + " \" but....*/ \n " ;
//return "#include <" + data.symbol.getName() + ">\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)
if ( data . symbol . getName ( ) = = " this " )
if ( enclosingObject )
return " this " ;
else
std : : cout < < " Error: this used in non-object scope " < < std : : endl ;
//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.
2014-03-06 13:13:40 -05:00
std : : string preName ;
if ( enclosingObject & & enclosingObject - > getDataRef ( ) - > scope . find ( data . symbol . getName ( ) ) ! = enclosingObject - > getDataRef ( ) - > scope . end ( ) )
2014-06-26 01:45:44 -07:00
preName + = " this-> " ;
2014-03-06 13:13:40 -05:00
if ( false )
for ( int j = 0 ; j < children . size ( ) - 1 ; j + + )
preName + = ValueTypeToCType ( children [ j ] - > getData ( ) . valueType ) + " _ " ;
2014-05-10 19:28:36 -04:00
return preName + CifyName ( data . symbol . getName ( ) ) ; //Cifying does nothing if not an operator overload
2014-02-03 11:41:25 -05:00
}
2014-01-07 13:14:58 -05:00
case type_def :
2014-05-10 19:28:36 -04:00
if ( data . valueType - > baseType = = template_type ) {
return " /* non instantiated template " + data . symbol . getName ( ) + " */ " ;
2014-07-18 08:52:15 -07:00
} else if ( data . valueType - > typeDefinition ! = from ) {
2014-01-19 18:20:52 -05:00
return " typedef " + ValueTypeToCType ( data . valueType ) + " " + data . symbol . getName ( ) + " ; " ;
} else {
2014-05-10 19:28:36 -04:00
std : : string objectString = " typedef struct __struct_dummy_ " + CifyName ( data . symbol . getName ( ) ) + " __ { \n " ;
2014-02-03 11:41:25 -05:00
std : : string postString ; //The functions have to be outside the struct definition
2014-05-19 20:00:35 -04:00
tabLevel + + ;
2014-02-03 11:41:25 -05:00
for ( int i = 0 ; i < children . size ( ) ; i + + ) {
std : : cout < < children [ i ] - > getName ( ) < < std : : endl ;
if ( children [ i ] - > getName ( ) = = " function " ) //If object method
postString + = generateObjectMethod ( from , children [ i ] ) + " \n " ;
else
2014-05-19 20:00:35 -04:00
objectString + = tabs ( ) + generate ( children [ i ] , enclosingObject ) + " \n " ;
2014-02-03 11:41:25 -05:00
}
2014-05-19 20:00:35 -04:00
tabLevel - - ;
2014-05-10 19:28:36 -04:00
objectString + = " } " + CifyName ( data . symbol . getName ( ) ) + " ; " ;
2014-02-03 11:41:25 -05:00
return objectString + postString ; //Functions come after the declaration of the struct
2014-01-19 18:20:52 -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 ( ) + " */ " ;
2014-03-06 13:13:40 -05:00
output + = " \n " + ValueTypeToCType ( data . valueType ) + " " ;
std : : string nameDecoration , parameters ;
for ( int j = 0 ; j < children . size ( ) - 1 ; j + + ) {
if ( j > 0 )
parameters + = " , " ;
parameters + = ValueTypeToCType ( children [ j ] - > getData ( ) . valueType ) + " " + generate ( children [ j ] , enclosingObject ) ;
2014-03-07 14:17:07 -05:00
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( children [ j ] - > getData ( ) . valueType ) ;
2013-11-01 02:52:18 -04:00
}
2014-06-10 00:53:30 -07:00
output + = CifyName ( data . symbol . getName ( ) + nameDecoration ) + " ( " + parameters + " ) \n " + generate ( children [ children . size ( ) - 1 ] , enclosingObject ) ;
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
std : : string destructorString = " " ;
tabLevel + + ;
2014-02-03 11:41:25 -05:00
for ( int i = 0 ; i < children . size ( ) ; i + + ) {
2014-03-06 13:13:40 -05:00
//std::cout << "Line " << i << std::endl;
2014-02-03 11:41:25 -05:00
std : : string line = generate ( children [ i ] , enclosingObject ) ;
2014-03-06 13:13:40 -05:00
//std::cout << line << std::endl;
2014-02-03 11:41:25 -05:00
output + = line ;
2014-06-28 08:31:33 -07:00
if ( children [ i ] - > getChildren ( ) . size ( ) & & children [ i ] - > getChildren ( ) [ 0 ] - > getDataRef ( ) - > type = = declaration_statement ) {
NodeTree < ASTData > * identifier = children [ i ] - > getChildren ( ) [ 0 ] - > getChildren ( ) [ 0 ] ;
NodeTree < ASTData > * typeDefinition = identifier - > getDataRef ( ) - > valueType - > typeDefinition ;
if ( ! typeDefinition )
continue ;
if ( typeDefinition - > getDataRef ( ) - > scope . find ( " destruct " ) = = typeDefinition - > getDataRef ( ) - > scope . end ( ) )
continue ;
destructorString + = tabs ( ) + CifyName ( typeDefinition - > getDataRef ( ) - > symbol . getName ( ) )
+ " __ " + " destruct " + " (& " + generate ( identifier , enclosingObject ) + " ); \n " ; //Call the destructor
}
}
output + = destructorString ;
tabLevel - - ;
2013-11-01 02:52:18 -04:00
output + = tabs ( ) + " } " ;
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 :
2014-02-03 11:41:25 -05:00
return tabs ( ) + generate ( children [ 0 ] , enclosingObject ) + " ; \ n " ;
2013-11-01 02:52:18 -04:00
case if_statement :
2014-02-03 11:41:25 -05:00
output + = " if ( " + generate ( children [ 0 ] , enclosingObject ) + " ) \n \t " + generate ( children [ 1 ] , enclosingObject ) ;
2013-11-01 02:52:18 -04:00
if ( children . size ( ) > 2 )
2014-02-03 11:41:25 -05:00
output + = " else " + generate ( children [ 2 ] , enclosingObject ) ;
2013-11-01 02:52:18 -04:00
return output ;
2013-12-18 18:05:21 -06:00
case while_loop :
2014-02-03 11:41:25 -05:00
output + = " while ( " + generate ( children [ 0 ] , enclosingObject ) + " ) \n \t " + generate ( children [ 1 ] , enclosingObject ) ;
2013-12-18 18:05:21 -06:00
return output ;
case for_loop :
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)
2014-02-03 11:41:25 -05:00
output + = " for ( " + strSlice ( generate ( children [ 0 ] , enclosingObject ) , 0 , - 3 ) + generate ( children [ 1 ] , enclosingObject ) + " ; " + strSlice ( generate ( children [ 2 ] , enclosingObject ) , 0 , - 3 ) + " ) \n \t " + generate ( children [ 3 ] , enclosingObject ) ;
2013-12-18 18:05:21 -06:00
return output ;
2013-11-01 02:52:18 -04:00
case return_statement :
2013-12-22 01:34:59 -06:00
if ( children . size ( ) )
2014-02-03 11:41:25 -05:00
return " return " + generate ( children [ 0 ] , enclosingObject ) ;
2013-12-22 01:34:59 -06:00
else
return " return " ;
2013-11-01 02:52:18 -04:00
case assignment_statement :
2014-02-03 11:41:25 -05:00
return generate ( children [ 0 ] , enclosingObject ) + " = " + generate ( children [ 1 ] , enclosingObject ) ;
2013-11-01 02:52:18 -04:00
case declaration_statement :
2014-01-07 13:14:58 -05:00
if ( children . size ( ) = = 1 )
2014-02-03 11:41:25 -05:00
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType ) + " " + generate ( children [ 0 ] , enclosingObject ) + " ; " ;
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])
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType ) + " " + generate ( children [ 0 ] , enclosingObject ) + " ; " + generate(children[1]) + " /*Init Position Call*/ " ;
} else
2014-02-03 11:41:25 -05:00
return ValueTypeToCType ( children [ 0 ] - > getData ( ) . valueType ) + " " + generate ( children [ 0 ] , enclosingObject ) + " = " + generate ( children [ 1 ] , enclosingObject ) + " ; " ;
2013-12-22 01:34:59 -06:00
case if_comp :
2014-02-03 11:41:25 -05:00
if ( generate ( children [ 0 ] , enclosingObject ) = = generatorString )
return generate ( children [ 1 ] , enclosingObject ) ;
2013-12-22 01:34:59 -06:00
return " " ;
case simple_passthrough :
2014-02-03 11:41:25 -05:00
return strSlice ( generate ( children [ 0 ] , enclosingObject ) , 3 , - 4 ) ;
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 ;
std : : cout < < " Doing function: " < < name < < std : : endl ;
//Test for specail 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 ) + name ;
2014-05-19 20:00:35 -04:00
if ( ( name = = " * " | | name = = " & " ) & & children . size ( ) = = 2 ) //Is dereference, not multiplication, or address-of
2014-05-06 13:54:53 -04:00
return name + " ( " + generate ( children [ 1 ] , enclosingObject ) + " ) " ;
if ( name = = " [] " )
return " ( " + generate ( children [ 1 ] , enclosingObject ) + " )[ " + generate ( children [ 2 ] , enclosingObject ) + " ] " ;
2014-02-03 11:41:25 -05:00
if ( name = = " + " | | name = = " - " | | name = = " * " | | name = = " / " | | name = = " == " | | name = = " >= " | | name = = " <= " | | name = = " != "
| | name = = " < " | | name = = " > " | | name = = " % " | | name = = " += " | | name = = " -= " | | name = = " *= " | | name = = " /= " | | name = = " || "
| | name = = " && " | | name = = " ! " )
return " (( " + generate ( children [ 1 ] , enclosingObject ) + " ) " + name + " ( " + generate ( children [ 2 ] , enclosingObject ) + " )) " ;
else if ( name = = " . " | | name = = " -> " ) {
if ( children . size ( ) = = 1 )
return " /*dot operation with one child*/ " + generate ( children [ 0 ] , enclosingObject ) + " /*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 ) ;
/*HERE*/ return CifyName ( unaliasedTypeDef - > getDataRef ( ) - > symbol . getName ( ) ) + " __ " + CifyName ( functionName + nameDecoration ) + " ( " + ( name = = " . " ? " & " : " " ) + generate ( children [ 1 ] , enclosingObject ) + " , " ;
//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 ) + " ) " + name + functionName + " ) " ;
}
} else {
std : : cout < < " Is not in scope or not type " < < std : : endl ;
return " (( " + generate ( children [ 1 ] , enclosingObject ) + " ) " + name + functionName + " ) " ;
2014-02-18 21:55:00 -05:00
}
} else {
2014-03-09 03:13:08 -04:00
//return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")";
return " (( " + generate ( children [ 1 ] , enclosingObject ) + " ) " + name + generate ( children [ 2 ] ) + " ) " ;
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 ] ) ;
if ( isSelfObjectMethod )
output + = enclosingObject - > getDataRef ( ) - > symbol . getName ( ) + " __ " ;
2014-06-10 00:53:30 -07:00
/*HERE*/ output + = CifyName ( name + nameDecoration ) + " ( " ;
2014-03-08 16:13:09 -05:00
if ( isSelfObjectMethod )
2014-06-26 01:45:44 -07:00
output + = children . size ( ) > 1 ? " this, " : " this " ;
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.
2014-02-18 21:55:00 -05:00
std : : string functionCallSource = generate ( children [ 0 ] , enclosingObject ) ;
if ( functionCallSource [ functionCallSource . size ( ) - 1 ] = = ' , ' ) //If it's a member method, it's already started the parameter list.
output + = children . size ( ) > 1 ? functionCallSource : functionCallSource . substr ( 0 , functionCallSource . size ( ) - 1 ) ;
else
output + = functionCallSource + " ( " ;
2014-02-03 11:41:25 -05:00
}
2013-12-27 13:05:07 -06:00
for ( int i = 1 ; i < children . size ( ) ; i + + ) //children[0] is the declaration
2013-11-01 02:52:18 -04:00
if ( i < children . size ( ) - 1 )
2014-02-03 11:41:25 -05:00
output + = generate ( children [ i ] , enclosingObject ) + " , " ;
2014-03-06 13:13:40 -05:00
else
output + = generate ( children [ i ] , enclosingObject ) ;
2013-11-01 02:52:18 -04:00
output + = " ) " ;
return output ;
}
case value :
return data . symbol . getName ( ) ;
default :
std : : cout < < " Nothing! " < < std : : endl ;
}
for ( int i = 0 ; i < children . size ( ) ; i + + )
2014-02-03 11:41:25 -05:00
output + = generate ( children [ i ] , enclosingObject ) ;
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-02-03 11:41:25 -05:00
std : : string CGenerator : : generateObjectMethod ( NodeTree < ASTData > * enclosingObject , NodeTree < ASTData > * from ) {
std : : string output ;
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 + + ) {
parameters + = " , " + ValueTypeToCType ( children [ i ] - > getData ( ) . valueType ) + " " + generate ( children [ i ] ) ;
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( children [ i ] - > getData ( ) . valueType ) ;
}
2014-05-10 19:28:36 -04:00
output + = " \n " + ValueTypeToCType ( data . valueType ) + " " + CifyName ( enclosingObject - > getDataRef ( ) - > symbol . getName ( ) ) + " __ "
+ CifyName ( data . symbol . getName ( ) ) + nameDecoration + " ( " + ValueTypeToCType ( & enclosingObjectType )
2014-06-26 01:45:44 -07:00
+ " this " + parameters + " ) \n " + generate ( children [ children . size ( ) - 1 ] , enclosingObject ) ; //Pass in the object so we can properly handle access to member stuff
2013-11-01 02:52:18 -04:00
return output ;
}
2014-01-07 13:14:58 -05:00
std : : string CGenerator : : ValueTypeToCType ( Type * type ) {
2013-12-23 01:26:24 -06:00
std : : string return_type ;
2014-01-07 13:14:58 -05:00
switch ( type - > baseType ) {
2013-11-01 02:52:18 -04:00
case none :
2014-01-07 13:14:58 -05:00
if ( type - > typeDefinition )
2014-05-10 19:28:36 -04:00
return_type = CifyName ( type - > typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ) ;
2014-01-07 13:14:58 -05:00
else
return_type = " none " ;
2013-12-23 01:26:24 -06:00
break ;
2013-12-22 01:34:59 -06:00
case void_type :
2013-12-23 01:26:24 -06:00
return_type = " void " ;
break ;
2013-11-01 02:52:18 -04:00
case boolean :
2013-12-23 01:26:24 -06:00
return_type = " bool " ;
break ;
2013-11-01 02:52:18 -04:00
case integer :
2013-12-23 01:26:24 -06:00
return_type = " int " ;
2013-11-01 02:52:18 -04:00
break ;
case floating :
2013-12-23 01:26:24 -06:00
return_type = " float " ;
break ;
2013-11-01 02:52:18 -04:00
case double_percision :
2013-12-23 01:26:24 -06:00
return_type = " double " ;
break ;
case character :
return_type = " char " ;
2013-11-01 02:52:18 -04:00
break ;
default :
2013-12-23 01:26:24 -06:00
return_type = " unknown_ValueType " ;
break ;
2013-11-01 02:52:18 -04:00
}
2014-05-19 20:00:35 -04:00
for ( int i = 0 ; i < type - > getIndirection ( ) ; i + + )
2013-12-23 01:26:24 -06:00
return_type + = " * " ;
return return_type ;
2013-11-01 02:52:18 -04:00
}
2014-03-06 13:13:40 -05:00
std : : string CGenerator : : ValueTypeToCTypeDecoration ( Type * type ) {
std : : string return_type ;
switch ( type - > baseType ) {
case none :
if ( type - > typeDefinition )
return_type = type - > typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ;
else
return_type = " none " ;
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 ;
}
2014-05-19 20:00:35 -04:00
for ( int i = 0 ; i < type - > getIndirection ( ) ; i + + )
2014-03-06 13:13:40 -05:00
return_type + = " _P__ " ;
return return_type ;
}
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 " ,
" ! " , " exclamationpt " ,
" , " , " comma " ,
" = " , " equals " ,
" ++ " , " doubleplus " ,
" -- " , " doubleminus " ,
" << " , " doubleleft " ,
" >> " , " doubleright " ,
" == " , " doubleequals " ,
" != " , " notequals " ,
" && " , " doubleamprsnd " ,
" || " , " doublepipe " ,
" += " , " plusequals " ,
" -= " , " minusequals " ,
" /= " , " divequals " ,
" %= " , " modequals " ,
" ^= " , " caratequals " ,
" &= " , " amprsdequals " ,
" |= " , " pipeequals " ,
" *= " , " starequals " ,
" <<= " , " doublerightequals " ,
2014-05-10 19:28:36 -04:00
" < " , " lessthan " ,
" > " , " greaterthan " ,
2014-03-14 15:55:45 -04:00
" >>= " , " doubleleftequals " ,
2014-07-18 08:52:15 -07:00
" ( " , " openparen " ,
" ) " , " closeparen " ,
" [ " , " openbracket " ,
" ] " , " closebracket " ,
" " , " space " ,
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 ;
}