reference type added and very basic pass by reference works in CGenerator. Much more work to go to make sure complicated cases work and return by reference

This commit is contained in:
Nathan Braswell
2015-07-14 19:32:54 -04:00
parent 8c490908d4
commit 602810002b
8 changed files with 106 additions and 22 deletions

View File

@@ -24,11 +24,12 @@ class Type {
Type(ValueType typeIn, std::set<std::string> traitsIn); //Mostly for template type type's Type(ValueType typeIn, std::set<std::string> traitsIn); //Mostly for template type type's
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0); Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0);
Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn); Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn);
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn); Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn);
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn); Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn);
Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn); Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn, bool referenceIn = false);
Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>()); Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>());
~Type(); ~Type();
const bool test_equality(const Type &other, bool care_about_references) const;
bool const operator==(const Type &other)const; bool const operator==(const Type &other)const;
bool const operator!=(const Type &other)const; bool const operator!=(const Type &other)const;
bool const operator<(const Type &other)const; bool const operator<(const Type &other)const;
@@ -50,6 +51,7 @@ class Type {
std::set<std::string> traits; std::set<std::string> traits;
std::vector<Type*> parameterTypes; std::vector<Type*> parameterTypes;
Type *returnType; Type *returnType;
bool is_reference;;
private: private:
int indirection; int indirection;
}; };

View File

@@ -2,7 +2,8 @@ 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 = "\*" WS type | "void" | "int" | "float" | "double" | "char" | scoped_identifier | scoped_identifier WS template_inst | function_type ; type = "ref" WS pre_reffed | pre_reffed ;
pre_reffed = "\*" WS pre_reffed | "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 ; function_type = "fun" WS "\(" WS opt_type_list WS "\)" WS ":" WS type ;
dec_type = ":" WS type ; dec_type = ":" WS type ;

View File

