Wooo actual scoping and better C interop

This commit is contained in:
Nathan Braswell
2015-04-10 00:37:31 -04:00
parent e37836aea5
commit e3aa531856
23 changed files with 194 additions and 46 deletions

View File

@@ -16,7 +16,8 @@ class Type;
enum ASTType {undef, translation_unit, interpreter_directive, import, identifier, type_def,
function, code_block, typed_parameter, expression, boolean_expression, statement,
if_statement, while_loop, for_loop, return_statement, assignment_statement, declaration_statement,
if_comp, simple_passthrough, passthrough_params, function_call, value};
if_comp, simple_passthrough, passthrough_params, in_passthrough_params, out_passthrough_params,
opt_string, param_assign, function_call, value};
class ASTData {
public:

View File

@@ -35,6 +35,7 @@ class CGenerator {
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName);
std::string generatorString;
std::string linkerString;
private:
std::string tabs();
int tabLevel;

View File

@@ -15,7 +15,7 @@ template_param = identifier WS traits | identifier ;
import = "import" WS identifier WS SEMI | "import" WS identifier WS ":" WS "\*" WS SEMI | "import" WS identifier WS ":" WS import_list WS SEMI ;
import_list = identifier | identifier WS "," WS import_list ;
# all for optional semicolons k k
# all for optional semicolons
line_break = "
+" ;
actual_white = "( | )+" | line_break | line_break actual_white | "( | )+" actual_white ;
@@ -28,9 +28,12 @@ SEMI = ";" | line_break | cpp_comment ;
if_comp = "__if_comp__" WS identifier WS if_comp_pred ;
if_comp_pred = code_block | simple_passthrough ;
simple_passthrough = "simple_passthrough" WS passthrough_params WS triple_quoted_string ;
passthrough_params = "\(" WS opt_param_assign_list WS ":" WS opt_param_assign_list WS ":" WS opt_string WS "\)" | ;
passthrough_params = "\(" WS in_passthrough_params WS ":" WS out_passthrough_params WS ":" WS opt_string WS "\)" | ;
in_passthrough_params = opt_param_assign_list ;
out_passthrough_params = opt_param_assign_list ;
opt_param_assign_list = param_assign_list | ;
param_assign_list = identifier WS "=" WS identifier | identifier WS "=" WS identifier WS "," WS param_assign_list ;
param_assign_list = param_assign WS "," WS param_assign_list | param_assign ;
param_assign = identifier WS "=" WS identifier ;
opt_string = string | ;
triple_quoted_string = "\"\"\"((\"\"(`|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|;|'|

View File

@@ -68,6 +68,12 @@ std::string ASTData::ASTTypeToString(ASTType type) {
return "simple_passthrough";
case passthrough_params:
return "passthrough_params";
case in_passthrough_params:
return "out_passthrough_params";
case param_assign:
return "param_assign";
case opt_string:
return "opt_string";
case function_call:
return "function_call";
case value:

View File

@@ -56,6 +56,8 @@ NodeTree<ASTData>* ASTTransformation::firstPass(std::string fileName, NodeTree<S
else //It's not
name = concatSymbolTree(i->getChildren()[0]);
NodeTree<ASTData>* firstDec = addToScope("~enclosing_scope", translationUnit, new NodeTree<ASTData>("type_def", ASTData(type_def, Symbol(name, true, name))));
addToScope(name, firstDec, translationUnit);
translationUnit->addChild(firstDec);
//If this is a template, go ahead and set it up. Pass 2 needs templates set up so it can (partially) instantiate them.
//So we give this typedef its name without any template types and make its type template_type, and point to this from node.
//Then, when this template is instantiated, it will run transform on from with the types filled in.
@@ -71,9 +73,6 @@ NodeTree<ASTData>* ASTTransformation::firstPass(std::string fileName, NodeTree<S
else if (typedefChildren.size() == 1 || typedefChildren[1]->getData().getName() != "type") //We don't make the type for alises, because the second pass will assign it the type it points to
firstDec->getDataRef()->valueType = new Type(firstDec);
translationUnit->addChild(firstDec);
translationUnit->getDataRef()->scope[name].push_back(firstDec);
firstDec->getDataRef()->scope["~enclosing_scope"].push_back(translationUnit);
} else if (i->getDataRef()->getName() == "if_comp") {
std::cout << "IF COMP" << std::endl;
NodeTree<ASTData>* newNode = addToScope("~enclosing_scope", translationUnit, new NodeTree<ASTData>(i->getDataRef()->getName(), ASTData(if_comp)));
@@ -154,7 +153,9 @@ void ASTTransformation::secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
if (typedefChildren.size() > 1 && typedefChildren[1]->getData().getName() == "type") {
Type* aliasedType = typeFromTypeNode(typedefChildren[1], ast, std::map<std::string, Type*>());
typeDef->getDataRef()->valueType = aliasedType;
typeDef->getDataRef()->scope["~enclosing_scope"][0] = aliasedType->typeDefinition; //So that object lookups find the right member. Note that this overrides translation_unit as a parent scope
// only put in scope if it has a definition, that is it is not an aliased primitive
if (aliasedType->typeDefinition)
typeDef->getDataRef()->scope["~enclosing_scope"][0] = aliasedType->typeDefinition; //So that object lookups find the right member. Note that this overrides translation_unit as a parent scope
// std::cout << name << " alias's to " << aliasedType->typeDefinition << std::endl;
// std::cout << "that is " << aliasedType->typeDefinition->getDataRef()->toString() << std::endl;
continue;
@@ -629,6 +630,18 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
} else if (name == "passthrough_params") {
newNode = new NodeTree<ASTData>(name, ASTData(passthrough_params));
addToScope("~enclosing_scope", scope, newNode);
} else if (name == "in_passthrough_params") {
newNode = new NodeTree<ASTData>(name, ASTData(in_passthrough_params));
addToScope("~enclosing_scope", scope, newNode);
} else if (name == "out_passthrough_params") {
newNode = new NodeTree<ASTData>(name, ASTData(out_passthrough_params));
addToScope("~enclosing_scope", scope, newNode);
} else if (name == "opt_string") {
newNode = new NodeTree<ASTData>(name, ASTData(opt_string));
addToScope("~enclosing_scope", scope, newNode);
} else if (name == "param_assign") {
newNode = new NodeTree<ASTData>(name, ASTData(param_assign));
addToScope("~enclosing_scope", scope, newNode);
} else if (name == "function_call") {
std::string functionCallName = concatSymbolTree(children[0]);
newNode = new NodeTree<ASTData>(functionCallName, ASTData(function_call, Symbol(functionCallName, true)));

View File

@@ -27,6 +27,7 @@ void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs,
outputCFile.close();
outputHFile.close();
buildString += linkerString;
buildString += "-o " + outputName;
std::ofstream outputBuild;
outputBuild.open(outputName + "/" + split(outputName, '/').back() + ".sh");
@@ -191,7 +192,7 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], nullptr);
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
}
functionPrototypes += scopePrefix(declaration) +
functionPrototypes += ((declarationData.symbol.getName() == "main") ? "" : scopePrefix(declaration)) +
CifyName(declarationData.symbol.getName() + nameDecoration) +
"(" + parameters + "); /*func*/\n";
// generate function
@@ -295,7 +296,9 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject);
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
}
output += scopePrefix(from) + CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
output += ((data.symbol.getName() == "main") ? "" : scopePrefix(from)) +
CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
return output;
}
case code_block:
@@ -379,7 +382,28 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
return generate(children[1], enclosingObject);
return "";
case simple_passthrough:
return strSlice(generate(children[0], enclosingObject), 3, -4);
{
// 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)
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType) + " " + assignChildren[1]->getDataRef()->symbol.getName() + " = " + generate(assignChildren[0], enclosingObject) + ";\n";
else if (in_or_out->getDataRef()->type == out_passthrough_params)
post_passthrough += generate(assignChildren[0], enclosingObject) + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n";
else
linkerString += " " + strSlice(generate(in_or_out, enclosingObject), 1, -2) + " ";
}
}
}
// The actual passthrough string is the last child now, as we might
// have passthrough_params be the first child
return pre_passthrough + strSlice(generate(children.back(), enclosingObject), 3, -4) + post_passthrough;
}
case function_call:
{
//NOTE: The first (0th) child of a function call node is the declaration of the function

View File

@@ -36,7 +36,8 @@ Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std:
removeSymbols.push_back(Symbol("template", true));
removeSymbols.push_back(Symbol("\\|", true));
//collapseSymbols.push_back(Symbol("scoped_identifier", false));
collapseSymbols.push_back(Symbol("opt_param_assign_list", false));
collapseSymbols.push_back(Symbol("opt_param_assign_list", false));
collapseSymbols.push_back(Symbol("param_assign_list", false));
collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false));
collapseSymbols.push_back(Symbol("opt_parameter_list", false));
collapseSymbols.push_back(Symbol("opt_import_list", false));

