some bug fixes, templated operator method overloading
This commit is contained in:
@@ -64,7 +64,10 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
|
|||||||
NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes);
|
NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes);
|
||||||
void unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap);
|
void unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap);
|
||||||
void unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes, std::map<std::string, Type*> typeMap);
|
void unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes, std::map<std::string, Type*> typeMap);
|
||||||
|
NodeTree<ASTData>* tryToFindOrInstantiateFunctionTemplate(std::string functionName, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::string functionName, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::string functionName, std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
std::map<std::string, Type*> makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types, std::map<std::string, Type*> scopeTypeMap);
|
std::map<std::string, Type*> makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types, std::map<std::string, Type*> scopeTypeMap);
|
||||||
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode);
|
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode);
|
||||||
|
|
||||||
|
|||||||
@@ -852,8 +852,12 @@ NodeTree<ASTData>* ASTTransformation::doFunction(NodeTree<ASTData>* scope, std::
|
|||||||
NodeTree<ASTData>* operatorMethod = NULL;
|
NodeTree<ASTData>* operatorMethod = NULL;
|
||||||
|
|
||||||
// make sure this isn't a pointer, also. Silly vector<string> bug
|
// make sure this isn't a pointer, also. Silly vector<string> bug
|
||||||
if (nodes[0]->getDataRef()->valueType && !nodes[0]->getDataRef()->valueType->getIndirection() && nodes[0]->getDataRef()->valueType->typeDefinition)
|
if (nodes[0]->getDataRef()->valueType && !nodes[0]->getDataRef()->valueType->getIndirection() && nodes[0]->getDataRef()->valueType->typeDefinition) {
|
||||||
operatorMethod = functionLookup(nodes[0]->getDataRef()->valueType->typeDefinition, lookupOp, mapNodesToTypes(slice(nodes,1,-1)));
|
operatorMethod = functionLookup(nodes[0]->getDataRef()->valueType->typeDefinition, lookupOp, mapNodesToTypes(slice(nodes,1,-1)));
|
||||||
|
// we're also gonna check to see if this is an operator template method
|
||||||
|
if (!operatorMethod)
|
||||||
|
operatorMethod = tryToFindOrInstantiateFunctionTemplate(lookupOp, nodes[0]->getDataRef()->valueType->typeDefinition, mapNodesToTypes(slice(nodes,1,-1)), templateTypeReplacements);
|
||||||
|
}
|
||||||
if (operatorMethod) {
|
if (operatorMethod) {
|
||||||
//Ok, so we construct
|
//Ok, so we construct
|
||||||
std::cout << "Early method level operator was found" << std::endl;
|
std::cout << "Early method level operator was found" << std::endl;
|
||||||
@@ -1634,10 +1638,26 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// So we want to be able to call this with either the children which is one name and one template thingy (func<a>), or just the name (func), or even with just
|
||||||
|
// a string as the name if, for example, we're generating the name from an operator overload (which we do) (operator+)
|
||||||
|
NodeTree<ASTData>* ASTTransformation::tryToFindOrInstantiateFunctionTemplate(std::string functionName, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
|
||||||
|
try {
|
||||||
|
return findOrInstantiateFunctionTemplate(functionName, std::vector<NodeTree<Symbol>*>(), scope, types, templateTypeReplacements);
|
||||||
|
} catch (const char *ex) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
|
NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
|
||||||
|
return findOrInstantiateFunctionTemplate("", children, scope, types, templateTypeReplacements);
|
||||||
|
}
|
||||||
|
NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::string functionName, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
|
||||||
|
return findOrInstantiateFunctionTemplate(functionName, std::vector<NodeTree<Symbol>*>(), scope, types, templateTypeReplacements);
|
||||||
|
}
|
||||||
|
NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::string functionName, std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
|
||||||
//First look to see if we can find this already instantiated
|
//First look to see if we can find this already instantiated
|
||||||
std::cout << "\n\nFinding or instantiating templated function\n\n" << std::endl;
|
std::cout << "\n\nFinding or instantiating templated function\n\n" << std::endl;
|
||||||
std::string functionName = concatSymbolTree(children[0]);
|
if (children.size())
|
||||||
|
functionName = concatSymbolTree(children[0]);
|
||||||
std::string fullyInstantiatedName;
|
std::string fullyInstantiatedName;
|
||||||
std::string scopelessFullyInstantiatedName;
|
std::string scopelessFullyInstantiatedName;
|
||||||
std::vector<Type*> templateActualTypes;
|
std::vector<Type*> templateActualTypes;
|
||||||
@@ -1659,7 +1679,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
|||||||
// Note that as a part o finferring the instantiation we already find the template, so we make that
|
// Note that as a part o finferring the instantiation we already find the template, so we make that
|
||||||
// condtitional too (templateDefinition)
|
// condtitional too (templateDefinition)
|
||||||
std::string instTypeString = "";
|
std::string instTypeString = "";
|
||||||
if (children.size() == 1) {
|
if (children.size() <= 1) {
|
||||||
// templateFunctionLookup adds the actual types to templateActualTypes if it's currently empty
|
// templateFunctionLookup adds the actual types to templateActualTypes if it's currently empty
|
||||||
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types, scopeTypeMap);
|
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types, scopeTypeMap);
|
||||||
for (auto instType : templateActualTypes)
|
for (auto instType : templateActualTypes)
|
||||||
|
|||||||
@@ -287,17 +287,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
return CCodeTriple("/* never reached import? */\n");
|
return CCodeTriple("/* never reached import? */\n");
|
||||||
case identifier:
|
case identifier:
|
||||||
{
|
{
|
||||||
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
|
std::string preName = "";
|
||||||
if (data.symbol.getName() == "this") {
|
std::string postName = "";
|
||||||
if (enclosingObject)
|
|
||||||
return CCodeTriple("this");
|
|
||||||
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.
|
|
||||||
std::string preName;
|
|
||||||
std::string postName;
|
|
||||||
//std::string preName = "/*ident*/";
|
|
||||||
// check for this being a closed over variable
|
// check for this being a closed over variable
|
||||||
// first, get declaring function, if it exists
|
// first, get declaring function, if it exists
|
||||||
if (enclosingFunction) {
|
if (enclosingFunction) {
|
||||||
@@ -309,6 +300,15 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// enclosing function comes first now, we might have a double closure that both close over the this pointer of an object
|
||||||
|
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
|
||||||
|
if (data.symbol.getName() == "this") {
|
||||||
|
if (enclosingObject || enclosingFunction)
|
||||||
|
return CCodeTriple(preName + "this" + postName);
|
||||||
|
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 (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
|
// dereference references, but only if inside a function
|
||||||
|
|||||||
@@ -104,18 +104,21 @@ obj grammer (Object) {
|
|||||||
var non_terminals: set::set<symbol::symbol>
|
var non_terminals: set::set<symbol::symbol>
|
||||||
var terminals: vector::vector<util::pair<symbol::symbol, regex::regex>>
|
var terminals: vector::vector<util::pair<symbol::symbol, regex::regex>>
|
||||||
var first_set_map: map::map<symbol::symbol, set::set<symbol::symbol>>
|
var first_set_map: map::map<symbol::symbol, set::set<symbol::symbol>>
|
||||||
|
var state_automata: state
|
||||||
|
|
||||||
fun construct(): *grammer {
|
fun construct(): *grammer {
|
||||||
rules.construct()
|
rules.construct()
|
||||||
non_terminals.construct()
|
non_terminals.construct()
|
||||||
terminals.construct()
|
terminals.construct()
|
||||||
first_set_map.construct()
|
first_set_map.construct()
|
||||||
|
state_automata.construct()
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *grammer) {
|
fun copy_construct(old: *grammer) {
|
||||||
rules.copy_construct(&old->rules)
|
rules.copy_construct(&old->rules)
|
||||||
non_terminals.copy_construct(&old->non_terminals)
|
non_terminals.copy_construct(&old->non_terminals)
|
||||||
terminals.copy_construct(&old->terminals)
|
terminals.copy_construct(&old->terminals)
|
||||||
first_set_map.copy_construct(&old->first_set_map)
|
first_set_map.copy_construct(&old->first_set_map)
|
||||||
|
state_automata.copy_construct(&old->state_automata)
|
||||||
}
|
}
|
||||||
fun operator=(other: grammer) {
|
fun operator=(other: grammer) {
|
||||||
destruct()
|
destruct()
|
||||||
@@ -126,6 +129,7 @@ obj grammer (Object) {
|
|||||||
non_terminals.destruct()
|
non_terminals.destruct()
|
||||||
terminals.destruct()
|
terminals.destruct()
|
||||||
first_set_map.destruct()
|
first_set_map.destruct()
|
||||||
|
state_automata.destruct()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculate_first_set() {
|
fun calculate_first_set() {
|
||||||
@@ -137,62 +141,74 @@ obj grammer (Object) {
|
|||||||
non_terminals.for_each( fun(non_terminal: symbol::symbol)
|
non_terminals.for_each( fun(non_terminal: symbol::symbol)
|
||||||
first_set_map[non_terminal] = set::set<symbol::symbol>()
|
first_set_map[non_terminal] = set::set<symbol::symbol>()
|
||||||
)
|
)
|
||||||
var first_helper = fun(rhs: vector::vector<symbol::symbol>): set::set<symbol::symbol> {
|
|
||||||
var toRet = set::set<symbol::symbol>()
|
|
||||||
if (rhs.size) {
|
|
||||||
for (var i = 0; i < rhs.size; i++;) {
|
|
||||||
var lookahead = first_set_map[rhs[i]]
|
|
||||||
if (lookahead.contains(symbol::null_symbol())) {
|
|
||||||
// remove the null if this is not the last in the rule
|
|
||||||
if (i != rhs.size-1)
|
|
||||||
lookahead.remove(symbol::null_symbol())
|
|
||||||
toRet.add(lookahead)
|
|
||||||
} else {
|
|
||||||
toRet.add(lookahead)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toRet.add(symbol::null_symbol())
|
|
||||||
}
|
|
||||||
return toRet
|
|
||||||
}
|
|
||||||
var changed = true
|
var changed = true
|
||||||
while (changed) {
|
while (changed) {
|
||||||
/*io::println("//////////current state of map/////////////")*/
|
|
||||||
first_set_map.keys.for_each(fun(sym: symbol::symbol) {
|
|
||||||
/*io::print("for ")*/
|
|
||||||
/*io::println(sym.to_string())*/
|
|
||||||
/*io::println("map is:")*/
|
|
||||||
/*first_set_map[sym].for_each(fun(look: symbol::symbol) {*/
|
|
||||||
/*io::print("lookahead: "); io::println(look.to_string())*/
|
|
||||||
/*})*/
|
|
||||||
})
|
|
||||||
changed = false
|
changed = false
|
||||||
rules.for_each( fun(r: rule) {
|
rules.for_each( fun(r: rule) {
|
||||||
var rule_lookahead = first_helper(r.rhs)
|
var rule_lookahead = first_vector(r.rhs)
|
||||||
if (!changed) {
|
if (!changed) {
|
||||||
/*io::println(r.to_string())*/
|
|
||||||
changed = !first_set_map[r.lhs].contains(rule_lookahead)
|
changed = !first_set_map[r.lhs].contains(rule_lookahead)
|
||||||
/*io::print("changed: "); io::println(changed)*/
|
|
||||||
/*io::print("\tcurrent lookahead is sized:")*/
|
|
||||||
/*io::println(first_set_map[r.lhs].size())*/
|
|
||||||
/*io::println("\tcurrent lookahead is:")*/
|
|
||||||
/*first_set_map[r.lhs].for_each(fun(look: symbol::symbol) {*/
|
|
||||||
/*io::print("\t\tlookahead: "); io::println(look.to_string())*/
|
|
||||||
/*})*/
|
|
||||||
/*io::println()*/
|
|
||||||
/*io::print("\rule lookahead is sized:")*/
|
|
||||||
/*io::println(rule_lookahead.size())*/
|
|
||||||
/*io::println("\trule lookahead is:")*/
|
|
||||||
/*rule_lookahead.for_each(fun(look: symbol::symbol) {*/
|
|
||||||
/*io::print("\t\tlookahead: "); io::println(look.to_string())*/
|
|
||||||
/*})*/
|
|
||||||
}
|
}
|
||||||
first_set_map[r.lhs].add(rule_lookahead)
|
first_set_map[r.lhs].add(rule_lookahead)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun first_vector(rhs: vector::vector<symbol::symbol>): set::set<symbol::symbol> {
|
||||||
|
var toRet = set::set<symbol::symbol>()
|
||||||
|
if (rhs.size) {
|
||||||
|
for (var i = 0; i < rhs.size; i++;) {
|
||||||
|
var lookahead = first_set_map[rhs[i]]
|
||||||
|
if (lookahead.contains(symbol::null_symbol())) {
|
||||||
|
// remove the null if this is not the last in the rule
|
||||||
|
if (i != rhs.size-1)
|
||||||
|
lookahead.remove(symbol::null_symbol())
|
||||||
|
toRet.add(lookahead)
|
||||||
|
} else {
|
||||||
|
toRet.add(lookahead)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toRet.add(symbol::null_symbol())
|
||||||
|
}
|
||||||
|
return toRet
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculate_state_automaton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closure(initial: vector::vector<rule>): vector::vector<rule> {
|
||||||
|
var continueIt = true
|
||||||
|
while (continueIt) {
|
||||||
|
continueIt = false
|
||||||
|
initial.for_each(fun(i: rule) {
|
||||||
|
rules.for_each(fun(r: rule) {
|
||||||
|
// if i is |a::=c . Bb, a|, we're doing each B::=... in rules
|
||||||
|
if (r.lhs != i.next())
|
||||||
|
return
|
||||||
|
// add r with lookahead
|
||||||
|
var newLookahead = first_vector(r.after_next())
|
||||||
|
if (newLookahead.contains(symbol::null_symbol())) {
|
||||||
|
newLookahead.remove(symbol::null_symbol())
|
||||||
|
newLookahead.add(i.lookahead)
|
||||||
|
}
|
||||||
|
for (var index = 0; index < initial.size; index++;) {
|
||||||
|
if (initial[index].equals_but_lookahead(r)) {
|
||||||
|
initial[index].lookahead += newLookahead
|
||||||
|
continueIt = true
|
||||||
|
return; // continuing rule-for_each
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var newRule = r.with_lookahead(newLookahead)
|
||||||
|
if (!initial.contains(newRule)) {
|
||||||
|
continueIt = true
|
||||||
|
initial.add(newRule)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return initial
|
||||||
|
}
|
||||||
|
|
||||||
fun to_string(): string::string {
|
fun to_string(): string::string {
|
||||||
var result = string::string("grammer rules:")
|
var result = string::string("grammer rules:")
|
||||||
@@ -201,6 +217,8 @@ obj grammer (Object) {
|
|||||||
non_terminals.for_each( fun(i : symbol::symbol) { result += string::string("\n\t") + i.to_string(); } )
|
non_terminals.for_each( fun(i : symbol::symbol) { result += string::string("\n\t") + i.to_string(); } )
|
||||||
result += "\nterminals:"
|
result += "\nterminals:"
|
||||||
terminals.for_each( fun(i : util::pair<symbol::symbol, regex::regex>) { result += string::string("\n\t") + i.first.to_string() + ": " + i.second.regexString; } )
|
terminals.for_each( fun(i : util::pair<symbol::symbol, regex::regex>) { result += string::string("\n\t") + i.first.to_string() + ": " + i.second.regexString; } )
|
||||||
|
result += "\nstate:"
|
||||||
|
result += state_automata.to_string()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,12 +252,34 @@ obj rule (Object) {
|
|||||||
destruct()
|
destruct()
|
||||||
copy_construct(&other)
|
copy_construct(&other)
|
||||||
}
|
}
|
||||||
|
//fun operator==(other: ref rule):bool {
|
||||||
|
fun operator==(other: rule):bool {
|
||||||
|
return lhs == other.lhs && rhs == other.rhs &&
|
||||||
|
position == other.position && lookahead == other.lookahead
|
||||||
|
}
|
||||||
|
fun equals_but_lookahead(other: ref rule):bool {
|
||||||
|
return lhs == other.lhs && rhs == other.rhs &&
|
||||||
|
position == other.position
|
||||||
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
lhs.destruct()
|
lhs.destruct()
|
||||||
rhs.destruct()
|
rhs.destruct()
|
||||||
lookahead.destruct()
|
lookahead.destruct()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun next(): symbol::symbol {
|
||||||
|
return rhs[position]
|
||||||
|
}
|
||||||
|
fun after_next(): vector::vector<symbol::symbol> {
|
||||||
|
return rhs.slice(position + 1, -1)
|
||||||
|
}
|
||||||
|
fun with_lookahead(newLookahead: set::set<symbol::symbol>): rule {
|
||||||
|
var toRet = rule(lhs, rhs)
|
||||||
|
toRet.position = position
|
||||||
|
toRet.lookahead = newLookahead
|
||||||
|
return toRet
|
||||||
|
}
|
||||||
|
|
||||||
fun to_string(): string::string {
|
fun to_string(): string::string {
|
||||||
var result = lhs.name + " -> "
|
var result = lhs.name + " -> "
|
||||||
rhs.for_each( fun(i : symbol::symbol) { result += i.to_string() + ", "; } )
|
rhs.for_each( fun(i : symbol::symbol) { result += i.to_string() + ", "; } )
|
||||||
@@ -255,6 +295,10 @@ obj state (Object) {
|
|||||||
kernel.construct()
|
kernel.construct()
|
||||||
rest.construct()
|
rest.construct()
|
||||||
}
|
}
|
||||||
|
fun construct(kernelIn: ref vector::vector<rule>, restIn: ref vector::vector<rule>): *state {
|
||||||
|
kernel.copy_construct(&kernelIn)
|
||||||
|
rest.copy_construct(&restIn)
|
||||||
|
}
|
||||||
fun copy_construct(other: *state) {
|
fun copy_construct(other: *state) {
|
||||||
kernel.copy_construct(&other->kernel)
|
kernel.copy_construct(&other->kernel)
|
||||||
rest.copy_construct(&other->rest)
|
rest.copy_construct(&other->rest)
|
||||||
@@ -267,5 +311,8 @@ obj state (Object) {
|
|||||||
kernel.destruct()
|
kernel.destruct()
|
||||||
rest.destruct()
|
rest.destruct()
|
||||||
}
|
}
|
||||||
|
fun to_string(): string::string {
|
||||||
|
return string::string("woo a state")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ obj set<T> (Object) {
|
|||||||
fun contains(item: T): bool {
|
fun contains(item: T): bool {
|
||||||
return data.find(item) != -1
|
return data.find(item) != -1
|
||||||
}
|
}
|
||||||
|
fun operator+=(item: T) {
|
||||||
|
add(item)
|
||||||
|
}
|
||||||
|
fun operator+=(items: set<T>) {
|
||||||
|
add(items)
|
||||||
|
}
|
||||||
fun add(item: T) {
|
fun add(item: T) {
|
||||||
if (!contains(item))
|
if (!contains(item))
|
||||||
data.add(item)
|
data.add(item)
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ obj symbol (Object) {
|
|||||||
fun operator==(other: symbol): bool {
|
fun operator==(other: symbol): bool {
|
||||||
return data == other.data && name == other.name && terminal == other.terminal;
|
return data == other.data && name == other.name && terminal == other.terminal;
|
||||||
}
|
}
|
||||||
|
fun operator!=(other: symbol): bool {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
fun to_string(): string::string {
|
fun to_string(): string::string {
|
||||||
var terminalString: *char
|
var terminalString: *char
|
||||||
if (terminal)
|
if (terminal)
|
||||||
|
|||||||
@@ -124,6 +124,16 @@ obj vector<T> (Object) {
|
|||||||
return find(item) != -1
|
return find(item) != -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// yep
|
||||||
|
fun operator==<U>(other:vector<U>):bool {
|
||||||
|
if (size != other.size)
|
||||||
|
return false
|
||||||
|
for (var i = 0; i < size; i++;)
|
||||||
|
if (!(data[i] == other.data[i])) // it's !(==) because we want equality if our members are equal, and overloading etc
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun set(index: int, dataIn: T): void {
|
fun set(index: int, dataIn: T): void {
|
||||||
if (index < 0 || index >= size)
|
if (index < 0 || index >= size)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ fun main():int {
|
|||||||
println("woo lexing:")
|
println("woo lexing:")
|
||||||
range(8).for_each(fun(i: int) { println(lex.next().to_string()); } )
|
range(8).for_each(fun(i: int) { println(lex.next().to_string()); } )
|
||||||
/*range(80).for_each(fun(i: int) { println(lex.next().to_string()); } )*/
|
/*range(80).for_each(fun(i: int) { println(lex.next().to_string()); } )*/
|
||||||
|
println(a.to_string())
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
tests/test_template_operator_overload.expected_results
Normal file
1
tests/test_template_operator_overload.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
works
|
||||||
14
tests/test_template_operator_overload.krak
Normal file
14
tests/test_template_operator_overload.krak
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import io:*
|
||||||
|
|
||||||
|
obj it {
|
||||||
|
fun operator+<U>(other: U): it {
|
||||||
|
println(other)
|
||||||
|
return *this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main():int {
|
||||||
|
var i: it
|
||||||
|
i + "works"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user