@@ -239,6 +239,8 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
functionName = concatSymbolTree(children[0]); functionName = concatSymbolTree(children[0]);
auto returnTypeNode = getNode("type", getNode("typed_return", children)); // if null, the typed_return had no children and we're supposed to automatically do a void type auto returnTypeNode = getNode("type", getNode("typed_return", children)); // if null, the typed_return had no children and we're supposed to automatically do a void type
auto returnType = returnTypeNode ? typeFromTypeNode(returnTypeNode, scope, templateTypeReplacements): new Type(void_type); auto returnType = returnTypeNode ? typeFromTypeNode(returnTypeNode, scope, templateTypeReplacements): new Type(void_type);
if (!returnType)
throw "freakout";
functionDef = new NodeTree<ASTData>("function", ASTData(function, Symbol(functionName, true), returnType)); functionDef = new NodeTree<ASTData>("function", ASTData(function, Symbol(functionName, true), returnType));
addToScope("~enclosing_scope", scope, functionDef); addToScope("~enclosing_scope", scope, functionDef);
addToScope(functionName, functionDef, scope); addToScope(functionName, functionDef, scope);
@@ -1025,7 +1027,9 @@ NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, s
//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
// for regular function lookups so that we know to retry with a template // for regular function lookups so that we know to retry with a template
if (types[j] != *tmpType) { //
// we use test_equality so that we can pass in a false to not care about references
if (!types[j].test_equality(*tmpType, false)) {
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 " << tmpType->toString() << std::endl; std::cout << " vs " << tmpType->toString() << std::endl;
@@ -1114,6 +1118,9 @@ NodeTree<ASTData>* ASTTransformation::templateClassLookup(NodeTree<ASTData>* sco
} }
void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap) { void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap) {
// First, get rid of the reference part - we don't care for unification
syntaxType = syntaxType->getChildren().back();
// Ok, 3 options for syntaxType here. // Ok, 3 options for syntaxType here.
// 1) This a basic type. (int, or object, etc) // 1) This a basic type. (int, or object, etc)
// THIS ONE will fall through and get put in the map, but it // THIS ONE will fall through and get put in the map, but it
@@ -1287,7 +1294,8 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
for (int j = 0; j < functionParameters.size(); j++) { for (int j = 0; j < functionParameters.size(); j++) {
auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[2], scope, typeMap); auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[2], scope, typeMap);
std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl; std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl;
if (*paramType != types[j]) { // use test_equality so we can pass false and not care about references
if (!paramType->test_equality(types[j], false)) {
parameterTypesMatch = false; parameterTypesMatch = false;
std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl; std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl;
break; break;
@@ -1458,19 +1466,28 @@ NodeTree<ASTData>* ASTTransformation::getUpperTranslationUnit(NodeTree<ASTData>*
//Create a type from a syntax tree. This can get complicated with templates //Create a type from a syntax tree. This can get complicated with templates
Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) { Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) {
std::string typeIn = concatSymbolTree(typeNode);
int indirection = 0; int indirection = 0;
bool is_reference = false;
ValueType baseType; ValueType baseType;
NodeTree<ASTData>* typeDefinition = NULL; NodeTree<ASTData>* typeDefinition = NULL;
std::set<std::string> traits; std::set<std::string> traits;
// if this is a reference, we also have to step down a level
if (typeNode->getChildren().size() && typeNode->getChildren().front()->getDataRef()->getValue() == "ref") {
is_reference = true;
}
// always step down below the ref level
typeNode = typeNode->getChildren().back();
std::string typeIn = concatSymbolTree(typeNode);
// To counter this, for every indirection we step down a level // To counter this, for every indirection we step down a level
//while (typeIn[indirection] == '*') { //while (typeIn[indirection] == '*') {
//since fun(*T):int gets transformed to *T:int, the text based way doesn't work anymore //since fun(*T):int gets transformed to *T:int, the text based way doesn't work anymore
while (typeNode->getChildren().size() && typeNode->getChildren().front()->getDataRef()->getValue() == "*") { while (typeNode->getChildren().size() && typeNode->getChildren().front()->getDataRef()->getValue() == "*") {
indirection++; indirection++;
typeNode = typeNode->getChildren().back(); typeNode = typeNode->getChildren().back();
}; }
std::string edited = strSlice(typeIn, indirection, -1); std::string edited = strSlice(typeIn, indirection, -1);
if (edited == "void") if (edited == "void")
baseType = void_type; baseType = void_type;
@@ -1489,7 +1506,7 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
std::vector<Type*> types; std::vector<Type*> types;
for (auto typeSyntaxNode : getNodes("type", typeNode->getChildren()[0]->getChildren())) for (auto typeSyntaxNode : getNodes("type", typeNode->getChildren()[0]->getChildren()))
types.push_back(typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements)); types.push_back(typeFromTypeNode(typeSyntaxNode, scope, templateTypeReplacements));
return new Type(slice(types, 0, -2),types.back()); return new Type(slice(types, 0, -2),types.back(), is_reference);
} else { } else {
baseType = none; baseType = none;
@@ -1607,10 +1624,10 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
std::cout << "Could not find type " << edited << ", returning NULL" << std::endl; std::cout << "Could not find type " << edited << ", returning NULL" << std::endl;
return NULL; return NULL;
} else { } else {
std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, traits).toString() << std::endl; std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection, is_reference, traits).toString() << std::endl;
} }
} }
Type* toReturn = new Type(baseType, typeDefinition, indirection, traits); Type* toReturn = new Type(baseType, typeDefinition, indirection, is_reference, traits);
std::cout << "Returning type " << toReturn->toString() << std::endl; std::cout << "Returning type " << toReturn->toString() << std::endl;
return toReturn; return toReturn;
} }

View File

