This commit is contained in:
Araq 2011-05-02 20:42:29 +02:00
commit 7d2b3dd6db
3 changed files with 54 additions and 61 deletions

View file

@ -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})
@ -72,17 +67,14 @@ proc sameMethodBucket(a, b: PSym): bool =
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
@ -137,50 +122,50 @@ proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) =
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))
var ret: PNode
if base.typ.sons[0] != nil: if base.typ.sons[0] != nil:
a = newNodeI(nkAsgn, base.info) 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:
var a = newNodeI(nkElifBranch, base.info)
addSon(a, cond) addSon(a, cond)
addSon(a, ret) addSon(a, ret)
addSon(disp, a) addSon(disp, a)
else:
disp = ret
result.ast.sons[codePos] = disp result.ast.sons[codePos] = disp
proc generateMethodDispatchers*(): PNode = proc generateMethodDispatchers*(): PNode =

View file

@ -0,0 +1,10 @@
discard """
output: "do nothing"
"""
method somethin(obj: TObject) =
echo "do nothing"
var o: TObject
o.somethin()

View file

@ -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