View File

@@ -1,4 +1,4 @@
__if_comp__ __C__ simple_passthrough """
__if_comp__ __C__ simple_passthrough(::"-lm") """
#include <math.h>
"""
@@ -16,7 +16,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = atan(arg);
"""
}//end C wrapper
@@ -28,7 +28,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(x = x, y = y : ans = ans :) """
simple_passthrough(x = x, y = y, ans = ans : ans = ans :) """
ans = atan2(x,y);
"""
}//end C wrapper
@@ -40,7 +40,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = acos(arg);
"""
}//end C wrapper
@@ -52,7 +52,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = asin(arg);
"""
}//end C wrapper
@@ -64,7 +64,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = tan(arg);
"""
}//end C wrapper
@@ -76,7 +76,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = cos(arg);
"""
}//end C wrapper
@@ -88,7 +88,7 @@ __if_comp__ __C__ simple_passthrough """
{
|double| ans = 0;
__if_comp__ __C__{
simple_passthrough(arg = arg : ans = ans :) """
simple_passthrough(arg = arg, ans = ans : ans = ans :) """
ans = sin(arg);
"""
}//end C wrapper

View File

@@ -5,9 +5,9 @@ __if_comp__ __C__ simple_passthrough """
/* we have a template versions so we don't have to cast (because we don't have that yet) */
template <T> |T*| malloc(|int| size) {
|T*| memPtr = 0;
|T*| memPtr;
__if_comp__ __C__ {
simple_passthrough( size = size : memPtr = memPtr :) """
simple_passthrough( size = size, memPtr = memPtr : memPtr = memPtr :) """
memPtr = malloc(size);
"""
}
@@ -23,11 +23,11 @@ template <T> |void| free(|T*| memPtr) {
}
template <T> |int| sizeof() {
|int| result = 0;
|T| testObj;
|int| result;
__if_comp__ __C__ {
simple_passthrough(testObj = testObj : result = result:) """
result = sizeof(testObj);
int result = sizeof(testObj);
"""
}
return result;

View File

@@ -1,11 +1,17 @@
__if_comp__ __C__ __simple_passthrough__ """
__if_comp__ __C__ simple_passthrough """
#include <stdio.h>
int diff = 7;
"""
|void| print_it() {
__if_comp__ __C__ __simple_passthrough__ """
__if_comp__ __C__ simple_passthrough """
printf("diff_file: %d\n", diff);
"""
}
|void| print_it(|int| i) {
__if_comp__ __C__ simple_passthrough(i = i::) """
printf("diff_file: %d\n", i);
"""
}

7
tests/sameNameOne.krak Normal file
View File

@@ -0,0 +1,7 @@
|int| sameVar;
|int| sameFun() { return 5; }
typedef classTester {
|int| method() { return 8; }
}

6
tests/sameNameTwo.krak Normal file
View File

@@ -0,0 +1,6 @@
|int| sameVar;
|int| sameFun() { return 6; }
typedef classTester {
|int| method() { return 9; }
}

View File

@@ -1,2 +1,3 @@
same_file: 5
diff_file: 7
diff_file: 13

View File

@@ -1,17 +1,24 @@
import c_passthrough_diff
__if_comp__ __C__ __simple_passthrough__ """
__if_comp__ __C__ simple_passthrough """
#include <stdio.h>
int same = 5;
"""
|int| main() {
__if_comp__ __C__ __simple_passthrough__ """
__if_comp__ __C__ simple_passthrough """
printf("same_file: %d\n", same);
"""
c_passthrough_diff::print_it()
c_passthrough_diff::print_it();
|int| i = 7;
|int| j = 6;
__if_comp__ __C__ simple_passthrough(i = i, j = j : j = j:) """
j = i + j;
"""
c_passthrough_diff::print_it(j)
return 0
}

View File

@@ -1,14 +0,0 @@
import io:*
|int| main() {
|int| a = -1
println(a)
println(-a)
println(+a); // this is still -1! (as C has it, anyway) (darn comment/semicolon interaction)
|int| b = 7
println(b)
println(-b)
return 0;
}

View File

@@ -0,0 +1,10 @@
#include "test_negative_number_unary.krak.h"
/**
* Variable Declarations
*/
/**
* Function Definitions
*/

View File

@@ -0,0 +1,27 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
/**
* Plain Typedefs
*/
/**
* Import Includes
*/
/**
* Top Level C Passthrough
*/
/**
* Extern Variable Declarations
*/
/**
* Class Structs
*/
/**
* Function Prototypes
*/

View File

@@ -0,0 +1,2 @@
#!/bin/sh
cc -std=c99 test_negative_number_unary.krak.c -o test_negative_number_unary.krak

View File

@@ -0,0 +1,9 @@
1
2
3
4
5
6
7
8
9

36
tests/test_sameName.krak Normal file
View File

@@ -0,0 +1,36 @@
import io:*
import sameNameOne
import sameNameTwo
|int| sameVar;
|int| sameFun() { return 4; }
typedef classTester {
|int| method() {
return 7
}
}
|int| main() {
sameVar = 1
sameNameOne::sameVar = 2
sameNameTwo::sameVar = 3
|classTester| class1;
|sameNameOne::classTester| class2;
|sameNameTwo::classTester| class3;
println(sameVar)
println(sameNameOne::sameVar)
println(sameNameTwo::sameVar)
println(sameFun())
println(sameNameOne::sameFun())
println(sameNameTwo::sameFun())
println(class1.method())
println(class2.method())
println(class3.method())
return 0
}

View File

@@ -0,0 +1 @@
3.141593

View File

@@ -5,6 +5,7 @@ import math:*;
{
|double| ans;
|double| STD_PI = 4.0*atan(1.0);
println(STD_PI);
/*
ans = 4.0*atan(1.0);