@@ -291,8 +291,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
if (data.symbol.getName() == "this") { if (data.symbol.getName() == "this") {
if (enclosingObject) if (enclosingObject)
return CCodeTriple("this"); return CCodeTriple("this");
else std::cerr << "Error: this used in non-object scope" << std::endl;
std::cerr << "Error: this used in non-object scope" << std::endl; throw "Error: this used in non-object scope";
} }
//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. //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.
std::string preName; std::string preName;
@@ -311,6 +311,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
} }
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
preName += "this->"; preName += "this->";
// dereference references, but only if inside a function
if (enclosingFunction && data.valueType->is_reference) {
preName += "(*";
postName += ")";
}
// we're scope prefixing EVERYTHING // we're scope prefixing EVERYTHING
return preName + scopePrefix(from) + CifyName(data.symbol.getName()) + postName; //Cifying does nothing if not an operator overload return preName + scopePrefix(from) + CifyName(data.symbol.getName()) + postName; //Cifying does nothing if not an operator overload
} }
@@ -734,18 +739,32 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
} }
} }
CCodeTriple parameters; CCodeTriple parameters;
// see if we should copy_construct all the parameters // see if we should copy_construct / referencize all the parameters
for (int i = 1; i < children.size(); i++) { //children[0] is the declaration for (int i = 1; i < children.size(); i++) { //children[0] is the declaration
Type* func_param_type = children[0]->getDataRef()->valueType->parameterTypes[i-1];
Type *param_type = children[i]->getDataRef()->valueType;
if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) { if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) {
std::string tmpParamName = "param" + getID(); std::string tmpParamName = "param" + getID();
CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction); CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction);
parameters.preValue += paramValue.preValue; parameters.preValue += paramValue.preValue;
parameters.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n"; parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + ";\n";
parameters.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()}); parameters.preValue += generateMethodIfExists(param_type, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
parameters.value += tmpParamName; if (func_param_type->is_reference)
parameters.value += "&" + tmpParamName;
else
parameters.value += tmpParamName;
parameters.postValue += paramValue.postValue; parameters.postValue += paramValue.postValue;
} else { } else {
parameters += generate(children[i], enclosingObject, true, enclosingFunction); if (func_param_type->is_reference) {
//std::string tmpParamName = "param" + getID();
//CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction);
//parameters.preValue += paramValue.preValue;
//parameters.preValue += ValueTypeToCType(param_type, tmpParamName) + " = " + paramValue.value + ";\n";
//parameters.value += "&" + tmpParamName;
parameters += "&" + generate(children[i], enclosingObject, true, enclosingFunction);
} else {
parameters += generate(children[i], enclosingObject, true, enclosingFunction);
}
} }
if (i < children.size()-1) if (i < children.size()-1)
parameters += ", "; parameters += ", ";
@@ -1010,6 +1029,8 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl
return return_type; return return_type;
for (int i = 0; i < type->getIndirection(); i++) for (int i = 0; i < type->getIndirection(); i++)
return_type += "*"; return_type += "*";
if (type->is_reference)
return_type += " /*ref*/ *";
return return_type + declaration; return return_type + declaration;
} }

View File

