about summary refs log tree commit diff stats
BranchCommit messageAuthorAge
bongkeys: st-xterm compatAcid Bong3 years
masterbump version to 6.4Hiltjo Posthuma3 years
musldmenumon fixAcid Bong3 years
 
TagDownloadAuthorAge
6.4dwm-6.4.tar.gz  Hiltjo Posthuma3 years
6.3dwm-6.3.tar.gz  Hiltjo Posthuma4 years
6.2dwm-6.2.tar.gz  Anselm R Garbe7 years
6.1dwm-6.1.tar.gz  Hiltjo Posthuma10 years
6.0dwm-6.0.tar.gz  anselm@garbe.us14 years
5.9dwm-5.9.tar.gz  garbeam@gmail.com14 years
5.8.2dwm-5.8.2.tar.gz  Anselm R Garbe15 years
5.8.1dwm-5.8.1.tar.gz  Anselm R Garbe15 years
5.8dwm-5.8.tar.gz  anselm@garbe.us15 years
5.7.2dwm-5.7.2.tar.gz  Anselm R Garbe16 years
5.7.1dwm-5.7.1.tar.gz  Anselm R Garbe16 years
5.7dwm-5.7.tar.gz  Anselm R Garbe16 years
5.6.1dwm-5.6.1.tar.gz  Anselm R Garbe16 years
5.6dwm-5.6.tar.gz  Anselm R Garbe16 years
5.5dwm-5.5.tar.gz  Anselm R Garbe16 years
5.4.1dwm-5.4.1.tar.gz  a@null17 years
5.4dwm-5.4.tar.gz  a@null17 years
5.3.1dwm-5.3.1.tar.gz  Anselm R Garbe17 years
5.3dwm-5.3.tar.gz  Anselm R Garbe17 years
5.2dwm-5.2.tar.gz  Anselm R Garbe17 years
5.1dwm-5.1.tar.gz  Anselm R Garbe17 years
5.0dwm-5.0.tar.gz  Anselm R Garbe17 years
4.9dwm-4.9.tar.gz  Anselm R Garbe17 years
4.8dwm-4.8.tar.gz  Anselm R Garbe17 years
4.7dwm-4.7.tar.gz  Anselm R. Garbe18 years
4.6dwm-4.6.tar.gz  arg@suckless.org18 years
4.5dwm-4.5.tar.gz  Anselm R. Garbe18 years
4.4.1dwm-4.4.1.tar.gz  Anselm R. Garbe18 years
4.4dwm-4.4.tar.gz  Anselm R. Garbe18 years
4.3dwm-4.3.tar.gz  arg@f00b4r18 years
4.2dwm-4.2.tar.gz  Anselm R. Garbe18 years
4.1dwm-4.1.tar.gz  Anselm R. Garbe18 years
4.0dwm-4.0.tar.gz  Anselm R. Garbe18 years
3.9dwm-3.9.tar.gz  Anselm R. Garbe18 years
3.8dwm-3.8.tar.gz  Anselm R. Garbe18 years
3.7dwm-3.7.tar.gz  Anselm R. Garbe18 years
3.6.1dwm-3.6.1.tar.gz  Anselm R. Garbe18 years
3.6dwm-3.6.tar.gz  Anselm R. Garbe18 years
3.5dwm-3.5.tar.gz  Anselm R. Garbe18 years
3.4dwm-3.4.tar.gz  Anselm R. Garbe19 years
3.3dwm-3.3.tar.gz  Anselm R. Garbe19 years
3.2.2dwm-3.2.2.tar.gz  Anselm R. Garbe19 years
3.2.1dwm-3.2.1.tar.gz  Anselm R. Garbe19 years
3.2dwm-3.2.tar.gz  Anselm R. Garbe19 years
3.1dwm-3.1.tar.gz  Anselm R. Garbe19 years
3.0dwm-3.0.tar.gz  Anselm R. Garbe19 years
2.9dwm-2.9.tar.gz  Anselm R. Garbe19 years
2.8dwm-2.8.tar.gz  arg@mig2919 years
2.7dwm-2.7.tar.gz  arg@mig2919 years
2.6dwm-2.6.tar.gz  arg@mig2919 years
2.5.1dwm-2.5.1.tar.gz  arg@mig2919 years
2.5dwm-2.5.tar.gz  arg@mig2919 years
2.4dwm-2.4.tar.gz  arg@mig2919 years
2.3dwm-2.3.tar.gz  arg@mig2919 years
2.2dwm-2.2.tar.gz  arg@mig2919 years
2.1dwm-2.1.tar.gz  arg@mig2919 years
2.0dwm-2.0.tar.gz  arg@mig2919 years
1.9dwm-1.9.tar.gz  Anselm R. Garbe19 years
1.8dwm-1.8.tar.gz  Anselm R. Garbe19 years
1.7.1dwm-1.7.1.tar.gz  Anselm R. Garbe19 years
1.7dwm-1.7.tar.gz  arg@mmvi19 years
1.6dwm-1.6.tar.gz  arg@mmvi19 years
1.5dwm-1.5.tar.gz  Anselm R. Garbe19 years
1.4dwm-1.4.tar.gz  Anselm R. Garbe19 years
1.3dwm-1.3.tar.gz  Anselm R. Garbe19 years
1.2dwm-1.2.tar.gz  Anselm R. Garbe19 years
1.1dwm-1.1.tar.gz  Anselm R. Garbe19 years
1.0dwm-1.0.tar.gz  Anselm R. Garbe19 years
0.9dwm-0.9.tar.gz  Anselm R.Garbe19 years
0.8dwm-0.8.tar.gz  Anselm R.Garbe19 years
0.7dwm-0.7.tar.gz  arg@10ksloc.org19 years
0.6dwm-0.6.tar.gz  arg@10ksloc.org19 years
0.5dwm-0.5.tar.gz  arg@10ksloc.org19 years
0.4dwm-0.4.tar.gz  arg@10ksloc.org19 years
0.3dwm-0.3.tar.gz  arg@10ksloc.org19 years
0.2dwm-0.2.tar.gz  Anselm R. Garbe19 years
0.1dwm-0.1.tar.gz  Anselm R. Garbe19 years
s has no dispatcher. let dispn = lastSon(s.ast) if dispn.kind == nkSym: let disp = dispn.sym if sfDispatcher in disp.flags: result = disp proc methodCall*(n: PNode): PNode = result = n # replace ordinary method by dispatcher method: let disp = getDispatcher(result.sons[0].sym) if disp != nil: result.sons[0].sym = disp # change the arguments to up/downcasts to fit the dispatcher's parameters: for i in countup(1, sonsLen(result)-1): result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true) else: localError(n.info, "'" & $result.sons[0] & "' lacks a dispatcher") type MethodResult = enum No, Invalid, Yes proc sameMethodBucket(a, b: PSym): MethodResult = if a.name.id != b.name.id: return if sonsLen(a.typ) != sonsLen(b.typ): return for i in countup(1, sonsLen(a.typ) - 1): var aa = a.typ.sons[i] var bb = b.typ.sons[i] while true: aa = skipTypes(aa, {tyGenericInst, tyAlias}) bb = skipTypes(bb, {tyGenericInst, tyAlias}) if aa.kind == bb.kind and aa.kind in {tyVar, tyPtr, tyRef}: aa = aa.lastSon bb = bb.lastSon else: break if sameType(aa, bb): if aa.kind == tyObject and result != Invalid: result = Yes elif aa.kind == tyObject and bb.kind == tyObject: let diff = inheritanceDiff(bb, aa) if diff < 0: if result != Invalid: result = Yes else: return No elif diff != high(int): result = Invalid else: return No else: return No if result == Yes: # check for return type: if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]): if b.typ.sons[0] != nil and b.typ.sons[0].kind == tyExpr: # infer 'auto' from the base to make it consistent: b.typ.sons[0] = a.typ.sons[0] else: return No proc attachDispatcher(s: PSym, dispatcher: PNode) = var L = s.ast.len-1 var x = s.ast.sons[L] if x.kind == nkSym and sfDispatcher in x.sym.flags: # we've added a dispatcher already, so overwrite it s.ast.sons[L] = dispatcher else: s.ast.add(dispatcher) proc createDispatcher(s: PSym): PSym = var disp = copySym(s) incl(disp.flags, sfDispatcher) excl(disp.flags, sfExported) disp.typ = copyType(disp.typ, disp.typ.owner, false) # we can't inline the dispatcher itself (for now): if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault disp.ast = copyTree(s.ast) disp.ast.sons[bodyPos] = ast.emptyNode disp.loc.r = nil if s.typ.sons[0] != nil: if disp.ast.sonsLen > resultPos: disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym) else: # We've encountered a method prototype without a filled-in # resultPos slot. We put a placeholder in there that will # be updated in fixupDispatcher(). disp.ast.addSon(ast.emptyNode) attachDispatcher(s, newSymNode(disp)) # attach to itself to prevent bugs: attachDispatcher(disp, newSymNode(disp)) return disp proc fixupDispatcher(meth, disp: PSym) = # We may have constructed the dispatcher from a method prototype # and need to augment the incomplete dispatcher with information # from later definitions, particularly the resultPos slot. Also, # the lock level of the dispatcher needs to be updated/checked # against that of the method. if disp.ast.sonsLen > resultPos and meth.ast.sonsLen > resultPos and disp.ast.sons[resultPos] == ast.emptyNode: disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos]) # The following code works only with lock levels, so we disable # it when they're not available. when declared(TLockLevel): proc `<`(a, b: TLockLevel): bool {.borrow.} proc `==`(a, b: TLockLevel): bool {.borrow.} if disp.typ.lockLevel == UnspecifiedLockLevel: disp.typ.lockLevel = meth.typ.lockLevel elif meth.typ.lockLevel != UnspecifiedLockLevel and meth.typ.lockLevel != disp.typ.lockLevel: message(meth.info, warnLockLevel, "method has lock level $1, but another method has $2" % [$meth.typ.lockLevel, $disp.typ.lockLevel]) # XXX The following code silences a duplicate warning in # checkMethodeffects() in sempass2.nim for now. if disp.typ.lockLevel < meth.typ.lockLevel: disp.typ.lockLevel = meth.typ.lockLevel proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = let L = len(g.methods) var witness: PSym for i in countup(0, L - 1): let disp = g.methods[i].dispatcher case sameMethodBucket(disp, s) of Yes: add(g.methods[i].methods, s) attachDispatcher(s, lastSon(disp.ast)) fixupDispatcher(s, disp) #echo "fixup ", disp.name.s, " ", disp.id when useEffectSystem: checkMethodEffects(disp, s) if {sfBase, sfFromGeneric} * s.flags == {sfBase} and g.methods[i].methods[0] != s: # already exists due to forwarding definition? localError(s.info, "method is not a base") return of No: discard of Invalid: if witness.isNil: witness = g.methods[i].methods[0] # create a new dispatcher: add(g.methods, (methods: @[s], dispatcher: createDispatcher(s))) #echo "adding ", s.info #if fromCache: # internalError(s.info, "no method dispatcher found") if witness != nil: localError(s.info, "invalid declaration order; cannot attach '" & s.name.s & "' to method defined here: " & $witness.info) elif sfBase notin s.flags: message(s.info, warnUseBase) proc relevantCol(methods: TSymSeq, col: int): bool = # returns true iff the position is relevant var t = methods[0].typ.sons[col].skipTypes(skipPtrs) if t.kind == tyObject: for i in countup(1, high(methods)): let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs) if not sameType(t2, t): return true proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int = for col in countup(1, sonsLen(a.typ) - 1): if contains(relevantCols, col): var aa = skipTypes(a.typ.sons[col], skipPtrs) var bb = skipTypes(b.typ.sons[col], skipPtrs) var d = inheritanceDiff(aa, bb) if (d != high(int)) and d != 0: return d proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = # we use shellsort here; fast and simple var n = len(a) var h = 1 while true: h = 3 * h + 1 if h > n: break while true: h = h div 3 for i in countup(h, n - 1): var v = a[i] var j = i while cmpSignatures(a[j - h], v, relevantCols) >= 0: a[j] = a[j - h] j = j - h if j < h: break a[j] = v if h == 1: break proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym = var base = lastSon(methods[0].ast).sym result = base var paramLen = sonsLen(base.typ) var disp = newNodeI(nkIfStmt, base.info) var ands = getSysSym("and") var iss = getSysSym("of") for meth in countup(0, high(methods)): var curr = methods[meth] # generate condition: var cond: PNode = nil for col in countup(1, paramLen - 1): if contains(relevantCols, col): var isn = newNodeIT(nkCall, base.info, getSysType(tyBool)) addSon(isn, newSymNode(iss)) addSon(isn, newSymNode(base.typ.n.sons[col].sym)) addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col])) if cond != nil: var a = newNodeIT(nkCall, base.info, getSysType(tyBool)) addSon(a, newSymNode(ands)) addSon(a, cond) addSon(a, isn) cond = a else: cond = isn var call = newNodeI(nkCall, base.info) addSon(call, newSymNode(curr)) for col in countup(1, paramLen - 1): addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym), curr.typ.sons[col], false)) var ret: PNode if base.typ.sons[0] != nil: var a = newNodeI(nkFastAsgn, base.info) addSon(a, newSymNode(base.ast.sons[resultPos].sym)) addSon(a, call) ret = newNodeI(nkReturnStmt, base.info) addSon(ret, a) else: ret = call if cond != nil: var a = newNodeI(nkElifBranch, base.info) addSon(a, cond) addSon(a, ret) addSon(disp, a) else: disp = ret result.ast.sons[bodyPos] = disp proc generateMethodDispatchers*(g: ModuleGraph): PNode = result = newNode(nkStmtList) for bucket in countup(0, len(g.methods) - 1): var relevantCols = initIntSet() for col in countup(1, sonsLen(g.methods[bucket].methods[0].typ) - 1): if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col) sortBucket(g.methods[bucket].methods, relevantCols) addSon(result, newSymNode(genDispatcher(g.methods[bucket].methods, relevantCols)))