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
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 " ;
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 :
{
if ( decChildren . size ( ) = = 0 ) { //Not a real function, must be a built in passthrough {
output + = " /* built in function: " + declarationData . toString ( ) + " */ \n " ;
break ;
}
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 ) ;
2014-03-07 14:17:07 -05:00
nameDecoration + = " _ " + ValueTypeToCTypeDecoration ( decChildren [ j ] - > getData ( ) . valueType ) ;
2014-03-06 13:13:40 -05:00
}
2014-03-07 14:17:07 -05:00
output + = declarationData . symbol . getName ( ) + nameDecoration + " ( " + parameters + " ); /*func*/ \n " ;
2014-02-03 11:41:25 -05: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 ;
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
{
//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 self 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 ( ) )
preName + = " self-> " ;
if ( false )
for ( int j = 0 ; j < children . size ( ) - 1 ; j + + )
preName + = ValueTypeToCType ( children [ j ] - > getData ( ) . valueType ) + " _ " ;
2014-03-08 16:13:09 -05:00
return preName + data . symbol . getName ( ) ;
2014-02-03 11:41:25 -05:00
}
2014-01-07 13:14:58 -05:00
case type_def :
2014-01-19 18:20:52 -05:00
if ( children . size ( ) = = 0 ) {
return " typedef " + ValueTypeToCType ( data . valueType ) + " " + data . symbol . getName ( ) + " ; " ;
} else {
std : : string objectString = " typedef struct __struct_dummy_ " + data . symbol . getName ( ) + " __ { \n " ;
2014-02-03 11:41:25 -05:00
std : : string postString ; //The functions have to be outside the struct definition
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
objectString + = generate ( children [ i ] , enclosingObject ) + " \n " ;
}
2014-01-19 18:20:52 -05:00
objectString + = " } " + 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
{
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-03-07 14:17:07 -05:00
output + = 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 :
2013-11-07 22:19:33 -05:00
output + = " { \n " ;
2013-11-01 02:52:18 -04:00
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 ;
}
2013-11-01 02:52:18 -04:00
tabLevel - - ;
output + = tabs ( ) + " } " ;
return output ;
case expression :
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-01-07 13:14:58 -05:00
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 ;
if ( name = = " * " & & children . size ( ) = = 2 ) //Is dereference, not multiplication
return " *( " + generate ( children [ 1 ] , enclosingObject ) + " ) " ;
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
if ( possibleObjectType & & possibleObjectType - > getDataRef ( ) - > scope . find ( functionName ) ! = possibleObjectType - > getDataRef ( ) - > scope . end ( ) ) {
2014-03-07 14:17:07 -05:00
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 possibleObjectType - > getDataRef ( ) - > symbol . getName ( ) + " __ " + functionName + nameDecoration + " ( " + ( name = = " . " ? " & " : " " ) + generate ( children [ 1 ] , enclosingObject ) + " , " ;
2014-02-18 21:55:00 -05:00
//The comma lets the upper function call know we already started the param list
2014-03-06 13:13:40 -05:00
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
2014-02-18 21:55:00 -05:00
} else {
std : : cout < < " Is not in scope or not type " < < std : : endl ;
2014-03-07 14:17:07 -05:00
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-03-07 14:17:07 -05:00
/*HERE*/ output + = name + nameDecoration + " ( " ;
2014-03-08 16:13:09 -05:00
if ( isSelfObjectMethod )
output + = children . size ( ) > 1 ? " self, " : " self " ;
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 ;
}
2013-11-01 02:52:18 -04:00
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-02-03 11:41:25 -05:00
enclosingObjectType . indirection + + ;
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-03-08 16:13:09 -05:00
output + = " \n " + ValueTypeToCType ( data . valueType ) + " " + enclosingObject - > getDataRef ( ) - > symbol . getName ( ) + " __ "
2014-03-07 14:17:07 -05:00
+ data . symbol . getName ( ) + nameDecoration + " ( " + ValueTypeToCType ( & enclosingObjectType ) + " self " + parameters + " ) \n "
+ generate ( children [ children . size ( ) - 1 ] , enclosingObject ) ; //Pass in the object so we can
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 )
return_type = type - > typeDefinition - > getDataRef ( ) - > symbol . getName ( ) ;
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-01-07 13:14:58 -05:00
for ( int i = 0 ; i < type - > indirection ; 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 ;
}
for ( int i = 0 ; i < type - > indirection ; i + + )
return_type + = " _P__ " ;
return return_type ;
}
2014-03-07 14:17:07 -05:00