fixes #12
This commit is contained in:
parent
4d5c3ebd46
commit
7d2b3dd6db
3 changed files with 54 additions and 61 deletions
|
|
@ -13,13 +13,10 @@ import
|
||||||
options, ast, astalgo, msgs, idents, renderer, types, magicsys
|
options, ast, astalgo, msgs, idents, renderer, types, magicsys
|
||||||
|
|
||||||
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||||
var
|
var dest = skipTypes(d, abstractPtrs)
|
||||||
dest, source: PType
|
var source = skipTypes(n.typ, abstractPtrs)
|
||||||
diff: int
|
|
||||||
dest = skipTypes(d, abstractPtrs)
|
|
||||||
source = skipTypes(n.typ, abstractPtrs)
|
|
||||||
if (source.kind == tyObject) and (dest.kind == tyObject):
|
if (source.kind == tyObject) and (dest.kind == tyObject):
|
||||||
diff = inheritanceDiff(dest, source)
|
var diff = inheritanceDiff(dest, source)
|
||||||
if diff == high(int): InternalError(n.info, "cgmeth.genConv")
|
if diff == high(int): InternalError(n.info, "cgmeth.genConv")
|
||||||
if diff < 0:
|
if diff < 0:
|
||||||
result = newNodeIT(nkObjUpConv, n.info, d)
|
result = newNodeIT(nkObjUpConv, n.info, d)
|
||||||
|
|
@ -36,9 +33,8 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc methodCall*(n: PNode): PNode =
|
proc methodCall*(n: PNode): PNode =
|
||||||
var disp: PSym
|
|
||||||
result = n
|
result = n
|
||||||
disp = lastSon(result.sons[0].sym.ast).sym
|
var disp = lastSon(result.sons[0].sym.ast).sym
|
||||||
result.sons[0].sym = disp
|
result.sons[0].sym = disp
|
||||||
for i in countup(1, sonsLen(result) - 1):
|
for i in countup(1, sonsLen(result) - 1):
|
||||||
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
|
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
|
||||||
|
|
@ -46,15 +42,14 @@ proc methodCall*(n: PNode): PNode =
|
||||||
var gMethods: seq[TSymSeq]
|
var gMethods: seq[TSymSeq]
|
||||||
|
|
||||||
proc sameMethodBucket(a, b: PSym): bool =
|
proc sameMethodBucket(a, b: PSym): bool =
|
||||||
var aa, bb: PType
|
|
||||||
result = false
|
result = false
|
||||||
if a.name.id != b.name.id: return
|
if a.name.id != b.name.id: return
|
||||||
if sonsLen(a.typ) != sonsLen(b.typ):
|
if sonsLen(a.typ) != sonsLen(b.typ):
|
||||||
return # check for return type:
|
return # check for return type:
|
||||||
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]): return
|
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]): return
|
||||||
for i in countup(1, sonsLen(a.typ) - 1):
|
for i in countup(1, sonsLen(a.typ) - 1):
|
||||||
aa = a.typ.sons[i]
|
var aa = a.typ.sons[i]
|
||||||
bb = b.typ.sons[i]
|
var bb = b.typ.sons[i]
|
||||||
while true:
|
while true:
|
||||||
aa = skipTypes(aa, {tyGenericInst})
|
aa = skipTypes(aa, {tyGenericInst})
|
||||||
bb = skipTypes(bb, {tyGenericInst})
|
bb = skipTypes(bb, {tyGenericInst})
|
||||||
|
|
@ -71,18 +66,15 @@ proc sameMethodBucket(a, b: PSym): bool =
|
||||||
return
|
return
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc methodDef*(s: PSym) =
|
proc methodDef*(s: PSym) =
|
||||||
var
|
var L = len(gMethods)
|
||||||
L, q: int
|
|
||||||
disp: PSym
|
|
||||||
L = len(gMethods)
|
|
||||||
for i in countup(0, L - 1):
|
for i in countup(0, L - 1):
|
||||||
if sameMethodBucket(gMethods[i][0], s):
|
if sameMethodBucket(gMethods[i][0], s):
|
||||||
add(gMethods[i], s) # store a symbol to the dispatcher:
|
add(gMethods[i], s) # store a symbol to the dispatcher:
|
||||||
addSon(s.ast, lastSon(gMethods[i][0].ast))
|
addSon(s.ast, lastSon(gMethods[i][0].ast))
|
||||||
return
|
return
|
||||||
add(gMethods, @[s]) # create a new dispatcher:
|
add(gMethods, @[s]) # create a new dispatcher:
|
||||||
disp = copySym(s)
|
var disp = copySym(s)
|
||||||
disp.typ = copyType(disp.typ, disp.typ.owner, false)
|
disp.typ = copyType(disp.typ, disp.typ.owner, false)
|
||||||
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
|
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
|
||||||
disp.ast = copyTree(s.ast)
|
disp.ast = copyTree(s.ast)
|
||||||
|
|
@ -92,9 +84,8 @@ proc methodDef*(s: PSym) =
|
||||||
addSon(s.ast, newSymNode(disp))
|
addSon(s.ast, newSymNode(disp))
|
||||||
|
|
||||||
proc relevantCol(methods: TSymSeq, col: int): bool =
|
proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||||
var t: PType
|
|
||||||
# returns true iff the position is relevant
|
# returns true iff the position is relevant
|
||||||
t = methods[0].typ.sons[col]
|
var t = methods[0].typ.sons[col]
|
||||||
result = false
|
result = false
|
||||||
if skipTypes(t, skipPtrs).kind == tyObject:
|
if skipTypes(t, skipPtrs).kind == tyObject:
|
||||||
for i in countup(1, high(methods)):
|
for i in countup(1, high(methods)):
|
||||||
|
|
@ -102,33 +93,27 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
|
proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
|
||||||
var
|
|
||||||
d: int
|
|
||||||
aa, bb: PType
|
|
||||||
result = 0
|
result = 0
|
||||||
for col in countup(1, sonsLen(a.typ) - 1):
|
for col in countup(1, sonsLen(a.typ) - 1):
|
||||||
if intSetContains(relevantCols, col):
|
if intSetContains(relevantCols, col):
|
||||||
aa = skipTypes(a.typ.sons[col], skipPtrs)
|
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
||||||
bb = skipTypes(b.typ.sons[col], skipPtrs)
|
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
||||||
d = inheritanceDiff(aa, bb)
|
var d = inheritanceDiff(aa, bb)
|
||||||
if (d != high(int)):
|
if (d != high(int)):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) =
|
proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) =
|
||||||
# we use shellsort here; fast and simple
|
# we use shellsort here; fast and simple
|
||||||
var
|
var N = len(a)
|
||||||
N, j, h: int
|
var h = 1
|
||||||
v: PSym
|
|
||||||
N = len(a)
|
|
||||||
h = 1
|
|
||||||
while true:
|
while true:
|
||||||
h = 3 * h + 1
|
h = 3 * h + 1
|
||||||
if h > N: break
|
if h > N: break
|
||||||
while true:
|
while true:
|
||||||
h = h div 3
|
h = h div 3
|
||||||
for i in countup(h, N - 1):
|
for i in countup(h, N - 1):
|
||||||
v = a[i]
|
var v = a[i]
|
||||||
j = i
|
var j = i
|
||||||
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
|
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
|
||||||
a[j] = a[j - h]
|
a[j] = a[j - h]
|
||||||
j = j - h
|
j = j - h
|
||||||
|
|
@ -136,51 +121,51 @@ proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) =
|
||||||
a[j] = v
|
a[j] = v
|
||||||
if h == 1: break
|
if h == 1: break
|
||||||
|
|
||||||
proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
|
proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
|
||||||
var
|
var base = lastSon(methods[0].ast).sym
|
||||||
disp, cond, call, ret, a, isn: PNode
|
|
||||||
base, curr, ands, iss: PSym
|
|
||||||
paramLen: int
|
|
||||||
base = lastSon(methods[0].ast).sym
|
|
||||||
result = base
|
result = base
|
||||||
paramLen = sonsLen(base.typ)
|
var paramLen = sonsLen(base.typ)
|
||||||
disp = newNodeI(nkIfStmt, base.info)
|
var disp = newNodeI(nkIfStmt, base.info)
|
||||||
ands = getSysSym("and")
|
var ands = getSysSym("and")
|
||||||
iss = getSysSym("is")
|
var iss = getSysSym("is")
|
||||||
for meth in countup(0, high(methods)):
|
for meth in countup(0, high(methods)):
|
||||||
curr = methods[meth] # generate condition:
|
var curr = methods[meth] # generate condition:
|
||||||
cond = nil
|
var cond: PNode = nil
|
||||||
for col in countup(1, paramLen - 1):
|
for col in countup(1, paramLen - 1):
|
||||||
if IntSetContains(relevantCols, col):
|
if IntSetContains(relevantCols, col):
|
||||||
isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
||||||
addSon(isn, newSymNode(iss))
|
addSon(isn, newSymNode(iss))
|
||||||
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
||||||
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
|
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
|
||||||
if cond != nil:
|
if cond != nil:
|
||||||
a = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
var a = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
||||||
addSon(a, newSymNode(ands))
|
addSon(a, newSymNode(ands))
|
||||||
addSon(a, cond)
|
addSon(a, cond)
|
||||||
addSon(a, isn)
|
addSon(a, isn)
|
||||||
cond = a
|
cond = a
|
||||||
else:
|
else:
|
||||||
cond = isn
|
cond = isn
|
||||||
call = newNodeI(nkCall, base.info)
|
var call = newNodeI(nkCall, base.info)
|
||||||
addSon(call, newSymNode(curr))
|
addSon(call, newSymNode(curr))
|
||||||
for col in countup(1, paramLen - 1):
|
for col in countup(1, paramLen - 1):
|
||||||
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
|
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
|
||||||
curr.typ.sons[col], false))
|
curr.typ.sons[col], false))
|
||||||
if base.typ.sons[0] != nil:
|
var ret: PNode
|
||||||
a = newNodeI(nkAsgn, base.info)
|
if base.typ.sons[0] != nil:
|
||||||
|
var a = newNodeI(nkAsgn, base.info)
|
||||||
addSon(a, newSymNode(base.ast.sons[resultPos].sym))
|
addSon(a, newSymNode(base.ast.sons[resultPos].sym))
|
||||||
addSon(a, call)
|
addSon(a, call)
|
||||||
ret = newNodeI(nkReturnStmt, base.info)
|
ret = newNodeI(nkReturnStmt, base.info)
|
||||||
addSon(ret, a)
|
addSon(ret, a)
|
||||||
else:
|
else:
|
||||||
ret = call
|
ret = call
|
||||||
a = newNodeI(nkElifBranch, base.info)
|
if cond != nil:
|
||||||
addSon(a, cond)
|
var a = newNodeI(nkElifBranch, base.info)
|
||||||
addSon(a, ret)
|
addSon(a, cond)
|
||||||
addSon(disp, a)
|
addSon(a, ret)
|
||||||
|
addSon(disp, a)
|
||||||
|
else:
|
||||||
|
disp = ret
|
||||||
result.ast.sons[codePos] = disp
|
result.ast.sons[codePos] = disp
|
||||||
|
|
||||||
proc generateMethodDispatchers*(): PNode =
|
proc generateMethodDispatchers*(): PNode =
|
||||||
|
|
|
||||||
10
tests/accept/run/tmethods1.nim
Normal file
10
tests/accept/run/tmethods1.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
discard """
|
||||||
|
output: "do nothing"
|
||||||
|
"""
|
||||||
|
|
||||||
|
method somethin(obj: TObject) =
|
||||||
|
echo "do nothing"
|
||||||
|
|
||||||
|
var o: TObject
|
||||||
|
o.somethin()
|
||||||
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -6,7 +6,7 @@
|
||||||
High priority (version 0.9.0)
|
High priority (version 0.9.0)
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
- tests: run modules that contain "when isMainModule", compile the other
|
- tests: run modules that contain "#RUN_ME", compile the other
|
||||||
modules; run the GC tests
|
modules; run the GC tests
|
||||||
- fix implicit generic routines
|
- fix implicit generic routines
|
||||||
- fix the streams implementation so that it uses methods
|
- fix the streams implementation so that it uses methods
|
||||||
|
|
@ -44,8 +44,6 @@ Low priority
|
||||||
------------
|
------------
|
||||||
- resizing of strings/sequences could take into account the memory that
|
- resizing of strings/sequences could take into account the memory that
|
||||||
is allocated
|
is allocated
|
||||||
- implicit conversions from ``ptr/ref T`` to ``var T`` (from
|
|
||||||
``ptr/ref T`` to ``T``)?
|
|
||||||
- typeAllowed() for parameters...
|
- typeAllowed() for parameters...
|
||||||
- find a way to reintroduce the cleanup() pass for C code generation: this
|
- find a way to reintroduce the cleanup() pass for C code generation: this
|
||||||
is hard because of partial evaluation --> symbol files will fix this as
|
is hard because of partial evaluation --> symbol files will fix this as
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue