Ok, full functions as values support with types and fixes of earlier bugs. Now typedef the function pointer types when generateing C.
This commit is contained in:
@@ -28,9 +28,9 @@ class CGenerator {
|
|||||||
std::pair<std::string, std::string> generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs);
|
std::pair<std::string, std::string> generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs);
|
||||||
std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL, bool justFuncName = false);
|
std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL, bool justFuncName = false);
|
||||||
std::string generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition);
|
std::string generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition);
|
||||||
static std::string ValueTypeToCType(Type *type, std::string);
|
std::string ValueTypeToCType(Type *type, std::string);
|
||||||
static std::string ValueTypeToCTypeDecoration(Type *type);
|
std::string ValueTypeToCTypeDecoration(Type *type);
|
||||||
static std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);
|
std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);
|
||||||
static std::string CifyName(std::string name);
|
static std::string CifyName(std::string name);
|
||||||
static std::string scopePrefix(NodeTree<ASTData>* from);
|
static std::string scopePrefix(NodeTree<ASTData>* from);
|
||||||
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
||||||
@@ -40,6 +40,7 @@ class CGenerator {
|
|||||||
int tabLevel;
|
int tabLevel;
|
||||||
std::string generatorString;
|
std::string generatorString;
|
||||||
std::string linkerString;
|
std::string linkerString;
|
||||||
|
std::string functionTypedefString;
|
||||||
std::vector<std::vector<NodeTree<ASTData>*>> deferDoubleStack;
|
std::vector<std::vector<NodeTree<ASTData>*>> deferDoubleStack;
|
||||||
std::stack<int> loopDeferStackDepth;
|
std::stack<int> loopDeferStackDepth;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ Goal = translation_unit ;
|
|||||||
translation_unit = WS unorderd_list_part WS ;
|
translation_unit = WS unorderd_list_part WS ;
|
||||||
unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def line_end WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement line_end WS unorderd_list_part | import | function | type_def line_end | if_comp | simple_passthrough | declaration_statement line_end ;
|
unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def line_end WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement line_end WS unorderd_list_part | import | function | type_def line_end | if_comp | simple_passthrough | declaration_statement line_end ;
|
||||||
|
|
||||||
type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst ;
|
type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst | function_type ;
|
||||||
|
function_type = "fun" WS "\(" WS opt_type_list WS "\)" WS ":" WS type ;
|
||||||
dec_type = ":" WS type ;
|
dec_type = ":" WS type ;
|
||||||
|
|
||||||
|
opt_type_list = type_list | ;
|
||||||
template_inst = "<" WS type_list WS ">" ;
|
template_inst = "<" WS type_list WS ">" ;
|
||||||
type_list = type_list WS "," WS type | type ;
|
type_list = type_list WS "," WS type | type ;
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ bool = "true" | "false" ;
|
|||||||
character = "'(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
character = "'(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )'" ;
|
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )'" ;
|
||||||
|
|
||||||
keywords_also_identifiers = "obj" | "def" ;
|
keywords_also_identifiers = "obj" | "def" | "fun" | "var" ;
|
||||||
alpha_alphanumeric = "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_)(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_|0|1|2|3|4|5|6|7|8|9)*" ;
|
alpha_alphanumeric = "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_)(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|_|0|1|2|3|4|5|6|7|8|9)*" ;
|
||||||
augmented_alpha_alphanumeric = alpha_alphanumeric augmented_alpha_alphanumeric | keywords_also_identifiers augmented_alpha_alphanumeric | alpha_alphanumeric | keywords_also_identifiers ;
|
augmented_alpha_alphanumeric = alpha_alphanumeric augmented_alpha_alphanumeric | keywords_also_identifiers augmented_alpha_alphanumeric | alpha_alphanumeric | keywords_also_identifiers ;
|
||||||
|
|
||||||
|
|||||||
@@ -904,29 +904,23 @@ NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, s
|
|||||||
//We're not looking for types
|
//We're not looking for types
|
||||||
if (i->getDataRef()->type == type_def)
|
if (i->getDataRef()->type == type_def)
|
||||||
continue;
|
continue;
|
||||||
|
Type* functionType = i->getDataRef()->valueType;
|
||||||
|
|
||||||
std::vector<NodeTree<ASTData>*> children = i->getChildren();
|
int numTypes = functionType->parameterTypes.size();
|
||||||
//We subtract one from the children to get the type size only if there is at least one child AND
|
|
||||||
// the last node is actually a body node, as it may not have been generated yet if we're in the body
|
|
||||||
//and this function is recursive or if this is a non-instantiated template function
|
|
||||||
int numTypes = (children.size() > 0 && children[children.size()-1]->getDataRef()->type == code_block) ? children.size()-1 : children.size();
|
|
||||||
if (types.size() != numTypes) {
|
if (types.size() != numTypes) {
|
||||||
std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << numTypes << "), types are: ";
|
std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << numTypes << "), types are: ";
|
||||||
for (auto j : types)
|
for (auto j : types)
|
||||||
std::cout << j.toString() << " ";
|
std::cout << j.toString() << " ";
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "Versus" << std::endl;
|
std::cout << "Versus" << std::endl;
|
||||||
for (int j = 0; j < numTypes; j++) {
|
for (int j = 0; j < numTypes; j++)
|
||||||
std::cout << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl;
|
std::cout << functionType->parameterTypes[j]->toString() << " ";
|
||||||
}
|
|
||||||
for (auto child: children)
|
|
||||||
std::cout << "\t" << child->getDataRef()->toString() << std::endl;
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bool typesMatch = true;
|
bool typesMatch = true;
|
||||||
for (int j = 0; j < types.size(); j++) {
|
for (int j = 0; j < types.size(); j++) {
|
||||||
Type* tmpType = children[j]->getDataRef()->valueType;
|
Type* tmpType = functionType->parameterTypes[j];
|
||||||
//Don't worry if types don't match if it's a template type
|
//Don't worry if types don't match if it's a template type
|
||||||
//if (types[j] != *tmpType && tmpType->baseType != template_type_type) {
|
//if (types[j] != *tmpType && tmpType->baseType != template_type_type) {
|
||||||
// WE DO WORRY NOW B/C template type infrence is ugly and we need this to fail
|
// WE DO WORRY NOW B/C template type infrence is ugly and we need this to fail
|
||||||
@@ -934,7 +928,7 @@ NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, s
|
|||||||
if (types[j] != *tmpType) {
|
if (types[j] != *tmpType) {
|
||||||
typesMatch = false;
|
typesMatch = false;
|
||||||
std::cout << "Types do not match between two " << lookup << " " << types[j].toString();
|
std::cout << "Types do not match between two " << lookup << " " << types[j].toString();
|
||||||
std::cout << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl;
|
std::cout << " vs " << tmpType->toString() << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1277,7 +1271,11 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
ValueType baseType;
|
ValueType baseType;
|
||||||
NodeTree<ASTData>* typeDefinition = NULL;
|
NodeTree<ASTData>* typeDefinition = NULL;
|
||||||
std::set<std::string> traits;
|
std::set<std::string> traits;
|
||||||
while (typeIn[typeIn.size() - indirection - 1] == '*') indirection++;
|
// To counter this, for every indirection we step down a level
|
||||||
|
while (typeIn[typeIn.size() - indirection - 1] == '*') {
|
||||||
|
indirection++;
|
||||||
|
typeNode = typeNode->getChildren()[0];
|
||||||
|
};
|
||||||
std::string edited = strSlice(typeIn, 0, -(indirection + 1));
|
std::string edited = strSlice(typeIn, 0, -(indirection + 1));
|
||||||
if (edited == "void")
|
if (edited == "void")
|
||||||
baseType = void_type;
|
baseType = void_type;
|
||||||
@@ -1291,7 +1289,13 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
baseType = double_percision;
|
baseType = double_percision;
|
||||||
else if (edited == "char")
|
else if (edited == "char")
|
||||||
baseType = character;
|
baseType = character;
|
||||||
else {
|
else if (typeNode->getChildren().size() && typeNode->getChildren()[0]->getDataRef()->getName() == "function_type") {
|
||||||
|
baseType = function_type;
|
||||||
|
std::vector<Type*> types;
|
||||||
|
for (auto typeSyntaxNode : getNodes("type", typeNode->getChildren()[0]->getChildren()))
|
||||||
|
types.push_back(typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements));
|
||||||
|
return new Type(slice(types, 0, -2),types.back());
|
||||||
|
} else {
|
||||||
baseType = none;
|
baseType = none;
|
||||||
|
|
||||||
auto possibleMatches = scopeLookup(scope, edited);
|
auto possibleMatches = scopeLookup(scope, edited);
|
||||||
@@ -1313,11 +1317,6 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
std::cout << i.first << " ";
|
std::cout << i.first << " ";
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
// getChildren()[1] is \* because of pointer instead of template_inst
|
|
||||||
// To counter this, for every indirection we step down a level
|
|
||||||
for (int i = 0; i < indirection; i++)
|
|
||||||
typeNode = typeNode->getChildren()[0];
|
|
||||||
|
|
||||||
std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl;
|
std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl;
|
||||||
if (typeNode->getChildren().size() > 1)
|
if (typeNode->getChildren().size() > 1)
|
||||||
std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl;
|
std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl;
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
|||||||
std::string classStructs = "/**\n * Class Structs\n */\n\n";
|
std::string classStructs = "/**\n * Class Structs\n */\n\n";
|
||||||
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
|
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
|
||||||
std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n";
|
std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n";
|
||||||
|
// There also exists functionTypedefString which is a member variable that keeps
|
||||||
|
// track of utility typedefs that allow our C type generation to be more sane
|
||||||
|
// it is emitted in the h file right before functionPrototypes
|
||||||
|
|
||||||
|
|
||||||
// And get the correct order for emiting classes, but not if they're not in our file, then they will get included
|
// And get the correct order for emiting classes, but not if they're not in our file, then they will get included
|
||||||
@@ -242,7 +245,7 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionPrototypes;
|
hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionTypedefString + functionPrototypes;
|
||||||
cOutput += variableDeclarations + functionDefinitions;
|
cOutput += variableDeclarations + functionDefinitions;
|
||||||
return std::make_pair(hOutput, cOutput);
|
return std::make_pair(hOutput, cOutput);
|
||||||
}
|
}
|
||||||
@@ -568,19 +571,20 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl
|
|||||||
case function_type:
|
case function_type:
|
||||||
{
|
{
|
||||||
std::string indr_str;
|
std::string indr_str;
|
||||||
|
std::string typedefStr = "typedef ";
|
||||||
|
std::string typedefID = "ID" + CifyName(type->toString(false));
|
||||||
for (int i = 0; i < type->getIndirection(); i++)
|
for (int i = 0; i < type->getIndirection(); i++)
|
||||||
indr_str += "*";
|
indr_str += "*";
|
||||||
return_type = ValueTypeToCTypeThingHelper(type->returnType, "");
|
typedefStr += ValueTypeToCTypeThingHelper(type->returnType, "");
|
||||||
if (type->getIndirection())
|
typedefStr += " (*" + typedefID + ")(";
|
||||||
return_type += " (" + indr_str + "(*" + declaration + "))(";
|
|
||||||
else
|
|
||||||
return_type += " (*" + declaration + ")(";
|
|
||||||
if (type->parameterTypes.size() == 0)
|
if (type->parameterTypes.size() == 0)
|
||||||
return_type += "void";
|
typedefStr += "void";
|
||||||
else
|
else
|
||||||
for (int i = 0; i < type->parameterTypes.size(); i++)
|
for (int i = 0; i < type->parameterTypes.size(); i++)
|
||||||
return_type += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "");
|
typedefStr += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "");
|
||||||
return_type += ")";
|
typedefStr += ");\n";
|
||||||
|
functionTypedefString += typedefStr;
|
||||||
|
return_type = typedefID + indr_str + " " + declaration;
|
||||||
do_ending = false;
|
do_ending = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std:
|
|||||||
removeSymbols.push_back(Symbol("WS", false));
|
removeSymbols.push_back(Symbol("WS", false));
|
||||||
removeSymbols.push_back(Symbol("\\(", true));
|
removeSymbols.push_back(Symbol("\\(", true));
|
||||||
removeSymbols.push_back(Symbol("\\)", true));
|
removeSymbols.push_back(Symbol("\\)", true));
|
||||||
//removeSymbols.push_back(Symbol("::", true));
|
|
||||||
//removeSymbols.push_back(Symbol(":", true));
|
|
||||||
removeSymbols.push_back(Symbol("var", true));
|
removeSymbols.push_back(Symbol("var", true));
|
||||||
removeSymbols.push_back(Symbol("fun", true));
|
removeSymbols.push_back(Symbol("fun", true));
|
||||||
|
|
||||||
@@ -53,6 +51,7 @@ Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std:
|
|||||||
collapseSymbols.push_back(Symbol("if_comp_pred", false));
|
collapseSymbols.push_back(Symbol("if_comp_pred", false));
|
||||||
collapseSymbols.push_back(Symbol("declaration_block", false));
|
collapseSymbols.push_back(Symbol("declaration_block", false));
|
||||||
collapseSymbols.push_back(Symbol("type_list", false));
|
collapseSymbols.push_back(Symbol("type_list", false));
|
||||||
|
collapseSymbols.push_back(Symbol("opt_type_list", false));
|
||||||
collapseSymbols.push_back(Symbol("template_param_list", false));
|
collapseSymbols.push_back(Symbol("template_param_list", false));
|
||||||
collapseSymbols.push_back(Symbol("trait_list", false));
|
collapseSymbols.push_back(Symbol("trait_list", false));
|
||||||
collapseSymbols.push_back(Symbol("dec_type", false));
|
collapseSymbols.push_back(Symbol("dec_type", false));
|
||||||
|
|||||||
@@ -1 +1,8 @@
|
|||||||
9
|
9
|
||||||
|
9
|
||||||
|
7
|
||||||
|
8
|
||||||
|
11
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14
|
||||||
|
|||||||
@@ -4,9 +4,52 @@ fun test(): void {
|
|||||||
println(9)
|
println(9)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun test2(toPrint: int): void {
|
||||||
|
println(toPrint)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(): fun():void {
|
||||||
|
return test4;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test4(): void {
|
||||||
|
println(11)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doIt(fun: fun():void):void {
|
||||||
|
fun()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun itToBeDone():void {
|
||||||
|
println(12)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doItParam(fun: fun(int):void, param:int):void {
|
||||||
|
fun(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun itToBeDoneParam(param:int):void {
|
||||||
|
println(param)
|
||||||
|
}
|
||||||
|
|
||||||
fun main(): int {
|
fun main(): int {
|
||||||
var val = test
|
var val = test
|
||||||
|
var val2: fun():void = test
|
||||||
val()
|
val()
|
||||||
|
val2()
|
||||||
|
|
||||||
|
|
||||||
|
var val3 = test2
|
||||||
|
var val4: fun(int):void = test2
|
||||||
|
val3(7)
|
||||||
|
val4(8)
|
||||||
|
|
||||||
|
test3()()
|
||||||
|
doIt(itToBeDone)
|
||||||
|
doItParam(itToBeDoneParam, 13)
|
||||||
|
var indrdo = doItParam
|
||||||
|
var indrdoParam = itToBeDoneParam
|
||||||
|
indrdo(indrdoParam, 14)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user