Skip to content

Commit

Permalink
Surprise mofos! Bounty's mine. Closes #346
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Jul 10, 2015
1 parent 757a9a9 commit 3aabfc1
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 9 deletions.
20 changes: 19 additions & 1 deletion source/rock/middle/FunctionCall.ooc
Expand Up @@ -1109,12 +1109,20 @@ FunctionCall: class extends Expression {

finalScore := 0
typeResult := resolveTypeArg(trail, res, typeArg name, finalScore&)

if(finalScore == -1) break
if(typeResult) {
if (debugCondition()) {
token printMessage("in #{this}, resolved typeArg #{typeArg}, result = #{typeResult}")
token printMessage("owner is #{typeResult owner ? typeResult owner toString() : "<nil>"}")
}
result := match {
case typeResult instanceOf?(FuncType) || (typeResult pointerLevel() > 0) =>
VariableAccess new("Pointer", token)
case =>
if (debugCondition()) {
token printMessage("making an access to typeResult")
}
VariableAccess new(typeResult, token)
}

Expand Down Expand Up @@ -1214,7 +1222,17 @@ FunctionCall: class extends Expression {
}

if(realCount == refCount) {
if(debugCondition()) " >> Found arg-arg %s for typeArgName %s, returning %s" printfln(implArg toString(), typeArgName, result toString())
if(debugCondition()) {
token printMessage(" >> Found arg-arg #{implArg} (of type #{implArg class name}) for typeArgName #{typeArgName}, returning #{result}")
}

match implArg {
case va: VariableAccess =>
if (va expr) {
result = result clone()
result owner = va expr
}
}
combineTypesHard(res, this, combinedResult&, result, "arg-arg")
}
}
Expand Down
6 changes: 5 additions & 1 deletion source/rock/middle/Type.ooc
Expand Up @@ -18,6 +18,8 @@ Type: abstract class extends Expression {
SCORE_SEED := const static 1024
NOLUCK_SCORE := const static -100000

owner: Expression = null

init: func ~type (.token) {
super(token)
}
Expand Down Expand Up @@ -292,7 +294,9 @@ TypeAccess: class extends Type {
setRef: func (d: Declaration) { inner setRef(d) }

clone: func -> This {
new(inner clone(), token)
copy := new(inner clone(), token)
copy owner = owner
copy
}

dereference: func -> Type { inner dereference() }
Expand Down
49 changes: 43 additions & 6 deletions source/rock/middle/VariableAccess.ooc
Expand Up @@ -61,13 +61,26 @@ VariableAccess: class extends Expression {
super(token)
name = type getName()

if (debugCondition()) {
token printMessage("Building new typeAccess for #{type}, ref = #{type getRef()}")
trap()
}

if(type getRef() instanceOf?(VariableDecl)) {
varDecl := type getRef() as VariableDecl
if(varDecl getOwner() != null) {
if(varDecl isStatic) {
expr = VariableAccess new(varDecl getOwner() getInstanceType(), token)
} else {
expr = VariableAccess new("this", token)
if (debugCondition()) {
token printMessage("That's where the 'this' comes from! owner is #{type owner ? type owner toString() : "<none>"}")
}
if (type owner) {
expr = type owner
} else {
// FIXME: ideally, this would never happen? 'owner' would just be 'this'
expr = VariableAccess new("this", token)
}
}
}
} else {
Expand Down Expand Up @@ -473,7 +486,8 @@ VariableAccess: class extends Expression {
println("trail = " + trail toString())
}
msg := "Undefined symbol '%s'" format(subject toString())
if(res params helpful) {
msg += "Trail = #{trail}"
if (res params helpful) {
similar := subject findSimilar(res)
if(similar) {
msg += similar
Expand All @@ -488,6 +502,9 @@ VariableAccess: class extends Expression {
res wholeAgain(this, "Couldn't resolve varacc")
}

if (debugCondition()) {
token printMessage("About to check generic access")
}
checkGenericAccess(trail, res)

return Response OK
Expand All @@ -496,10 +513,6 @@ VariableAccess: class extends Expression {

_genericAccessDone := false

/**
* This has some intersection with FunctionCall's `resolveTypeArg`
* TODO: maybe find a unified way to do that? (amos)
*/
checkGenericAccess: func (trail: Trail, res: Resolver) {
type := getType()
if (!type) {
Expand Down Expand Up @@ -533,8 +546,18 @@ VariableAccess: class extends Expression {
return
}

if (debugCondition()) {
token printMessage("About to realtypize maybe?")
}

if (type isGeneric()) {
if (debugCondition()) {
token printMessage("realtypizing!")
}
realTypize(trail, res)
if (debugCondition()) {
token printMessage("done realtypizing.")
}
return
}

Expand Down Expand Up @@ -567,6 +590,9 @@ VariableAccess: class extends Expression {
return
}

if (debugCondition()) {
token printMessage("realtypizing inner!")
}
realTypizeInner(trail, res)
}

Expand All @@ -588,18 +614,29 @@ VariableAccess: class extends Expression {
ourTypeArg := getType() getName()
finalScore := 0
realType := expr getType() searchTypeArg(ourTypeArg, finalScore&)
if (debugCondition()) {
token printMessage("done doing searchTypeArg, finalScore = #{finalScore}")
}

if (finalScore == -1) {
// try again next time!
return
}

if (realType == null || realType isGeneric()) {
if (debugCondition()) {
token printMessage("realType null or generic :(")
}
// we're probably inside a generic type declaration, where generic
// types aren't real yet
_genericAccessDone = true
return
}

if (debugCondition()) {
token printMessage("realType for #{this} found to be #{realType}, with ref #{realType getRef()}")
}

cast := Cast new(this, realType clone(), token)
if (!trail peek() replace(this, cast)) {
res throwError(CouldntReplace new(token, this, cast, trail))
Expand Down
9 changes: 8 additions & 1 deletion source/rock/middle/VariableDecl.ooc
Expand Up @@ -142,7 +142,7 @@ VariableDecl: class extends Declaration {

resolveAccess: func (access: VariableAccess, res: Resolver, trail: Trail) -> Int {
// FIXME: This, huh, shouldn't be needed at all, right?
// ie. it should all be handled in Scope anyway, I think.
// ie. it should all be handled in Scope anyway, I think. -- amos
if(name == access name) {
access suggest(this)
}
Expand Down Expand Up @@ -378,6 +378,10 @@ VariableDecl: class extends Declaration {
expr = null
}

if (type getName() == "Kakhi") {
token printMessage("It's for this varDecl! Trail = \n\n#{trail}")
}

typeAcc := VariableAccess new(type, token)
sizeAcc := VariableAccess new(typeAcc, "size", token)

Expand Down Expand Up @@ -692,3 +696,6 @@ IncompatibleElementInTupleVarDecl: class extends Error {
IncompatibleInit: class extends Error {
init: super func ~tokenMessage
}

trap: func {}

43 changes: 43 additions & 0 deletions test/compiler/generics/use-owner-not-this.ooc
@@ -0,0 +1,43 @@

// Test for https://github.com/fasterthanlime/rock/issues/346

import structs/HashBag

Pair: class <Kakhi, V> {
kik: Kakhi
v: V

init: func (=kik, =v) {}
}

index := 0

gprint: func <Tina> (t: Tina) {
r := match t {
case i: Int => "#{i}"
case s: String => "#{s}"
case => "nope"
}
match index {
case 0 => expect("Hello", r)
case 1 => expect("World!", r)
case 2 => expect("leet", r)
case 3 => expect("1337", r)
}
index += 1
}

//operator => <K, V> (k: K, v: V) -> Pair { Pair<K, V> new(k, v) }

hashbag: func (args: ...) {
args each(|arg|
pair := arg as Pair
gprint(pair kik)
gprint(pair v)
)
}

describe("should refer to typeArg from owner, not 'this'", ||
hashbag(Pair new("Hello", "World!"), Pair new("leet", 1337))
)

44 changes: 44 additions & 0 deletions test/compiler/generics/use-owner-not-this2.ooc
@@ -0,0 +1,44 @@

// Test for https://github.com/fasterthanlime/rock/issues/346

import structs/HashBag

Pair: class <Kakhi, V> {
kik: Kakhi
v: V

init: func (=kik, =v) {}
}

index := 0

gprint: func <Tina> (t: Tina) {
r := match t {
case i: Int => "#{i}"
case s: String => "#{s}"
case => "nope"
}
match index {
case 0 => expect("Hello", r)
case 1 => expect("World!", r)
case 2 => expect("leet", r)
case 3 => expect("1337", r)
}
index += 1
}

operator => <K, V> (k: K, v: V) -> Pair<K, V> { Pair<K, V> new(k, v) }

hashbag: func (args: ...) {
args each(|arg|
pair := arg as Pair
gprint(pair kik)
gprint(pair v)
)
}

describe("should refer to typeArg from owner, not 'this'", ||
hashbag("Hello" => "World!", "leet" => 1337)
)


0 comments on commit 3aabfc1

Please sign in to comment.