@@ -58,6 +58,7 @@ Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std:
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));
//collapseSymbols.push_back(Symbol("pre_reffed", false));
} }
Importer::~Importer() { Importer::~Importer() {

View File

@@ -7,6 +7,7 @@ Type::Type() {
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
Type::Type(ValueType typeIn, int indirectionIn) { Type::Type(ValueType typeIn, int indirectionIn) {
@@ -16,6 +17,7 @@ Type::Type(ValueType typeIn, int indirectionIn) {
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
Type::Type(ValueType typeIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
@@ -26,6 +28,7 @@ Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) { Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
@@ -35,6 +38,7 @@ Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) { Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) {
@@ -45,9 +49,10 @@ Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn)
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn) {
baseType = typeIn; baseType = typeIn;
indirection = indirectionIn; indirection = indirectionIn;
typeDefinition = typeDefinitionIn; typeDefinition = typeDefinitionIn;
@@ -55,9 +60,10 @@ Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectio
templateDefinition = nullptr; templateDefinition = nullptr;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = referenceIn;
} }
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn) { Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, bool referenceIn, std::set<std::string> traitsIn, std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
baseType = typeIn; baseType = typeIn;
indirection = indirectionIn; indirection = indirectionIn;
typeDefinition = typeDefinitionIn; typeDefinition = typeDefinitionIn;
@@ -66,8 +72,9 @@ Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectio
parameterTypes = parameterTypesIn; parameterTypes = parameterTypesIn;
returnType = returnTypeIn; returnType = returnTypeIn;
templateInstantiated = false; templateInstantiated = false;
is_reference = referenceIn;
} }
Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn) { Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn, bool referenceIn) {
baseType = function_type; baseType = function_type;
indirection = 0; indirection = 0;
typeDefinition = nullptr; typeDefinition = nullptr;
@@ -75,6 +82,7 @@ Type::Type(std::vector<Type*> parameterTypesIn, Type* returnTypeIn) {
parameterTypes = parameterTypesIn; parameterTypes = parameterTypesIn;
returnType = returnTypeIn; returnType = returnTypeIn;
templateInstantiated = false; templateInstantiated = false;
is_reference = referenceIn;
} }
Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) { Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) {
@@ -85,6 +93,7 @@ Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<st
traits = traitsIn; traits = traitsIn;
returnType = nullptr; returnType = nullptr;
templateInstantiated = false; templateInstantiated = false;
is_reference = false;
} }
@@ -92,7 +101,12 @@ Type::~Type() {
} }
const bool Type::operator==(const Type &other) const { const bool Type::operator==(const Type &other) const {
return test_equality(other, true);
}
const bool Type::test_equality(const Type &other, bool care_about_references) const {
bool first_part = ( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits); bool first_part = ( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits);
if (care_about_references && is_reference != other.is_reference)
return false;
if (!first_part) if (!first_part)
return false; return false;
if ((returnType && !other.returnType) || (!returnType && other.returnType)) if ((returnType && !other.returnType) || (!returnType && other.returnType))
@@ -116,6 +130,8 @@ const bool Type::operator<(const Type &other) const {
return baseType < other.baseType; return baseType < other.baseType;
if (indirection != other.indirection) if (indirection != other.indirection)
return indirection < other.indirection; return indirection < other.indirection;
if (is_reference != other.is_reference)
return is_reference;
if (typeDefinition != other.typeDefinition) if (typeDefinition != other.typeDefinition)
return typeDefinition < other.typeDefinition; return typeDefinition < other.typeDefinition;
if (templateDefinition != other.templateDefinition) if (templateDefinition != other.templateDefinition)
@@ -180,6 +196,8 @@ std::string Type::toString(bool showTraits) {
else else
typeString = "unknown_type"; typeString = "unknown_type";
} }
if (is_reference)
typeString = "ref " + typeString;
for (int i = 0; i < indirection; i++) for (int i = 0; i < indirection; i++)
typeString += "*"; typeString += "*";
if (indirection < 0) if (indirection < 0)
@@ -195,7 +213,7 @@ std::string Type::toString(bool showTraits) {
} }
Type* Type::clone() { Type* Type::clone() {
return new Type(baseType, typeDefinition, indirection, traits, parameterTypes, returnType); return new Type(baseType, typeDefinition, indirection, is_reference, traits, parameterTypes, returnType);
} }
int Type::getIndirection() { int Type::getIndirection() {

View File

@@ -0,0 +1 @@
7

View File

@@ -0,0 +1,23 @@
import io:*
/*fun byRef<T>(it: ref T) {*/
/*it = it + 1*/
/*}*/
/*fun byRef(it: * int) {*/
/**it = *it + 1*/
/*}*/
fun byRef(it: ref int) {
it = it + 1
}
// what about cosures closing over references?
fun main():int {
var a = 6
byRef(a)
println(a)
return 0
}