Wooo actual scoping and better C interop
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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|;|'|
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
7
tests/sameNameOne.krak
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
|int| sameVar;
|
||||
|int| sameFun() { return 5; }
|
||||
typedef classTester {
|
||||
|int| method() { return 8; }
|
||||
}
|
||||
|
||||
6
tests/sameNameTwo.krak
Normal file
6
tests/sameNameTwo.krak
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|int| sameVar;
|
||||
|int| sameFun() { return 6; }
|
||||
typedef classTester {
|
||||
|int| method() { return 9; }
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
same_file: 5
|
||||
diff_file: 7
|
||||
diff_file: 13
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "test_negative_number_unary.krak.h"
|
||||
|
||||
/**
|
||||
* Variable Declarations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function Definitions
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
2
tests/test_negative_number_unary.krak/test_negative_number_unary.krak.sh
Executable file
2
tests/test_negative_number_unary.krak/test_negative_number_unary.krak.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
cc -std=c99 test_negative_number_unary.krak.c -o test_negative_number_unary.krak
|
||||
9
tests/test_sameName.expected_results
Normal file
9
tests/test_sameName.expected_results
Normal file
@@ -0,0 +1,9 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
36
tests/test_sameName.krak
Normal file
36
tests/test_sameName.krak
Normal 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
|
||||
}
|
||||
1
tests/test_trigTest.expected_results
Normal file
1
tests/test_trigTest.expected_results
Normal file
@@ -0,0 +1 @@
|
||||
3.141593
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user