Skip to content

Commit

Permalink
Operator overload in types, closes #583
Browse files Browse the repository at this point in the history
  • Loading branch information
nddrylliog committed Feb 14, 2013
1 parent b17b5fb commit 6ec80f5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 23 deletions.
74 changes: 63 additions & 11 deletions source/rock/middle/ArrayAccess.ooc
Expand Up @@ -209,10 +209,11 @@ ArrayAccess: class extends Expression {
resolveOverload: func (trail: Trail, res: Resolver, hasOne?: Bool* = null) -> Response {

/*
printf("Looking for an overload of %s[%s], %s\n",
"Looking for an overload of %s[%s], %s" printfln(
array getType() ? array getType() toString() : "(nil)",
indices[0] getType() ? indices[0] getType() toString() : "(nil)",
array getType() && array getType() getRef() ? array getType() getRef() toString() : "(nil)")
array getType() && array getType() getRef() ? array getType() getRef() toString() : "(nil)"
)
*/

// so here's the plan: we give each operator overload a score
Expand All @@ -228,6 +229,33 @@ ArrayAccess: class extends Expression {
(parent as BinaryOp isAssign()) &&
(parent as BinaryOp getLeft() == this)

// first we check the lhs's type
lhsType := array getType()

if (lhsType) {
lhsTypeRef := lhsType getRef()

match lhsTypeRef {
case tDecl: TypeDecl =>
if (tDecl isMeta) {
tDecl = tDecl getNonMeta()
}

for (opDecl in tDecl operators) {
"Matching %s against %s" printfln(opDecl toString(), toString())
score := getScore(opDecl, reqType, inAssign ? parent as BinaryOp : null, res)
if(score == -1) {
return Response LOOP
}
if(score > bestScore) {
bestScore = score
candidate = opDecl
}
}
}
}

// then we check the current module
for(opDecl in trail module() getOperators()) {
score := getScore(opDecl, reqType, inAssign ? parent as BinaryOp : null, res)
if(score == -1) {
Expand All @@ -239,6 +267,7 @@ ArrayAccess: class extends Expression {
}
}

// and then the imports
for(imp in trail module() getAllImports()) {
module := imp getModule()
for(opDecl in module getOperators()) {
Expand All @@ -257,7 +286,13 @@ ArrayAccess: class extends Expression {
fDecl := candidate getFunctionDecl()
fCall := FunctionCall new(fDecl getName(), token)
fCall setRef(fDecl)
fCall getArguments() add(array)

if (fDecl owner) {
fCall expr = array
} else {
fCall getArguments() add(array)
}

fCall getArguments() addAll(indices)

if(inAssign) {
Expand All @@ -284,35 +319,52 @@ ArrayAccess: class extends Expression {

isResolved: func -> Bool { array isResolved() && type != null }
getScore: func (op: OperatorDecl, reqType: Type, assign: BinaryOp, res: Resolver) -> Int {
"op symbol = %s" printfln(op getSymbol())

if(!(op getSymbol() equals?(assign != null ? "[]=" : "[]"))) {
return 0 // not the right overload type - skip
}
diff := op getSymbol() endsWith?("=") ? 2 : 1
requiredArgs := indices getSize() + diff

fDecl := op getFunctionDecl()
"fDecl = %s" printfln(fDecl toString())

args := ArrayList<VariableDecl> new()
args addAll(fDecl getArguments())

if (fDecl owner) {
args add(0, fDecl owner getThisDecl())
}

args := fDecl getArguments()
if(!args last() instanceOf?(VarArg) && (args getSize() != indices getSize() + diff)) {
"args size = %d, required = %d" printfln(args size, requiredArgs)

if(!args last() instanceOf?(VarArg) && (args getSize() != requiredArgs)) {
// not a match!
if(res params veryVerbose) {
//if(res params veryVerbose) {
"For %s vs %s, got %d args, %d indices, diff is %d - no luck!" format(op toString(), toString(), args getSize(), indices getSize(), diff) println()
}
//}
return 0
}

// Handle the array expression first, e.g. array[indices...]
opArray := args get(0)
if(opArray getType() == null || array getType() == null) return -1
if(opArray getType() == null || array getType() == null) {
"Null opArray" println()
return -1
}

arrayScore := array getType() getScore(opArray getType())
if(arrayScore == -1) return -1
if(arrayScore == -1) {
"-1 arrayScore" println()
return -1
}

indexScore := 0
for(i in 0..(args getSize() - diff)) {
opIndex := args[i + 1]
index := indices[i]
//"opIndex = %s, index = %s (diff = %d)" printfln(opIndex toString(), index toString(), diff)
"opIndex = %s, index = %s (diff = %d)" printfln(opIndex toString(), index toString(), diff)
match {
case opIndex instanceOf?(VarArg) =>
indexScore += Type SCORE_SEED
Expand All @@ -336,7 +388,7 @@ ArrayAccess: class extends Expression {
reqScore := reqType ? fDecl getReturnType() getScore(reqType) : 0
if(reqScore == -1) return -1

//"Score of %s for %s = %d (array %d, index %d, req %d)" printfln(op toString(), toString(), arrayScore + indexScore + reqScore, arrayScore, indexScore, reqScore)
"Score of %s for %s = %d (array %d, index %d, req %d)" printfln(op toString(), toString(), arrayScore + indexScore + reqScore, arrayScore, indexScore, reqScore)

return arrayScore + indexScore + reqScore

Expand Down
8 changes: 8 additions & 0 deletions source/rock/middle/CoverDecl.ooc
Expand Up @@ -129,7 +129,15 @@ CoverDecl: class extends TypeDecl {
instance addVariable(variable clone())
}

for (oDecl in operators) {
instance addOperator(oDecl)
}

for (fDecl in getMeta() functions) {
if (fDecl oDecl) {
// already been added at last step
continue
}
instance addFunction(fDecl)
}

Expand Down
7 changes: 5 additions & 2 deletions source/rock/middle/FunctionDecl.ooc
Expand Up @@ -5,7 +5,7 @@ import Cast, Expression, Type, Visitor, Argument, TypeDecl, Scope,
VariableDecl, Node, Statement, Module, FunctionCall, Declaration,
Version, StringLiteral, Conditional, Import, ClassDecl, StringLiteral,
IntLiteral, NullLiteral, BaseType, FuncType, AddressOf, BinaryOp,
TypeList, CoverDecl, StructLiteral, Dereference
TypeList, CoverDecl, StructLiteral, Dereference, OperatorDecl

import tinker/[Resolver, Response, Trail, Errors]

Expand Down Expand Up @@ -43,6 +43,9 @@ import algo/autoReturn
*/
FunctionDecl: class extends Declaration {

/** The operator declaration this FunctionDecl corresponds to */
oDecl: OperatorDecl

/** name: func ~suffix - suffix is null if there's no suffix in the grammar */
name = "", suffix = null, fullName = null, doc = "" : String

Expand Down Expand Up @@ -124,7 +127,7 @@ FunctionDecl: class extends Declaration {
* If we are a method (member function), 'owner' is non-null, and is a reference
* to the TypeDecl to which we belong
*/
owner : TypeDecl = null
owner : TypeDecl { get set }

/** If we're a method, staticVariant is the variant where 'this' is an actual explicit argument */
staticVariant : This = null
Expand Down
1 change: 1 addition & 0 deletions source/rock/middle/OperatorDecl.ooc
Expand Up @@ -29,6 +29,7 @@ OperatorDecl: class extends Expression {

setFunctionDecl: func (=fDecl) {
fDecl setInline(true)
fDecl oDecl = this
}
getFunctionDecl: func -> FunctionDecl { fDecl }

Expand Down
19 changes: 9 additions & 10 deletions source/rock/middle/TypeDecl.ooc
Expand Up @@ -102,8 +102,7 @@ TypeDecl: abstract class extends Declaration {
}

debugCondition: inline func -> Bool {
//false
name == "MyArrayClass" || name == "MyArray"
false
}

isAbstract: func -> Bool { false }
Expand Down Expand Up @@ -409,10 +408,6 @@ TypeDecl: abstract class extends Declaration {

if(debugCondition() || res params veryVerbose) "====== Resolving type decl %s" printfln(toString())

if(debugCondition()) {
[0][1]
}

if (!type isResolved()) {
response := type resolve(trail, res)
if(!response ok()) {
Expand All @@ -426,18 +421,15 @@ TypeDecl: abstract class extends Declaration {
if(!superType isResolved()) {
response := superType resolve(trail, res)
if(!response ok()) {
//if(debugCondition() || res params veryVerbose) printf("====== Response of superType of %s == %s\n", toString(), response toString())
trail pop(this)
return response
}
}

//hasCheckedInheritance := static false
if(!hasCheckedInheritance && superType getRef() != null) {
if(checkInheritanceLoop(res)) hasCheckedInheritance = true
}

//hasCheckedAbstract := static false
if(!hasCheckedAbstract && superType getRef() != null && isMeta) {
if(checkAbstractFuncs(res)) hasCheckedAbstract = true
}
Expand All @@ -446,7 +438,6 @@ TypeDecl: abstract class extends Declaration {
if(!_finishedGhosting) {
response := ghostTypeParams(trail, res)
if(!response ok()) {
//if(debugCondition() || res params veryVerbose) printf("====== Response of type-param ghosting of %s == %s\n", toString(), response toString())
trail pop(this)
return response
}
Expand Down Expand Up @@ -531,6 +522,14 @@ TypeDecl: abstract class extends Declaration {
}
}

for(oDecl in operators) {
response := oDecl resolve(trail, res)
if(!response ok()) {
trail pop(this)
return response
}
}

if(meta) {
meta module = module
response := meta resolve(trail, res)
Expand Down

0 comments on commit 6ec80f5

Please sign in to comment.