From 569c1ce5ec7cedd2c28d3272aae92062638cad0d Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 21 Jul 2011 00:57:39 +0200 Subject: bugfix: proper cache for generic instantiations --- compiler/cgen.nim | 2 +- compiler/sem.nim | 10 +- compiler/semcall.nim | 8 - compiler/semdata.nim | 12 +- compiler/seminst.nim | 54 ++--- compiler/semthreads.nim | 13 +- compiler/trees.nim | 33 +-- doc/lib.txt | 3 + doc/nimrodc.txt | 2 +- doc/theindex.txt | 418 +++++++++++++++++++---------------- lib/pure/htmlgen.nim | 406 ++++++++++++++++++++++++++++++++++ lib/pure/matchers.nim | 51 +++++ lib/pure/os.nim | 78 +------ lib/pure/osproc.nim | 12 - lib/pure/parseopt.nim | 10 +- lib/pure/parseutils.nim | 2 +- lib/pure/regexprs.nim | 179 --------------- lib/pure/strutils.nim | 123 +++++------ lib/pure/xmlgen.nim | 411 ---------------------------------- lib/system/threads.nim | 2 +- tests/accept/run/tgenericprocvar.nim | 19 ++ todo.txt | 2 +- tools/sunset.tmpl | 2 +- web/news.txt | 22 +- web/nimrod.ini | 2 +- 25 files changed, 846 insertions(+), 1030 deletions(-) create mode 100755 lib/pure/htmlgen.nim create mode 100644 lib/pure/matchers.nim delete mode 100755 lib/pure/regexprs.nim delete mode 100755 lib/pure/xmlgen.nim create mode 100644 tests/accept/run/tgenericprocvar.nim diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 02fcce980..68e377f8b 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -15,7 +15,7 @@ import options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, - rodutils + rodutils, renderer when options.hasTinyCBackend: import tccgen diff --git a/compiler/sem.nim b/compiler/sem.nim index 19b3cc9e2..c2fbfff72 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -134,15 +134,13 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode = include semtypes, semexprs, semgnrc, semstmts proc addCodeForGenerics(c: PContext, n: PNode) = - for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1): - var it = c.generics.sons[i].sons[1] - if it.kind != nkSym: InternalError("addCodeForGenerics") - var prc = it.sym + for i in countup(lastGenericIdx, Len(generics) - 1): + var prc = generics[i].instSym if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: if prc.ast == nil or prc.ast.sons[codePos] == nil: InternalError(prc.info, "no code for " & prc.name.s) addSon(n, prc.ast) - c.lastGenericIdx = sonsLen(c.generics) + lastGenericIdx = Len(generics) proc semExprNoFlags(c: PContext, n: PNode): PNode = result = semExpr(c, n, {}) @@ -174,7 +172,7 @@ proc myOpenCached(module: PSym, filename: string, proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = result = semStmt(c, n) # BUGFIX: process newly generated generics here, not at the end! - if sonsLen(c.generics) > 0: + if lastGenericIdx < Len(generics): var a = newNodeI(nkStmtList, n.info) addCodeForGenerics(c, a) if sonsLen(a) > 0: diff --git a/compiler/semcall.nim b/compiler/semcall.nim index cf277728d..f20349c0f 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -119,12 +119,4 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = # candidateCount != 1: return explicitGenericInstError(n) else: assert false - - when false: - var x: TCandidate - initCandidate(x, s, n) - var newInst = generateInstance(c, s, x.bindings, n.info) - - markUsed(n, s) - result = newSymNode(newInst, n.info) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 9051e4726..306638d6c 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -33,16 +33,17 @@ type nestedBlockCounter*: int # whether we are in a block or not next*: PProcCon # used for stacking procedure contexts + TInstantiatedSymbol* {.final.} = object + genericSym*, instSym*: PSym + concreteTypes*: seq[PType] + PContext* = ref TContext TContext* = object of TPassContext # a context represents a module module*: PSym # the module sym belonging to the context p*: PProcCon # procedure context InstCounter*: int # to prevent endless instantiations - generics*: PNode # a list of the things to compile; list of - # nkExprEqExpr nodes which contain the - # generic symbol and the instantiated symbol + threadEntries*: TSymSeq # list of thread entries to check - lastGenericIdx*: int # used for the generics stack tab*: TSymTab # each module has its own symbol table AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot # store this info in the syms themselves!) @@ -58,6 +59,8 @@ type var gInstTypes*: TIdTable # map PType to PType +var generics*: seq[TInstantiatedSymbol] = @[] # a list of the things to compile +var lastGenericIdx*: int # used for the generics stack proc newContext*(module: PSym, nimfile: string): PContext @@ -124,7 +127,6 @@ proc newContext(module: PSym, nimfile: string): PContext = initLinkedList(result.libs) append(result.optionStack, newOptionEntry()) result.module = module - result.generics = newNode(nkStmtList) result.threadEntries = @[] result.converters = @[] result.filename = nimfile diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 3d0b672bc..6cb325290 100755 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -9,15 +9,17 @@ # This module implements the instantiation of generic procs. -proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = - if (n.kind != nkGenericParams): +proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable, + entry: var TInstantiatedSymbol) = + if n.kind != nkGenericParams: InternalError(n.info, "instantiateGenericParamList; no generic params") - for i in countup(0, sonsLen(n) - 1): + newSeq(entry.concreteTypes, n.len) + for i in countup(0, n.len - 1): var a = n.sons[i] if a.kind != nkSym: InternalError(a.info, "instantiateGenericParamList; no symbol") var q = a.sym - if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue + if q.typ.kind notin {tyTypeDesc, tyGenericParam}: continue var s = newSym(skType, q.name, getCurrOwner()) s.info = q.info incl(s.flags, sfUsed) @@ -29,24 +31,23 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = InternalError(a.info, "instantiateGenericParamList: " & q.name.s) s.typ = t addDecl(c, s) + entry.concreteTypes[i] = t -proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym = - result = nil - for i in countup(0, sonsLen(c.generics) - 1): - if c.generics.sons[i].kind != nkExprEqExpr: - InternalError(genericSym.info, "GenericCacheGet") - var a = c.generics.sons[i].sons[0].sym - if genericSym.id == a.id: - var b = c.generics.sons[i].sons[1].sym - if equalParams(b.typ.n, instSym.typ.n) == paramsEqual: - #echo "found in cache: ", getProcHeader(instSym) - return b +proc sameInstantiation(a, b: TInstantiatedSymbol): bool = + if a.genericSym.id == b.genericSym.id and + a.concreteTypes.len == b.concreteTypes.len: + for i in 0 .. < a.concreteTypes.len: + if not sameType(a.concreteTypes[i], b.concreteTypes[i]): return + result = true -proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) = - var n = newNode(nkExprEqExpr) - addSon(n, newSymNode(genericSym)) - addSon(n, newSymNode(instSym)) - addSon(c.generics, n) +proc GenericCacheGet(c: PContext, entry: var TInstantiatedSymbol): PSym = + for i in countup(0, Len(generics) - 1): + if sameInstantiation(entry, generics[i]): + result = generics[i].instSym + # checking for the concrete parameter list is wrong and unnecessary! + #if equalParams(b.typ.n, instSym.typ.n) == paramsEqual: + #echo "found in cache: ", getProcHeader(result) + return proc removeDefaultParamValues(n: PNode) = # we remove default params, because they cannot be instantiated properly @@ -81,11 +82,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, result.ast = n pushOwner(result) openScope(c.tab) - if (n.sons[genericParamsPos].kind == nkEmpty): + if n.sons[genericParamsPos].kind == nkEmpty: InternalError(n.info, "generateInstance") n.sons[namePos] = newSymNode(result) pushInfoContext(info) - instantiateGenericParamList(c, n.sons[genericParamsPos], pt) + var entry: TInstantiatedSymbol + entry.instSym = result + entry.genericSym = fn + instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry) n.sons[genericParamsPos] = ast.emptyNode # semantic checking for the parameters: if n.sons[paramsPos].kind != nkEmpty: @@ -96,10 +100,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, result.typ = newTypeS(tyProc, c) addSon(result.typ, nil) result.typ.callConv = fn.typ.callConv - var oldPrc = GenericCacheGet(c, fn, result) - if oldPrc == nil: + var oldPrc = GenericCacheGet(c, entry) + if oldPrc == nil: # add it here, so that recursive generic procs are possible: - GenericCacheAdd(c, fn, result) + generics.add(entry) addDecl(c, result) if n.sons[codePos].kind != nkEmpty: pushProcCon(c, result) diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim index b6bdc9e60..5e52aea72 100755 --- a/compiler/semthreads.nim +++ b/compiler/semthreads.nim @@ -358,6 +358,8 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner = of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef: result = toVoid + of nkExprColonExpr: + result = analyse(c, n.sons[1]) else: InternalError(n.info, "analysis not implemented for: " & $n.kind) proc analyseThreadProc*(prc: PSym) = @@ -368,17 +370,6 @@ proc analyseThreadProc*(prc: PSym) = c.mapping[formal.id] = toTheirs # thread receives foreign data! discard analyse(c, prc.ast.sons[codePos]) -when false: - proc analyseThreadCreationCall(n: PNode) = - # thread proc is second param of ``createThread``: - if n[2].kind != nkSym or n[2].sym.kind != skProc: - Message(n.info, warnAnalysisLoophole, renderTree(n)) - return - analyseProc(n[2].sym) - - proc AnalyseThread*(threadCreation: PNode) = - analyseThreadCreationCall(threadCreation) - proc needsGlobalAnalysis*: bool = result = gGlobalOptions * {optThreads, optThreadAnalysis} == {optThreads, optThreadAnalysis} diff --git a/compiler/trees.nim b/compiler/trees.nim index 76a30e3ac..7b90296ad 100755 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -12,19 +12,6 @@ import ast, astalgo, lexer, msgs, strutils, wordrecg -proc getMagic*(op: PNode): TMagic - -proc isConstExpr*(n: PNode): bool -proc flattenTree*(root: PNode, op: TMagic): PNode -proc TreeToSym*(t: PNode): PSym -proc SwapOperands*(op: PNode) -proc getOpSym*(op: PNode): PSym -proc getProcSym*(call: PNode): PSym -proc ExprStructuralEquivalent*(a, b: PNode): bool -proc sameTree*(a, b: PNode): bool -proc cyclicTree*(n: PNode): bool -# implementation - proc hasSon(father, son: PNode): bool = for i in countup(0, sonsLen(father) - 1): if father.sons[i] == son: @@ -45,11 +32,11 @@ proc cyclicTreeAux(n, s: PNode): bool = result = false delSon(s, m) -proc cyclicTree(n: PNode): bool = +proc cyclicTree*(n: PNode): bool = var s = newNodeI(nkEmpty, n.info) result = cyclicTreeAux(n, s) -proc ExprStructuralEquivalent(a, b: PNode): bool = +proc ExprStructuralEquivalent*(a, b: PNode): bool = result = false if a == b: result = true @@ -69,7 +56,7 @@ proc ExprStructuralEquivalent(a, b: PNode): bool = if not ExprStructuralEquivalent(a.sons[i], b.sons[i]): return result = true -proc sameTree(a, b: PNode): bool = +proc sameTree*(a, b: PNode): bool = result = false if a == b: result = true @@ -93,10 +80,10 @@ proc sameTree(a, b: PNode): bool = if not sameTree(a.sons[i], b.sons[i]): return result = true -proc getProcSym(call: PNode): PSym = +proc getProcSym*(call: PNode): PSym = result = call.sons[0].sym -proc getOpSym(op: PNode): PSym = +proc getOpSym*(op: PNode): PSym = if not (op.kind in {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}): result = nil else: @@ -104,7 +91,7 @@ proc getOpSym(op: PNode): PSym = if op.sons[0].Kind == nkSym: result = op.sons[0].sym else: result = nil -proc getMagic(op: PNode): TMagic = +proc getMagic*(op: PNode): TMagic = case op.kind of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkPrefix, nkPostfix, nkInfix: @@ -113,10 +100,10 @@ proc getMagic(op: PNode): TMagic = else: result = mNone else: result = mNone -proc TreeToSym(t: PNode): PSym = +proc TreeToSym*(t: PNode): PSym = result = t.sym -proc isConstExpr(n: PNode): bool = +proc isConstExpr*(n: PNode): bool = result = (n.kind in {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags) @@ -128,14 +115,14 @@ proc flattenTreeAux(d, a: PNode, op: TMagic) = else: addSon(d, copyTree(a)) -proc flattenTree(root: PNode, op: TMagic): PNode = +proc flattenTree*(root: PNode, op: TMagic): PNode = result = copyNode(root) if (getMagic(root) == op): # BUGFIX: forget to copy prc addSon(result, copyNode(root.sons[0])) flattenTreeAux(result, root, op) -proc SwapOperands(op: PNode) = +proc SwapOperands*(op: PNode) = var tmp = op.sons[1] op.sons[1] = op.sons[2] op.sons[2] = tmp diff --git a/doc/lib.txt b/doc/lib.txt index c63d5b0aa..12890d33d 100755 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -99,6 +99,9 @@ String handling It finds the sequence of ASCII characters that is the closest approximation to the Unicode string. +* `matchers `_ + This module contains various string matchers for email addresses, etc. + Generic Operating System Services --------------------------------- diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 375a65109..71f5c0387 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -175,7 +175,7 @@ Emit pragma The `emit`:idx: pragma can be used to directly affect the output of the compiler's code generator. So it makes your code unportable to other code generators/backends. Its usage is highly discouraged! However, it can be -extremely useful for interfacing with C++ or Objective C code. +extremely useful for interfacing with `C++`:idx: or `Objective C`:idx: code. Example: diff --git a/doc/theindex.txt b/doc/theindex.txt index 9a5dde744..be5d48562 100755 --- a/doc/theindex.txt +++ b/doc/theindex.txt @@ -22,15 +22,15 @@ Index `$`:idx: * `macros.html#115 `_ * `sockets.html#111 `_ - * `system.html#445 `_ - * `system.html#446 `_ - * `system.html#447 `_ - * `system.html#448 `_ * `system.html#449 `_ * `system.html#450 `_ * `system.html#451 `_ * `system.html#452 `_ - * `system.html#503 `_ + * `system.html#453 `_ + * `system.html#454 `_ + * `system.html#455 `_ + * `system.html#456 `_ + * `system.html#507 `_ * `complex.html#134 `_ * `times.html#109 `_ * `times.html#110 `_ @@ -75,9 +75,9 @@ Index * `system.html#379 `_ * `system.html#380 `_ * `system.html#381 `_ - * `system.html#487 `_ - * `system.html#488 `_ - * `system.html#489 `_ + * `system.html#491 `_ + * `system.html#492 `_ + * `system.html#493 `_ * `pegs.html#116 `_ * `ropes.html#109 `_ * `ropes.html#110 `_ @@ -165,11 +165,11 @@ Index `..`:idx: * `system.html#137 `_ * `system.html#139 `_ - * `system.html#462 `_ + * `system.html#466 `_ `/`:idx: * `system.html#328 `_ - * `system.html#578 `_ + * `system.html#582 `_ * `os.html#125 `_ * `complex.html#111 `_ * `complex.html#112 `_ @@ -202,7 +202,7 @@ Index * `system.html#360 `_ * `system.html#361 `_ * `system.html#362 `_ - * `system.html#502 `_ + * `system.html#506 `_ * `times.html#112 `_ `<%`:idx: @@ -229,7 +229,7 @@ Index * `system.html#352 `_ * `system.html#353 `_ * `system.html#354 `_ - * `system.html#501 `_ + * `system.html#505 `_ `<=`:idx: `times.html#113 `_ @@ -268,35 +268,35 @@ Index * `system.html#345 `_ * `system.html#346 `_ * `system.html#347 `_ - * `system.html#490 `_ - * `system.html#500 `_ + * `system.html#494 `_ + * `system.html#504 `_ * `complex.html#102 `_ * `unicode.html#105 `_ * `colors.html#102 `_ `=~`:idx: - `re.html#120 `_ + `complex.html#103 `_ `=~`:idx: - `regexprs.html#111 `_ + `re.html#120 `_ `=~`:idx: `pegs.html#157 `_ `=~`:idx: - `complex.html#103 `_ + `regexprs.html#111 `_ `>`:idx: `system.html#365 `_ `>%`:idx: - `system.html#444 `_ + `system.html#448 `_ `>=`:idx: `system.html#364 `_ `>=%`:idx: - `system.html#443 `_ + `system.html#447 `_ `?`:idx: `pegs.html#111 `_ @@ -309,69 +309,69 @@ Index `pegs.html#114 `_ `[]`:idx: - `ropes.html#115 `_ + * `json.html#130 `_ + * `json.html#131 `_ `[]`:idx: - * `tables.html#106 `_ - * `tables.html#119 `_ - * `tables.html#131 `_ + * `graphics.html#116 `_ + * `graphics.html#117 `_ `[]`:idx: - `xmltree.html#114 `_ + * `typeinfo.html#111 `_ + * `typeinfo.html#119 `_ + * `typeinfo.html#120 `_ `[]`:idx: - * `graphics.html#116 `_ - * `graphics.html#117 `_ + * `system.html#583 `_ + * `system.html#585 `_ + * `system.html#587 `_ + * `system.html#589 `_ `[]`:idx: - `strtabs.html#107 `_ + `xmltree.html#114 `_ `[]`:idx: - * `json.html#130 `_ - * `json.html#131 `_ + * `tables.html#106 `_ + * `tables.html#119 `_ + * `tables.html#131 `_ `[]`:idx: - `macros.html#112 `_ + `strtabs.html#107 `_ `[]`:idx: - * `system.html#579 `_ - * `system.html#581 `_ - * `system.html#583 `_ - * `system.html#585 `_ + `ropes.html#115 `_ `[]`:idx: - * `typeinfo.html#111 `_ - * `typeinfo.html#119 `_ - * `typeinfo.html#120 `_ + `macros.html#112 `_ `[]=`:idx: - `json.html#135 `_ + `strtabs.html#109 `_ `[]=`:idx: - * `typeinfo.html#112 `_ - * `typeinfo.html#118 `_ - * `typeinfo.html#121 `_ + `json.html#135 `_ `[]=`:idx: * `graphics.html#118 `_ * `graphics.html#119 `_ `[]=`:idx: - * `system.html#580 `_ - * `system.html#582 `_ * `system.html#584 `_ * `system.html#586 `_ + * `system.html#588 `_ + * `system.html#590 `_ `[]=`:idx: - * `tables.html#108 `_ - * `tables.html#121 `_ - * `tables.html#133 `_ + * `typeinfo.html#112 `_ + * `typeinfo.html#118 `_ + * `typeinfo.html#121 `_ `[]=`:idx: `macros.html#113 `_ `[]=`:idx: - `strtabs.html#109 `_ + * `tables.html#108 `_ + * `tables.html#121 `_ + * `tables.html#133 `_ `[ESC]`:idx: `manual.html#134 `_ @@ -395,10 +395,10 @@ Index `sockets.html#122 `_ `accumulateResult`:idx: - `system.html#518 `_ + `system.html#522 `_ `Acquire`:idx: - `threads.html#112 `_ + `threads.html#113 `_ `acronym`:idx: `xmlgen.html#108 `_ @@ -416,7 +416,7 @@ Index * `system.html#383 `_ * `system.html#398 `_ * `system.html#399 `_ - * `system.html#523 `_ + * `system.html#527 `_ * `parsesql.html#108 `_ * `ropes.html#113 `_ * `ropes.html#114 `_ @@ -491,6 +491,12 @@ Index `ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP`:idx: `mysql.html#318 `_ + `allocShared`:idx: + `system.html#440 `_ + + `allocShared0`:idx: + `system.html#441 `_ + `AltSep`:idx: `os.html#104 `_ @@ -567,7 +573,7 @@ Index `manual.html#212 `_ `assert`:idx: - `system.html#441 `_ + `system.html#445 `_ `assign`:idx: `typeinfo.html#143 `_ @@ -576,10 +582,10 @@ Index `macros.html#101 `_ `atomicDec`:idx: - `system.html#570 `_ + `system.html#574 `_ `atomicInc`:idx: - `system.html#569 `_ + `system.html#573 `_ `attr`:idx: `xmltree.html#129 `_ @@ -777,6 +783,9 @@ Index `ChangeFileExt`:idx: `os.html#137 `_ + `channelId`:idx: + `inboxes.html#111 `_ + `char`:idx: `system.html#110 `_ @@ -918,14 +927,9 @@ Index `clonglong`:idx: `system.html#414 `_ - `Close`:idx: - * `system.html#539 `_ - * `db_postgres.html#117 `_ - * `db_mysql.html#116 `_ - * `db_sqlite.html#117 `_ - `close`:idx: * `sockets.html#123 `_ + * `inboxes.html#110 `_ * `osproc.html#108 `_ * `lexbase.html#105 `_ * `parsecfg.html#105 `_ @@ -941,6 +945,12 @@ Index * `sphinx.html#159 `_ * `encodings.html#106 `_ + `Close`:idx: + * `system.html#543 `_ + * `db_postgres.html#117 `_ + * `db_mysql.html#116 `_ + * `db_sqlite.html#117 `_ + `closure`:idx: `manual.html#183 `_ @@ -1470,7 +1480,7 @@ Index * `re.html#122 `_ * `system.html#140 `_ * `system.html#366 `_ - * `system.html#492 `_ + * `system.html#496 `_ * `strutils.html#151 `_ * `strutils.html#152 `_ * `strutils.html#153 `_ @@ -1537,13 +1547,13 @@ Index `math.html#112 `_ `countdown`:idx: - `system.html#460 `_ + `system.html#464 `_ `countProcessors`:idx: `osproc.html#119 `_ `countup`:idx: - `system.html#461 `_ + `system.html#465 `_ `cpuEndian`:idx: `system.html#392 `_ @@ -1622,8 +1632,8 @@ Index `system.html#418 `_ `cstringArrayToSeq`:idx: - * `system.html#567 `_ - * `system.html#568 `_ + * `system.html#571 `_ + * `system.html#572 `_ `CSV`:idx: `parsecsv.html#101 `_ @@ -2010,7 +2020,7 @@ Index * `db_sqlite.html#107 `_ `dbgLineHook`:idx: - `system.html#519 `_ + `system.html#523 `_ `dbsize`:idx: `redis.html#209 `_ @@ -2027,6 +2037,9 @@ Index `dealloc`:idx: `system.html#439 `_ + `deallocShared`:idx: + `system.html#443 `_ + `debug build`:idx: `nimrodc.html#101 `_ @@ -2088,12 +2101,12 @@ Index `dfn`:idx: `xmlgen.html#125 `_ - `digits`:idx: - `pegs.html#138 `_ - `Digits`:idx: `strutils.html#104 `_ + `digits`:idx: + `pegs.html#138 `_ + `directory`:idx: `os.html#165 `_ @@ -2101,7 +2114,7 @@ Index `os.html#103 `_ `disableCache`:idx: - `ropes.html#107 `_ + `ropes.html#108 `_ `discard`:idx: `manual.html#193 `_ @@ -2188,8 +2201,8 @@ Index `system.html#157 `_ `each`:idx: - * `system.html#494 `_ - * `system.html#495 `_ + * `system.html#498 `_ + * `system.html#499 `_ `EADDRINUSE`:idx: `zmq.html#107 `_ @@ -2213,7 +2226,7 @@ Index `cgi.html#104 `_ `echo`:idx: - `system.html#524 `_ + `system.html#528 `_ `echoServ`:idx: `redis.html#200 `_ @@ -2376,7 +2389,7 @@ Index `zmq.html#114 `_ `enableCache`:idx: - `ropes.html#108 `_ + `ropes.html#107 `_ `ENamespaceErr`:idx: `xmldom.html#110 `_ @@ -2391,7 +2404,7 @@ Index `endb.html#102 `_ `EndOfFile`:idx: - * `system.html#540 `_ + * `system.html#544 `_ * `lexbase.html#101 `_ `endsWith`:idx: @@ -2727,13 +2740,13 @@ Index `manual.html#263 `_ `fieldPairs`:idx: - * `system.html#498 `_ - * `system.html#499 `_ + * `system.html#502 `_ + * `system.html#503 `_ `fields`:idx: * `typeinfo.html#117 `_ - * `system.html#496 `_ - * `system.html#497 `_ + * `system.html#500 `_ + * `system.html#501 `_ `fieldset`:idx: `xmlgen.html#130 `_ @@ -2823,7 +2836,7 @@ Index `mysql.html#218 `_ `fileHandle`:idx: - `system.html#566 `_ + `system.html#570 `_ `fileNewer`:idx: `os.html#118 `_ @@ -2857,7 +2870,7 @@ Index * `regexprs.html#110 `_ * `re.html#116 `_ * `re.html#117 `_ - * `system.html#491 `_ + * `system.html#495 `_ * `strutils.html#147 `_ * `strutils.html#148 `_ * `strutils.html#149 `_ @@ -2914,7 +2927,7 @@ Index `redis.html#213 `_ `FlushFile`:idx: - `system.html#542 `_ + `system.html#546 `_ `for`:idx: * `manual.html#222 `_ @@ -2953,35 +2966,35 @@ Index `manual.html#215 `_ `GC_disable`:idx: - `system.html#504 `_ + `system.html#508 `_ `GC_disableMarkAndSweep`:idx: - `system.html#510 `_ + `system.html#514 `_ `GC_enable`:idx: - `system.html#505 `_ + `system.html#509 `_ `GC_enableMarkAndSweep`:idx: - `system.html#509 `_ + `system.html#513 `_ `GC_fullCollect`:idx: - `system.html#506 `_ + `system.html#510 `_ `GC_getStatistics`:idx: - `system.html#511 `_ + `system.html#515 `_ `GC_ref`:idx: - * `system.html#512 `_ - * `system.html#513 `_ - * `system.html#514 `_ + * `system.html#516 `_ + * `system.html#517 `_ + * `system.html#518 `_ `GC_setStrategy`:idx: - `system.html#508 `_ + `system.html#512 `_ `GC_unref`:idx: - * `system.html#515 `_ - * `system.html#516 `_ - * `system.html#517 `_ + * `system.html#519 `_ + * `system.html#520 `_ + * `system.html#521 `_ `generalized raw string literal`:idx: `manual.html#137 `_ @@ -3081,10 +3094,10 @@ Index `encodings.html#104 `_ `getCurrentException`:idx: - `system.html#573 `_ + `system.html#577 `_ `getCurrentExceptionMsg`:idx: - `system.html#574 `_ + `system.html#578 `_ `getCurrentLine`:idx: `lexbase.html#106 `_ @@ -3125,19 +3138,19 @@ Index `os.html#170 `_ `getFilePos`:idx: - `system.html#565 `_ + `system.html#569 `_ `getFileSize`:idx: - * `system.html#557 `_ + * `system.html#561 `_ * `os.html#186 `_ + `get_float`:idx: + `sphinx.html#186 `_ + `getFloat`:idx: * `typeinfo.html#135 `_ * `json.html#109 `_ - `get_float`:idx: - `sphinx.html#186 `_ - `getFloat32`:idx: `typeinfo.html#136 `_ @@ -3145,7 +3158,7 @@ Index `typeinfo.html#137 `_ `getFreeMem`:idx: - `system.html#458 `_ + `system.html#462 `_ `getGatewayInterface`:idx: `cgi.html#114 `_ @@ -3243,7 +3256,7 @@ Index `sphinx.html#182 `_ `getOccupiedMem`:idx: - `system.html#457 `_ + `system.html#461 `_ `getopt`:idx: `parseopt.html#108 `_ @@ -3264,7 +3277,7 @@ Index `redis.html#127 `_ `getRefcount`:idx: - `system.html#453 `_ + `system.html#457 `_ `getRemoteAddr`:idx: `cgi.html#127 `_ @@ -3360,13 +3373,13 @@ Index `times.html#105 `_ `getTotalMem`:idx: - `system.html#459 `_ + `system.html#463 `_ `get_tty_password`:idx: `mysql.html#282 `_ `getTypeInfo`:idx: - `system.html#587 `_ + `system.html#591 `_ `GetValue`:idx: * `db_postgres.html#113 `_ @@ -3572,12 +3585,12 @@ Index `ident=`:idx: `macros.html#132 `_ - `IdentChars`:idx: - `strutils.html#106 `_ - `identChars`:idx: `pegs.html#140 `_ + `IdentChars`:idx: + `strutils.html#106 `_ + `identifier`:idx: `manual.html#105 `_ @@ -3650,7 +3663,7 @@ Index `manual.html#113 `_ `inf`:idx: - `system.html#454 `_ + `system.html#458 `_ `InfChecks`:idx: `manual.html#155 `_ @@ -3679,7 +3692,7 @@ Index `intsets.html#106 `_ `InitLock`:idx: - `threads.html#110 `_ + `threads.html#111 `_ `initOptParser`:idx: `parseopt.html#103 `_ @@ -3790,12 +3803,12 @@ Index `isNil`:idx: * `typeinfo.html#114 `_ - * `system.html#481 `_ - * `system.html#482 `_ - * `system.html#483 `_ - * `system.html#484 `_ * `system.html#485 `_ * `system.html#486 `_ + * `system.html#487 `_ + * `system.html#488 `_ + * `system.html#489 `_ + * `system.html#490 `_ `is_not`:idx: `system.html#370 `_ @@ -3834,12 +3847,12 @@ Index `mysql.html#255 `_ `items`:idx: - * `system.html#475 `_ - * `system.html#476 `_ - * `system.html#477 `_ - * `system.html#478 `_ * `system.html#479 `_ * `system.html#480 `_ + * `system.html#481 `_ + * `system.html#482 `_ + * `system.html#483 `_ + * `system.html#484 `_ * `ropes.html#117 `_ * `xmltree.html#115 `_ * `json.html#141 `_ @@ -3938,12 +3951,12 @@ Index * `sets.html#113 `_ * `queues.html#103 `_ - `Letters`:idx: - `strutils.html#103 `_ - `letters`:idx: `pegs.html#137 `_ + `Letters`:idx: + `strutils.html#103 `_ + `li`:idx: `xmlgen.html#148 `_ @@ -3963,7 +3976,7 @@ Index `libcurl.html#276 `_ `likely`:idx: - `system.html#575 `_ + `system.html#579 `_ `lIndex`:idx: `redis.html#152 `_ @@ -3978,8 +3991,8 @@ Index `nimrodc.html#110 `_ `lines`:idx: - * `system.html#571 `_ - * `system.html#572 `_ + * `system.html#575 `_ + * `system.html#576 `_ `lineTrace`:idx: `nimrodc.html#112 `_ @@ -4077,6 +4090,9 @@ Index `Macros`:idx: `manual.html#229 `_ + `mainThreadId`:idx: + `threads.html#109 `_ + `make_password_from_salt`:idx: `mysql.html#281 `_ @@ -4124,12 +4140,12 @@ Index `max`:idx: * `system.html#334 `_ - * `system.html#469 `_ - * `system.html#470 `_ - * `system.html#471 `_ - * `system.html#472 `_ * `system.html#473 `_ * `system.html#474 `_ + * `system.html#475 `_ + * `system.html#476 `_ + * `system.html#477 `_ + * `system.html#478 `_ `MAX_BIGINT_WIDTH`:idx: `mysql.html#194 `_ @@ -4207,12 +4223,12 @@ Index `min`:idx: * `system.html#333 `_ - * `system.html#463 `_ - * `system.html#464 `_ - * `system.html#465 `_ - * `system.html#466 `_ * `system.html#467 `_ * `system.html#468 `_ + * `system.html#469 `_ + * `system.html#470 `_ + * `system.html#471 `_ + * `system.html#472 `_ `mix`:idx: `colors.html#107 `_ @@ -4805,19 +4821,19 @@ Index `xmldom.html#158 `_ `nan`:idx: - `system.html#456 `_ + `system.html#460 `_ `NaNChecks`:idx: `manual.html#154 `_ - `Natural`:idx: - `system.html#142 `_ - `natural`:idx: `pegs.html#143 `_ + `Natural`:idx: + `system.html#142 `_ + `neginf`:idx: - `system.html#455 `_ + `system.html#459 `_ `nestList`:idx: `macros.html#152 `_ @@ -4885,7 +4901,7 @@ Index `xmltree.html#108 `_ `newException`:idx: - `system.html#525 `_ + `system.html#529 `_ `newFileStream`:idx: * `streams.html#120 `_ @@ -4925,13 +4941,13 @@ Index `newJString`:idx: `json.html#122 `_ - `newLine`:idx: - `pegs.html#123 `_ - `newline`:idx: * `manual.html#121 `_ * `pegs.html#122 `_ + `newLine`:idx: + `pegs.html#123 `_ + `NewLines`:idx: * `strutils.html#108 `_ * `lexbase.html#102 `_ @@ -5092,6 +5108,7 @@ Index `mysql.html#189 `_ `open`:idx: + * `inboxes.html#109 `_ * `lexbase.html#104 `_ * `parsecfg.html#104 `_ * `parsexml.html#107 `_ @@ -5106,9 +5123,9 @@ Index * `encodings.html#105 `_ `Open`:idx: - * `system.html#535 `_ - * `system.html#536 `_ - * `system.html#537 `_ + * `system.html#539 `_ + * `system.html#540 `_ + * `system.html#541 `_ * `db_postgres.html#118 `_ * `db_mysql.html#117 `_ * `db_sqlite.html#118 `_ @@ -5159,10 +5176,10 @@ Index `os.html#110 `_ `out of memory`:idx: - `system.html#521 `_ + `system.html#525 `_ `outOfMemHook`:idx: - `system.html#522 `_ + `system.html#526 `_ `outputStream`:idx: `osproc.html#117 `_ @@ -5229,12 +5246,12 @@ Index `parseFile`:idx: `json.html#145 `_ - `ParseFloat`:idx: - `strutils.html#134 `_ - `parseFloat`:idx: `parseutils.html#115 `_ + `ParseFloat`:idx: + `strutils.html#134 `_ + `parseHex`:idx: `parseutils.html#101 `_ @@ -5248,12 +5265,12 @@ Index `parseIdent`:idx: `parseutils.html#103 `_ - `parseInt`:idx: - `parseutils.html#113 `_ - `ParseInt`:idx: `strutils.html#132 `_ + `parseInt`:idx: + `parseutils.html#113 `_ + `parseIp4`:idx: `sockets.html#118 `_ @@ -5451,6 +5468,8 @@ Index `peek`:idx: * `inboxes.html#104 `_ * `inboxes.html#105 `_ + * `inboxes.html#114 `_ + * `inboxes.html#115 `_ `peekExitCode`:idx: `osproc.html#115 `_ @@ -5604,7 +5623,7 @@ Index `zmq.html#117 `_ `pop`:idx: - `system.html#493 `_ + `system.html#497 `_ `port`:idx: `httpserver.html#105 `_ @@ -5703,7 +5722,7 @@ Index `manual.html#243 `_ `programming by contracts`:idx: - `system.html#440 `_ + `system.html#444 `_ `PRope`:idx: `ropes.html#102 `_ @@ -5816,13 +5835,13 @@ Index `PUSED_MEM`:idx: `mysql.html#322 `_ - `PUSH`:idx: - `zmq.html#130 `_ - `push`:idx: * `math.html#140 `_ * `math.html#141 `_ + `PUSH`:idx: + `zmq.html#130 `_ + `push/pop`:idx: `manual.html#259 `_ @@ -5851,15 +5870,15 @@ Index `zmq.html#121 `_ `quit`:idx: - * `system.html#528 `_ - * `system.html#577 `_ + * `system.html#532 `_ + * `system.html#581 `_ * `redis.html#202 `_ `QuitFailure`:idx: - `system.html#527 `_ + `system.html#531 `_ `QuitSuccess`:idx: - `system.html#526 `_ + `system.html#530 `_ `quotation mark`:idx: `manual.html#128 `_ @@ -5868,7 +5887,7 @@ Index `strutils.html#150 `_ `raiseHook`:idx: - `system.html#520 `_ + `system.html#524 `_ `raiseParseErr`:idx: `json.html#121 `_ @@ -5907,23 +5926,23 @@ Index `streams.html#106 `_ `readBuffer`:idx: - `system.html#560 `_ + `system.html#564 `_ `ReadBytes`:idx: - `system.html#558 `_ + `system.html#562 `_ `readChar`:idx: - * `system.html#541 `_ + * `system.html#545 `_ * `streams.html#105 `_ `ReadChars`:idx: - `system.html#559 `_ + `system.html#563 `_ `readData`:idx: `cgi.html#109 `_ `readFile`:idx: - `system.html#543 `_ + `system.html#547 `_ `readFloat32`:idx: `streams.html#111 `_ @@ -5944,7 +5963,7 @@ Index `streams.html#107 `_ `readLine`:idx: - * `system.html#554 `_ + * `system.html#558 `_ * `streams.html#114 `_ `ReadLineFromStdin`:idx: @@ -5962,6 +5981,9 @@ Index `realloc`:idx: `system.html#438 `_ + `reallocShared`:idx: + `system.html#442 `_ + `reBinary`:idx: * `regexprs.html#116 `_ * `re.html#136 `_ @@ -5977,6 +5999,8 @@ Index * `sockets.html#137 `_ * `sockets.html#138 `_ * `inboxes.html#103 `_ + * `inboxes.html#116 `_ + * `inboxes.html#117 `_ * `zmq.html#165 `_ `recvAsync`:idx: @@ -6055,7 +6079,7 @@ Index * `re.html#134 `_ `Release`:idx: - `threads.html#113 `_ + `threads.html#114 `_ `release build`:idx: `nimrodc.html#102 `_ @@ -6106,7 +6130,7 @@ Index * `re.html#137 `_ `reopen`:idx: - `system.html#538 `_ + `system.html#542 `_ `REP`:idx: `zmq.html#126 `_ @@ -6313,6 +6337,8 @@ Index * `sockets.html#142 `_ * `inboxes.html#101 `_ * `inboxes.html#102 `_ + * `inboxes.html#112 `_ + * `inboxes.html#113 `_ * `ssl.html#104 `_ * `zmq.html#164 `_ * `zmq.html#174 `_ @@ -6435,7 +6461,7 @@ Index `os.html#171 `_ `setFilePos`:idx: - `system.html#564 `_ + `system.html#568 `_ `SET_FLAG`:idx: `mysql.html#135 `_ @@ -7345,15 +7371,15 @@ Index `manual.html#177 `_ `stderr`:idx: - `system.html#534 `_ + `system.html#538 `_ `stdin`:idx: * `lib.html#101 `_ - * `system.html#532 `_ + * `system.html#536 `_ * `rdstdin.html#101 `_ `stdout`:idx: - `system.html#533 `_ + `system.html#537 `_ `stdtmpl`:idx: `filters.html#104 `_ @@ -7495,7 +7521,7 @@ Index `osproc.html#109 `_ `swap`:idx: - `system.html#442 `_ + `system.html#446 `_ `symAddr`:idx: `dynlib.html#104 `_ @@ -7570,6 +7596,12 @@ Index `TCfgParser`:idx: `parsecfg.html#103 `_ + `TChannel`:idx: + `inboxes.html#107 `_ + + `TChannelId`:idx: + `inboxes.html#108 `_ + `TCharSet`:idx: `strutils.html#101 `_ @@ -7815,13 +7847,13 @@ Index `xmldom.html#119 `_ `TFile`:idx: - `system.html#529 `_ + `system.html#533 `_ `TFileHandle`:idx: - `system.html#531 `_ + `system.html#535 `_ `TFileMode`:idx: - `system.html#530 `_ + `system.html#534 `_ `TFilePermission`:idx: `os.html#169 `_ @@ -7845,7 +7877,7 @@ Index `strtabs.html#106 `_ `TGC_Strategy`:idx: - `system.html#507 `_ + `system.html#511 `_ `th`:idx: `xmlgen.html#175 `_ @@ -7908,7 +7940,7 @@ Index `dynlib.html#101 `_ `TLock`:idx: - `threads.html#109 `_ + `threads.html#110 `_ `TMessage`:idx: `smtp.html#102 `_ @@ -8133,7 +8165,7 @@ Index * `tut2.html#108 `_ `TryAcquire`:idx: - `threads.html#111 `_ + `threads.html#112 `_ `TryExec`:idx: * `db_postgres.html#108 `_ @@ -8361,7 +8393,7 @@ Index `os.html#112 `_ `unlikely`:idx: - `system.html#576 `_ + `system.html#580 `_ `UnloadLib`:idx: `dynlib.html#103 `_ @@ -8506,37 +8538,37 @@ Index `strutils.html#140 `_ `write`:idx: - * `system.html#545 `_ - * `system.html#546 `_ - * `system.html#547 `_ - * `system.html#548 `_ * `system.html#549 `_ * `system.html#550 `_ * `system.html#551 `_ * `system.html#552 `_ * `system.html#553 `_ + * `system.html#554 `_ + * `system.html#555 `_ + * `system.html#556 `_ + * `system.html#557 `_ * `streams.html#103 `_ * `streams.html#104 `_ * `ropes.html#118 `_ `writeBuffer`:idx: - `system.html#563 `_ + `system.html#567 `_ `writeBytes`:idx: - `system.html#561 `_ + `system.html#565 `_ `writeChars`:idx: - `system.html#562 `_ + `system.html#566 `_ `writeContentType`:idx: `cgi.html#144 `_ `writeFile`:idx: - `system.html#544 `_ + `system.html#548 `_ `writeln`:idx: - * `system.html#555 `_ - * `system.html#556 `_ + * `system.html#559 `_ + * `system.html#560 `_ `writeStatusOkTextContent`:idx: `scgi.html#107 `_ diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim new file mode 100755 index 000000000..e836bac94 --- /dev/null +++ b/lib/pure/htmlgen.nim @@ -0,0 +1,406 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2011 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements a simple `XML`:idx: and `HTML`:idx: code +## generator. Each commonly used HTML tag has a corresponding macro +## that generates a string with its HTML representation. +## +## Example: +## +## .. code-block:: nimrod +## var nim = "Nimrod" +## echo h1(a(href="http://force7.de/nimrod", nim)) +## +## Writes the string:: +## +##

Nimrod

+## + +import + macros, strutils + +const + coreAttr* = " id class title style " + eventAttr* = " onclick ondblclick onmousedown onmouseup " & + "onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup " + commonAttr* = coreAttr & eventAttr + +proc getIdent(e: PNimrodNode): string {.compileTime.} = + case e.kind + of nnkIdent: result = normalize($e.ident) + of nnkAccQuoted: result = getIdent(e[0]) + else: error("cannot extract identifier from node: " & toStrLit(e).strVal) + +proc delete[T](s: var seq[T], attr: T): bool = + var idx = find(s, attr) + if idx >= 0: + var L = s.len + s[idx] = s[L-1] + setLen(s, L-1) + result = true + +proc xmlCheckedTag*(e: PNimrodNode, tag: string, + optAttr = "", reqAttr = "", + isLeaf = false): PNimrodNode {.compileTime.} = + ## use this procedure to define a new XML tag + + # copy the attributes; when iterating over them these lists + # will be modified, so that each attribute is only given one value + var req = split(reqAttr) + var opt = split(optAttr) + result = newNimNode(nnkBracket, e) + result.add(newStrLitNode("<")) + result.add(newStrLitNode(tag)) + # first pass over attributes: + for i in 1..e.len-1: + if e[i].kind == nnkExprEqExpr: + var name = getIdent(e[i][0]) + if delete(req, name) or delete(opt, name): + result.add(newStrLitNode(" ")) + result.add(newStrLitNode(name)) + result.add(newStrLitNode("=\"")) + result.add(e[i][1]) + result.add(newStrLitNode("\"")) + else: + error("invalid attribute for '" & tag & "' element: " & name) + # check each required attribute exists: + if req.len > 0: + error(req[0] & " attribute for '" & tag & "' element expected") + if isLeaf: + for i in 1..e.len-1: + if e[i].kind != nnkExprEqExpr: + error("element " & tag & " cannot be nested") + result.add(newStrLitNode(" />")) + else: + result.add(newStrLitNode(">")) + # second pass over elements: + for i in 1..e.len-1: + if e[i].kind != nnkExprEqExpr: result.add(e[i]) + result.add(newStrLitNode("")) + result = NestList(!"&", result) + + +macro a*(e: expr): expr = + ## generates the HTML ``a`` element. + result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " & + "accesskey tabindex" & commonAttr) + +macro acronym*(e: expr): expr = + ## generates the HTML ``acronym`` element. + result = xmlCheckedTag(e, "acronym", commonAttr) + +macro address*(e: expr): expr = + ## generates the HTML ``address`` element. + result = xmlCheckedTag(e, "address", commonAttr) + +macro area*(e: expr): expr = + ## generates the HTML ``area`` element. + result = xmlCheckedTag(e, "area", "shape coords href nohref" & + " accesskey tabindex" & commonAttr, "alt", true) + +macro b*(e: expr): expr = + ## generates the HTML ``b`` element. + result = xmlCheckedTag(e, "b", commonAttr) + +macro base*(e: expr): expr = + ## generates the HTML ``base`` element. + result = xmlCheckedTag(e, "base", "", "href", true) + +macro big*(e: expr): expr = + ## generates the HTML ``big`` element. + result = xmlCheckedTag(e, "big", commonAttr) + +macro blockquote*(e: expr): expr = + ## generates the HTML ``blockquote`` element. + result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr) + +macro body*(e: expr): expr = + ## generates the HTML ``body`` element. + result = xmlCheckedTag(e, "body", commonAttr) + +macro br*(e: expr): expr = + ## generates the HTML ``br`` element. + result = xmlCheckedTag(e, "br", "", "", true) + +macro button*(e: expr): expr = + ## generates the HTML ``button`` element. + result = xmlCheckedTag(e, "button", "accesskey tabindex " & + "disabled name type value" & commonAttr) + +macro caption*(e: expr): expr = + ## generates the HTML ``caption`` element. + result = xmlCheckedTag(e, "caption", commonAttr) + +macro cite*(e: expr): expr = + ## generates the HTML ``cite`` element. + result = xmlCheckedTag(e, "cite", commonAttr) + +macro code*(e: expr): expr = + ## generates the HTML ``code`` element. + result = xmlCheckedTag(e, "code", commonAttr) + +macro col*(e: expr): expr = + ## generates the HTML ``col`` element. + result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true) + +macro colgroup*(e: expr): expr = + ## generates the HTML ``colgroup`` element. + result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr) + +macro dd*(e: expr): expr = + ## generates the HTML ``dd`` element. + result = xmlCheckedTag(e, "dd", commonAttr) + +macro del*(e: expr): expr = + ## generates the HTML ``del`` element. + result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr) + +macro dfn*(e: expr): expr = + ## generates the HTML ``dfn`` element. + result = xmlCheckedTag(e, "dfn", commonAttr) + +macro `div`*(e: expr): expr = + ## generates the HTML ``div`` element. + result = xmlCheckedTag(e, "div", commonAttr) + +macro dl*(e: expr): expr = + ## generates the HTML ``dl`` element. + result = xmlCheckedTag(e, "dl", commonAttr) + +macro dt*(e: expr): expr = + ## generates the HTML ``dt`` element. + result = xmlCheckedTag(e, "dt", commonAttr) + +macro em*(e: expr): expr = + ## generates the HTML ``em`` element. + result = xmlCheckedTag(e, "em", commonAttr) + +macro fieldset*(e: expr): expr = + ## generates the HTML ``fieldset`` element. + result = xmlCheckedTag(e, "fieldset", commonAttr) + +macro form*(e: expr): expr = + ## generates the HTML ``form`` element. + result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & + commonAttr, "action") + +macro h1*(e: expr): expr = + ## generates the HTML ``h1`` element. + result = xmlCheckedTag(e, "h1", commonAttr) + +macro h2*(e: expr): expr = + ## generates the HTML ``h2`` element. + result = xmlCheckedTag(e, "h2", commonAttr) + +macro h3*(e: expr): expr = + ## generates the HTML ``h3`` element. + result = xmlCheckedTag(e, "h3", commonAttr) + +macro h4*(e: expr): expr = + ## generates the HTML ``h4`` element. + result = xmlCheckedTag(e, "h4", commonAttr) + +macro h5*(e: expr): expr = + ## generates the HTML ``h5`` element. + result = xmlCheckedTag(e, "h5", commonAttr) + +macro h6*(e: expr): expr = + ## generates the HTML ``h6`` element. + result = xmlCheckedTag(e, "h6", commonAttr) + +macro head*(e: expr): expr = + ## generates the HTML ``head`` element. + result = xmlCheckedTag(e, "head", "profile") + +macro html*(e: expr): expr = + ## generates the HTML ``html`` element. + result = xmlCheckedTag(e, "html", "", "xmlns") + +macro hr*(e: expr): expr = + ## generates the HTML ``hr`` element. + result = xmlCheckedTag(e, "hr", commonAttr, "", true) + +macro i*(e: expr): expr = + ## generates the HTML ``i`` element. + result = xmlCheckedTag(e, "i", commonAttr) + +macro img*(e: expr): expr = + ## generates the HTML ``img`` element. + result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true) + +macro input*(e: expr): expr = + ## generates the HTML ``input`` element. + result = xmlCheckedTag(e, "input", "name type value checked maxlength src" & + " alt accept disabled readonly accesskey tabindex" & commonAttr, "", true) + +macro ins*(e: expr): expr = + ## generates the HTML ``ins`` element. + result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr) + +macro kbd*(e: expr): expr = + ## generates the HTML ``kbd`` element. + result = xmlCheckedTag(e, "kbd", commonAttr) + +macro label*(e: expr): expr = + ## generates the HTML ``label`` element. + result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr) + +macro legend*(e: expr): expr = + ## generates the HTML ``legend`` element. + result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr) + +macro li*(e: expr): expr = + ## generates the HTML ``li`` element. + result = xmlCheckedTag(e, "li", commonAttr) + +macro link*(e: expr): expr = + ## generates the HTML ``link`` element. + result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & + commonAttr, "", true) + +macro map*(e: expr): expr = + ## generates the HTML ``map`` element. + result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false) + +macro meta*(e: expr): expr = + ## generates the HTML ``meta`` element. + result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true) + +macro noscript*(e: expr): expr = + ## generates the HTML ``noscript`` element. + result = xmlCheckedTag(e, "noscript", commonAttr) + +macro `object`*(e: expr): expr = + ## generates the HTML ``object`` element. + result = xmlCheckedTag(e, "object", "classid data codebase declare type " & + "codetype archive standby width height name tabindex" & commonAttr) + +macro ol*(e: expr): expr = + ## generates the HTML ``ol`` element. + result = xmlCheckedTag(e, "ol", commonAttr) + +macro optgroup*(e: expr): expr = + ## generates the HTML ``optgroup`` element. + result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false) + +macro option*(e: expr): expr = + ## generates the HTML ``option`` element. + result = xmlCheckedTag(e, "option", "selected value" & commonAttr) + +macro p*(e: expr): expr = + ## generates the HTML ``p`` element. + result = xmlCheckedTag(e, "p", commonAttr) + +macro param*(e: expr): expr = + ## generates the HTML ``param`` element. + result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true) + +macro pre*(e: expr): expr = + ## generates the HTML ``pre`` element. + result = xmlCheckedTag(e, "pre", commonAttr) + +macro q*(e: expr): expr = + ## generates the HTML ``q`` element. + result = xmlCheckedTag(e, "q", "cite" & commonAttr) + +macro samp*(e: expr): expr = + ## generates the HTML ``samp`` element. + result = xmlCheckedTag(e, "samp", commonAttr) + +macro script*(e: expr): expr = + ## generates the HTML ``script`` element. + result = xmlCheckedTag(e, "script", "src charset defer", "type", false) + +macro select*(e: expr): expr = + ## generates the HTML ``select`` element. + result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & + commonAttr) + +macro small*(e: expr): expr = + ## generates the HTML ``small`` element. + result = xmlCheckedTag(e, "small", commonAttr) + +macro span*(e: expr): expr = + ## generates the HTML ``span`` element. + result = xmlCheckedTag(e, "span", commonAttr) + +macro strong*(e: expr): expr = + ## generates the HTML ``strong`` element. + result = xmlCheckedTag(e, "strong", commonAttr) + +macro style*(e: expr): expr = + ## generates the HTML ``style`` element. + result = xmlCheckedTag(e, "style", "media title", "type") + +macro sub*(e: expr): expr = + ## generates the HTML ``sub`` element. + result = xmlCheckedTag(e, "sub", commonAttr) + +macro sup*(e: expr): expr = + ## generates the HTML ``sup`` element. + result = xmlCheckedTag(e, "sup", commonAttr) + +macro table*(e: expr): expr = + ## generates the HTML ``table`` element. + result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" & + " frame rules width" & commonAttr) + +macro tbody*(e: expr): expr = + ## generates the HTML ``tbody`` element. + result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr) + +macro td*(e: expr): expr = + ## generates the HTML ``td`` element. + result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" & + " align valign" & commonAttr) + +macro textarea*(e: expr): expr = + ## generates the HTML ``textarea`` element. + result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" & + " tabindex" & commonAttr, "rows cols", false) + +macro tfoot*(e: expr): expr = + ## generates the HTML ``tfoot`` element. + result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr) + +macro th*(e: expr): expr = + ## generates the HTML ``th`` element. + result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" & + " align valign" & commonAttr) + +macro thead*(e: expr): expr = + ## generates the HTML ``thead`` element. + result = xmlCheckedTag(e, "thead", "align valign" & commonAttr) + +macro title*(e: expr): expr = + ## generates the HTML ``title`` element. + result = xmlCheckedTag(e, "title") + +macro tr*(e: expr): expr = + ## generates the HTML ``tr`` element. + result = xmlCheckedTag(e, "tr", "align valign" & commonAttr) + +macro tt*(e: expr): expr = + ## generates the HTML ``tt`` element. + result = xmlCheckedTag(e, "tt", commonAttr) + +macro ul*(e: expr): expr = + ## generates the HTML ``ul`` element. + result = xmlCheckedTag(e, "ul", commonAttr) + +macro `var`*(e: expr): expr = + ## generates the HTML ``var`` element. + result = xmlCheckedTag(e, "var", commonAttr) + +when isMainModule: + var nim = "Nimrod" + echo h1(a(href="http://force7.de/nimrod", nim)) + diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim new file mode 100644 index 000000000..f49538737 --- /dev/null +++ b/lib/pure/matchers.nim @@ -0,0 +1,51 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2011 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module contains various string matchers for email addresses, etc. +{.deadCodeElim: on.} + +{.push debugger:off .} # the user does not want to trace a part + # of the standard library! + +include "system/inclrtl" + +import strutils + +proc validEmailAddress*(s: string): bool {.noSideEffect, + rtl, extern: "nsuValidEmailAddress".} = + ## returns true if `s` seems to be a valid e-mail address. + ## The checking also uses a domain list. + const + chars = Letters + Digits + {'!','#','$','%','&', + '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'} + var i = 0 + if s[i] notin chars or s[i] == '.': return false + while s[i] in chars: + if s[i] == '.' and s[i+1] == '.': return false + inc(i) + if s[i] != '@': return false + var j = len(s)-1 + if s[j] notin letters: return false + while j >= i and s[j] in letters: dec(j) + inc(i) # skip '@' + while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) + if s[i] != '\0': return false + + var x = substr(s, j+1) + if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true + case toLower(x) + of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name", + "aero", "jobs", "museum": return true + return false + +when isMainModule: + assert "wuseldusel@codehome.com".validEmailAddress + +{.pop.} + diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 2b2cb1ba7..f33950376 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -351,23 +351,6 @@ proc `/` * (head, tail: string): string {.noSideEffect.} = ## The same as ``joinPath(head, tail)`` return joinPath(head, tail) -proc SplitPath*(path: string, head, tail: var string) {.noSideEffect, - deprecated.} = - ## **Deprecated since version 0.8.2**: use the version that returns a tuple - ## instead - var - sepPos = -1 - for i in countdown(len(path)-1, 0): - if path[i] in {dirsep, altsep}: - sepPos = i - break - if sepPos >= 0: - head = substr(path, 0, sepPos-1) - tail = substr(path, sepPos+1) - else: - head = "" - tail = path # make a string copy here - proc SplitPath*(path: string): tuple[head, tail: string] {. noSideEffect, rtl, extern: "nos$1".} = ## Splits a directory into (head, tail), so that @@ -466,13 +449,6 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {. result.name = substr(path, sepPos+1, dotPos-1) result.ext = substr(path, dotPos) -proc extractDir*(path: string): string {.noSideEffect, deprecated.} = - ## Extracts the directory of a given path. This is almost the - ## same as the `head` result of `splitPath`, except that - ## ``extractDir("/usr/lib/") == "/usr/lib/"``. - ## **Deprecated since version 0.8.2**: Use ``splitFile(path).dir`` instead. - result = splitFile(path).dir - proc extractFilename*(path: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Extracts the filename of a given `path`. This is the same as @@ -495,37 +471,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1".} = if res == nil: OSError() result = $res c_free(res) - -proc SplitFilename*(filename: string, name, extension: var string) {. - noSideEffect, deprecated.} = - ## Splits a filename into (name, extension), so that - ## ``name & extension == filename``. - ## - ## Example: After ``SplitFilename("usr/local/nimrodc.html", name, ext)``, - ## `name` is "usr/local/nimrodc" and `ext` is ".html". - ## If the file has no extension, extension is the empty string. - ## **Deprecated since version 0.8.2**: Use ``splitFile(filename)`` instead. - var extPos = searchExtPos(filename) - if extPos >= 0: - name = substr(filename, 0, extPos-1) - extension = substr(filename, extPos) - else: - name = filename # make a string copy here - extension = "" - -proc extractFileExt*(filename: string): string {.noSideEffect, deprecated.} = - ## Extracts the file extension of a given `filename`. This is the - ## same as the `extension` result of `splitFilename`. - ## **Deprecated since version 0.8.2**: Use ``splitFile(filename).ext`` - ## instead. - result = splitFile(filename).ext - -proc extractFileTrunk*(filename: string): string {.noSideEffect, deprecated.} = - ## Extracts the file name of a given `filename`. This removes any - ## directory information and the file extension. - ## **Deprecated since version 0.8.2**: Use ``splitFile(path).name`` instead. - result = splitFile(filename).name - + proc ChangeFileExt*(filename, ext: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Changes the file extension to `ext`. @@ -551,11 +497,6 @@ proc addFileExt*(filename, ext: string): string {. if extPos < 0: result = filename & normExt(ext) else: result = filename -proc AppendFileExt*(filename, ext: string): string {. - noSideEffect, deprecated.} = - ## **Deprecated since version 0.8.2**: Use `addFileExt` instead. - result = addFileExt(filename, ext) - proc cmpPaths*(pathA, pathB: string): int {. noSideEffect, rtl, extern: "nos$1".} = ## Compares two paths. @@ -661,10 +602,6 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1".} = ## Removes the `file`. If this fails, `EOS` is raised. if cremove(file) != 0'i32: OSError() -proc executeShellCommand*(command: string): int {.deprecated.} = - ## **Deprecated since version 0.8.2**: Use `execShellCmd` instead. - result = csystem(command) - proc execShellCmd*(command: string): int {.rtl, extern: "nos$1".} = ## Executes a `shell command`:idx:. ## @@ -781,15 +718,6 @@ proc putEnv*(key, val: string) = if SetEnvironmentVariableA(key, val) == 0'i32: OSError() -iterator iterOverEnvironment*(): tuple[key, value: string] {.deprecated.} = - ## Iterate over all environments variables. In the first component of the - ## tuple is the name of the current variable stored, in the second its value. - ## **Deprecated since version 0.8.2**: Use `envPairs` instead. - getEnvVarsC() - for i in 0..high(environment): - var p = find(environment[i], '=') - yield (substr(environment[i], 0, p-1), substr(environment[i], p+1)) - iterator envPairs*(): tuple[key, value: string] = ## Iterate over all `environments variables`:idx:. In the first component ## of the tuple is the name of the current variable stored, in the second @@ -837,10 +765,6 @@ type pcDir, ## path refers to a directory pcLinkToDir ## path refers to a symbolic link to a directory -const - pcDirectory* {.deprecated.} = pcDir ## deprecated alias - pcLinkToDirectory* {.deprecated.} = pcLinkToDir ## deprecated alias - iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] = ## walks over the directory `dir` and yields for each directory or file in ## `dir`. The component type and full path for each item is returned. diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 281615881..6add08d26 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -46,22 +46,10 @@ proc execProcess*(command: string, ## A convenience procedure that executes ``command`` with ``startProcess`` ## and returns its output as a string. -proc executeProcess*(command: string, - options: set[TProcessOption] = {poStdErrToStdOut, - poUseShell}): string {. - deprecated.} = - ## **Deprecated since version 0.8.2**: Use `execProcess` instead. - result = execProcess(command, options) - proc execCmd*(command: string): int {.rtl, extern: "nosp$1".} ## Executes ``command`` and returns its error code. Standard input, output, ## error streams are inherited from the calling process. -proc executeCommand*(command: string): int {.deprecated.} = - ## **Deprecated since version 0.8.2**: Use `execCmd` instead. - result = execCmd(command) - - proc startProcess*(command: string, workingDir: string = "", args: openarray[string] = [], diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index c4625c161..1981c9242 100755 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -53,10 +53,6 @@ when defined(os.ParamCount): result.key = "" result.val = "" - proc init*(cmdline: string = ""): TOptParser {.deprecated.} = - ## **Deprecated since version 0.8.2**: Use `initOptParser` instead. - result = initOptParser(cmdline) - proc parseWord(s: string, i: int, w: var string, delim: TCharSet = {'\x09', ' ', '\0'}): int = result = i @@ -128,10 +124,6 @@ proc cmdLineRest*(p: TOptParser): string {. ## retrieves the rest of the command line that has not been parsed yet. result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)) -proc getRestOfCommandLine*(p: TOptParser): string {.deprecated.} = - ## **Deprecated since version 0.8.2**: Use `cmdLineRest` instead. - result = cmdLineRest(p) - when defined(initOptParser): iterator getopt*(): tuple[kind: TCmdLineKind, key, val: string] = diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index a7776bd5f..d3346ecde 100755 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. diff --git a/lib/pure/regexprs.nim b/lib/pure/regexprs.nim deleted file mode 100755 index 2969098f5..000000000 --- a/lib/pure/regexprs.nim +++ /dev/null @@ -1,179 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2009 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## Regular expression support for Nimrod. -## Currently this module is implemented by providing a wrapper around the -## `PRCE (Perl-Compatible Regular Expressions) `_ -## C library. This means that your application will depend on the PRCE -## library's licence when using this module, which should not be a problem -## though. -## PRCE's licence follows: -## -## .. include:: ../doc/regexprs.txt -## - -# This is not just a convenient wrapper for the pcre library; the -# API will stay the same if the implementation should change. - -{.deprecated.} - -import - pcre, strutils - -type - EInvalidRegEx* = object of EInvalidValue - ## is raised if the pattern is no valid regular expression. - -const - MaxSubpatterns* = 10 - ## defines the maximum number of subpatterns that can be captured. - ## More subpatterns cannot be captured! - -proc match*(s, pattern: string, matches: var openarray[string], - start: int = 0): bool - ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and - ## the captured substrings in the array ``matches``. If it does not - ## match, nothing is written into ``matches`` and ``false`` is - ## returned. - -proc match*(s, pattern: string, start: int = 0): bool - ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``. - -proc matchLen*(s, pattern: string, matches: var openarray[string], - start: int = 0): int - ## the same as ``match``, but it returns the length of the match, - ## if there is no match, -1 is returned. Note that a match length - ## of zero can happen. - -proc find*(s, pattern: string, matches: var openarray[string], - start: int = 0): bool - ## returns ``true`` if ``pattern`` occurs in ``s`` and the captured - ## substrings in the array ``matches``. If it does not match, nothing - ## is written into ``matches``. - -proc find*(s, pattern: string, start: int = 0): bool - ## returns ``true`` if ``pattern`` occurs in ``s``. - -proc rawCompile(pattern: string, flags: cint): PPcre = - var - msg: CString - offset: cint - com = pcre.Compile(pattern, flags, addr(msg), addr(offset), nil) - if com == nil: - var e: ref EInvalidRegEx - new(e) - e.msg = $msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n" - raise e - return com - -proc matchOrFind(s: string, pattern: PPcre, matches: var openarray[string], - start: cint): cint = - var - rawMatches: array [0..maxSubpatterns * 3 - 1, cint] - res = int(pcre.Exec(pattern, nil, s, len(s), start, 0, - cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)) - dealloc(pattern) - if res < 0: return res - for i in 0..res-1: - var - a = rawMatches[i * 2] - b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i] = substr(s, a, int(b)-1) - else: matches[i] = "" - return res - -proc matchOrFind(s: string, pattern: PPcre, start: cint): cint = - var - rawMatches: array [0..maxSubpatterns * 3 - 1, cint] - res = pcre.Exec(pattern, nil, s, len(s), start, 0, - cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) - dealloc(pattern) - return res - -proc match(s, pattern: string, matches: var openarray[string], - start: int = 0): bool = - return matchOrFind(s, rawCompile(pattern, PCRE.ANCHORED), - matches, start) >= 0'i32 - -proc matchLen(s, pattern: string, matches: var openarray[string], - start: int = 0): int = - return matchOrFind(s, rawCompile(pattern, PCRE.ANCHORED), matches, start) - -proc find(s, pattern: string, matches: var openarray[string], - start: int = 0): bool = - return matchOrFind(s, rawCompile(pattern, PCRE.MULTILINE), - matches, start) >= 0'i32 - -proc match(s, pattern: string, start: int = 0): bool = - return matchOrFind(s, rawCompile(pattern, PCRE.ANCHORED), start) >= 0'i32 - -proc find(s, pattern: string, start: int = 0): bool = - return matchOrFind(s, rawCompile(pattern, PCRE.MULTILINE), start) >= 0'i32 - -template `=~` *(s, pattern: expr): expr = - ## This calls ``match`` with an implicit declared ``matches`` array that - ## can be used in the scope of the ``=~`` call: - ## - ## .. code-block:: nimrod - ## - ## if line =~ r"\s*(\w+)\s*\=\s*(\w+)": - ## # matches a key=value pair: - ## echo("Key: ", matches[1]) - ## echo("Value: ", matches[2]) - ## elif line =~ r"\s*(\#.*)": - ## # matches a comment - ## # note that the implicit ``matches`` array is different from the - ## # ``matches`` array of the first branch - ## echo("comment: ", matches[1]) - ## else: - ## echo("syntax error") - ## - when not definedInScope(matches): - var matches: array[0..maxSubPatterns-1, string] - match(s, pattern, matches) - - -const ## common regular expressions - reIdentifier* = r"\b[a-zA-Z_][a-zA-Z_0-9]*\b" ## describes an identifier - reNatural* = r"\b\d+\b" ## describes a natural number - reInteger* = r"\b[-+]?\d+\b" ## describes an integer - reHex* = r"\b0[xX][0-9a-fA-F]+\b" ## describes a hexadecimal number - reBinary* = r"\b0[bB][01]+\b" ## describes a binary number (example: 0b11101) - reOctal* = r"\b0[oO][0-7]+\b" ## describes an octal number (example: 0o777) - reFloat* = r"\b[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\b" - ## describes a floating point number - reEmail* = r"\b[a-zA-Z0-9!#$%&'*+/=?^_`{|}~\-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)" & - r"*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+(?:[a-zA-Z]{2}|com|org|" & - r"net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\b" - ## describes a common email address - reURL* = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms\-help):" & - r"((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b" - ## describes an URL - -proc verbose*(pattern: string): string {.noSideEffect.} = - ## deletes whitespace from a pattern that is not escaped or in a character - ## class. This is modelled after Perl's ``/x`` modifier. - result = "" - var i = 0 - while i < pattern.len: - case pattern[i] - of ' ', '\t': - inc i - of '\\': - add result, '\\' - add result, pattern[i+1] - inc i, 2 - of '[': - while pattern[i] != ']' and pattern[i] != '\0': - add result, pattern[i] - inc i - else: - add result, pattern[i] - inc i - diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 58e1e5fed..9b4b09fae 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -480,40 +480,40 @@ proc align*(s: string, count: int): string {. for i in spaces..count-1: result[i] = s[i-spaces] else: result = s - -iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ - token: string, isSep: bool] = - ## Tokenizes the string `s` into substrings. - ## - ## Substrings are separated by a substring containing only `seps`. - ## Examples: - ## - ## .. code-block:: nimrod - ## for word in tokenize(" this is an example "): - ## writeln(stdout, word) - ## - ## Results in: - ## - ## .. code-block:: nimrod - ## (" ", true) - ## ("this", false) - ## (" ", true) - ## ("is", false) - ## (" ", true) - ## ("an", false) - ## (" ", true) - ## ("example", false) - ## (" ", true) - var i = 0 - while true: - var j = i - var isSep = s[j] in seps - while j < s.len and (s[j] in seps) == isSep: inc(j) - if j > i: - yield (substr(s, i, j-1), isSep) - else: - break - i = j + +iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ + token: string, isSep: bool] = + ## Tokenizes the string `s` into substrings. + ## + ## Substrings are separated by a substring containing only `seps`. + ## Examples: + ## + ## .. code-block:: nimrod + ## for word in tokenize(" this is an example "): + ## writeln(stdout, word) + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## (" ", true) + ## ("this", false) + ## (" ", true) + ## ("is", false) + ## (" ", true) + ## ("an", false) + ## (" ", true) + ## ("example", false) + ## (" ", true) + var i = 0 + while true: + var j = i + var isSep = s[j] in seps + while j < s.len and (s[j] in seps) == isSep: inc(j) + if j > i: + yield (substr(s, i, j-1), isSep) + else: + break + i = j proc wordWrap*(s: string, maxLineWidth = 80, splitLongWords = true, @@ -544,6 +544,33 @@ proc wordWrap*(s: string, maxLineWidth = 80, SpaceLeft = SpaceLeft - len(Word) result.add(word) +proc unindent*(s: string, eatAllIndent = false): string {. + noSideEffect, rtl, extern: "nsuUnindent".} = + ## unindents `s`. + result = newStringOfCap(s.len) + var i = 0 + var pattern = true + var indent = 0 + while s[i] == ' ': inc i + var level = if i == 0: -1 else: i + while i < s.len: + if s[i] == ' ': + if i > 0 and s[i-1] in {'\l', '\c'}: + pattern = true + indent = 0 + if pattern: + inc(indent) + if indent > level and not eatAllIndent: + result.add(s[i]) + if level < 0: level = indent + else: + # a space somewhere: do not delete + result.add(s[i]) + else: + pattern = false + result.add(s[i]) + inc i + proc startsWith*(s, prefix: string): bool {.noSideEffect, rtl, extern: "nsuStartsWith".} = ## Returns true iff ``s`` starts with ``prefix``. @@ -827,34 +854,6 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, of '\"': add(result, "\\\"") else: add(result, c) add(result, suffix) - -proc validEmailAddress*(s: string): bool {.noSideEffect, - rtl, extern: "nsuValidEmailAddress".} = - ## returns true if `s` seems to be a valid e-mail address. - ## The checking also uses a domain list. - ## Note: This will be moved to another module soon. - const - chars = Letters + Digits + {'!','#','$','%','&', - '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'} - var i = 0 - if s[i] notin chars or s[i] == '.': return false - while s[i] in chars: - if s[i] == '.' and s[i+1] == '.': return false - inc(i) - if s[i] != '@': return false - var j = len(s)-1 - if s[j] notin letters: return false - while j >= i and s[j] in letters: dec(j) - inc(i) # skip '@' - while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) - if s[i] != '\0': return false - - var x = substr(s, j+1) - if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true - case toLower(x) - of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name", - "aero", "jobs", "museum": return true - return false proc validIdentifier*(s: string): bool {.noSideEffect, rtl, extern: "nsuValidIdentifier".} = diff --git a/lib/pure/xmlgen.nim b/lib/pure/xmlgen.nim deleted file mode 100755 index d1fdcdd57..000000000 --- a/lib/pure/xmlgen.nim +++ /dev/null @@ -1,411 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements a simple `XML`:idx: and `HTML`:idx: code -## generator. Each commonly used HTML tag has a corresponding macro -## that generates a string with its HTML representation. -## -## Example: -## -## .. code-block:: nimrod -## var nim = "Nimrod" -## echo h1(a(href="http://force7.de/nimrod", nim)) -## -## Writes the string:: -## -##

Nimrod

-## -## **Deprecated since version 0.8.8.** Use the macro ``<>`` in xmltree -## instead. - -{.deprecated.} - -import - macros, strutils - -const - coreAttr* = " id class title style " - eventAttr* = " onclick ondblclick onmousedown onmouseup " & - "onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup " - commonAttr* = coreAttr & eventAttr - -proc getIdent(e: PNimrodNode): string {.compileTime.} = - case e.kind - of nnkIdent: result = normalize($e.ident) - of nnkAccQuoted: result = getIdent(e[0]) - else: error("cannot extract identifier from node: " & toStrLit(e).strVal) - -proc delete[T](s: var seq[T], attr: T): bool = - var idx = find(s, attr) - if idx >= 0: - var L = s.len - s[idx] = s[L-1] - setLen(s, L-1) - result = true - -proc xmlCheckedTag*(e: PNimrodNode, tag: string, - optAttr = "", reqAttr = "", - isLeaf = false): PNimrodNode {.compileTime.} = - ## use this procedure to define a new XML tag - - # copy the attributes; when iterating over them these lists - # will be modified, so that each attribute is only given one value - var req = split(reqAttr) - var opt = split(optAttr) - echo "##", optAttr, "##", opt.len - result = newNimNode(nnkBracket, e) - result.add(newStrLitNode("<")) - result.add(newStrLitNode(tag)) - # first pass over attributes: - for i in 1..e.len-1: - if e[i].kind == nnkExprEqExpr: - var name = getIdent(e[i][0]) - if delete(req, name) or delete(opt, name): - result.add(newStrLitNode(" ")) - result.add(newStrLitNode(name)) - result.add(newStrLitNode("=\"")) - result.add(e[i][1]) - result.add(newStrLitNode("\"")) - else: - error("invalid attribute for '" & tag & "' element: " & name) - # check each required attribute exists: - if req.len > 0: - error(req[0] & " attribute for '" & tag & "' element expected") - if isLeaf: - for i in 1..e.len-1: - if e[i].kind != nnkExprEqExpr: - error("element " & tag & " cannot be nested") - result.add(newStrLitNode(" />")) - else: - result.add(newStrLitNode(">")) - # second pass over elements: - for i in 1..e.len-1: - if e[i].kind != nnkExprEqExpr: result.add(e[i]) - result.add(newStrLitNode("")) - result = NestList(!"&", result) - - -macro a*(e: expr): expr = - ## generates the HTML ``a`` element. - result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " & - "accesskey tabindex" & commonAttr) - -macro acronym*(e: expr): expr = - ## generates the HTML ``acronym`` element. - result = xmlCheckedTag(e, "acronym", commonAttr) - -macro address*(e: expr): expr = - ## generates the HTML ``address`` element. - result = xmlCheckedTag(e, "address", commonAttr) - -macro area*(e: expr): expr = - ## generates the HTML ``area`` element. - result = xmlCheckedTag(e, "area", "shape coords href nohref" & - " accesskey tabindex" & commonAttr, "alt", true) - -macro b*(e: expr): expr = - ## generates the HTML ``b`` element. - result = xmlCheckedTag(e, "b", commonAttr) - -macro base*(e: expr): expr = - ## generates the HTML ``base`` element. - result = xmlCheckedTag(e, "base", "", "href", true) - -macro big*(e: expr): expr = - ## generates the HTML ``big`` element. - result = xmlCheckedTag(e, "big", commonAttr) - -macro blockquote*(e: expr): expr = - ## generates the HTML ``blockquote`` element. - result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr) - -macro body*(e: expr): expr = - ## generates the HTML ``body`` element. - result = xmlCheckedTag(e, "body", commonAttr) - -macro br*(e: expr): expr = - ## generates the HTML ``br`` element. - result = xmlCheckedTag(e, "br", "", "", true) - -macro button*(e: expr): expr = - ## generates the HTML ``button`` element. - result = xmlCheckedTag(e, "button", "accesskey tabindex " & - "disabled name type value" & commonAttr) - -macro caption*(e: expr): expr = - ## generates the HTML ``caption`` element. - result = xmlCheckedTag(e, "caption", commonAttr) - -macro cite*(e: expr): expr = - ## generates the HTML ``cite`` element. - result = xmlCheckedTag(e, "cite", commonAttr) - -macro code*(e: expr): expr = - ## generates the HTML ``code`` element. - result = xmlCheckedTag(e, "code", commonAttr) - -macro col*(e: expr): expr = - ## generates the HTML ``col`` element. - result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true) - -macro colgroup*(e: expr): expr = - ## generates the HTML ``colgroup`` element. - result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr) - -macro dd*(e: expr): expr = - ## generates the HTML ``dd`` element. - result = xmlCheckedTag(e, "dd", commonAttr) - -macro del*(e: expr): expr = - ## generates the HTML ``del`` element. - result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr) - -macro dfn*(e: expr): expr = - ## generates the HTML ``dfn`` element. - result = xmlCheckedTag(e, "dfn", commonAttr) - -macro `div`*(e: expr): expr = - ## generates the HTML ``div`` element. - result = xmlCheckedTag(e, "div", commonAttr) - -macro dl*(e: expr): expr = - ## generates the HTML ``dl`` element. - result = xmlCheckedTag(e, "dl", commonAttr) - -macro dt*(e: expr): expr = - ## generates the HTML ``dt`` element. - result = xmlCheckedTag(e, "dt", commonAttr) - -macro em*(e: expr): expr = - ## generates the HTML ``em`` element. - result = xmlCheckedTag(e, "em", commonAttr) - -macro fieldset*(e: expr): expr = - ## generates the HTML ``fieldset`` element. - result = xmlCheckedTag(e, "fieldset", commonAttr) - -macro form*(e: expr): expr = - ## generates the HTML ``form`` element. - result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & - commonAttr, "action") - -macro h1*(e: expr): expr = - ## generates the HTML ``h1`` element. - result = xmlCheckedTag(e, "h1", commonAttr) - -macro h2*(e: expr): expr = - ## generates the HTML ``h2`` element. - result = xmlCheckedTag(e, "h2", commonAttr) - -macro h3*(e: expr): expr = - ## generates the HTML ``h3`` element. - result = xmlCheckedTag(e, "h3", commonAttr) - -macro h4*(e: expr): expr = - ## generates the HTML ``h4`` element. - result = xmlCheckedTag(e, "h4", commonAttr) - -macro h5*(e: expr): expr = - ## generates the HTML ``h5`` element. - result = xmlCheckedTag(e, "h5", commonAttr) - -macro h6*(e: expr): expr = - ## generates the HTML ``h6`` element. - result = xmlCheckedTag(e, "h6", commonAttr) - -macro head*(e: expr): expr = - ## generates the HTML ``head`` element. - result = xmlCheckedTag(e, "head", "profile") - -macro html*(e: expr): expr = - ## generates the HTML ``html`` element. - result = xmlCheckedTag(e, "html", "", "xmlns") - -macro hr*(e: expr): expr = - ## generates the HTML ``hr`` element. - result = xmlCheckedTag(e, "hr", commonAttr, "", true) - -macro i*(e: expr): expr = - ## generates the HTML ``i`` element. - result = xmlCheckedTag(e, "i", commonAttr) - -macro img*(e: expr): expr = - ## generates the HTML ``img`` element. - result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true) - -macro input*(e: expr): expr = - ## generates the HTML ``input`` element. - result = xmlCheckedTag(e, "input", "name type value checked maxlength src" & - " alt accept disabled readonly accesskey tabindex" & commonAttr, "", true) - -macro ins*(e: expr): expr = - ## generates the HTML ``ins`` element. - result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr) - -macro kbd*(e: expr): expr = - ## generates the HTML ``kbd`` element. - result = xmlCheckedTag(e, "kbd", commonAttr) - -macro label*(e: expr): expr = - ## generates the HTML ``label`` element. - result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr) - -macro legend*(e: expr): expr = - ## generates the HTML ``legend`` element. - result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr) - -macro li*(e: expr): expr = - ## generates the HTML ``li`` element. - result = xmlCheckedTag(e, "li", commonAttr) - -macro link*(e: expr): expr = - ## generates the HTML ``link`` element. - result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & - commonAttr, "", true) - -macro map*(e: expr): expr = - ## generates the HTML ``map`` element. - result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false) - -macro meta*(e: expr): expr = - ## generates the HTML ``meta`` element. - result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true) - -macro noscript*(e: expr): expr = - ## generates the HTML ``noscript`` element. - result = xmlCheckedTag(e, "noscript", commonAttr) - -macro `object`*(e: expr): expr = - ## generates the HTML ``object`` element. - result = xmlCheckedTag(e, "object", "classid data codebase declare type " & - "codetype archive standby width height name tabindex" & commonAttr) - -macro ol*(e: expr): expr = - ## generates the HTML ``ol`` element. - result = xmlCheckedTag(e, "ol", commonAttr) - -macro optgroup*(e: expr): expr = - ## generates the HTML ``optgroup`` element. - result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false) - -macro option*(e: expr): expr = - ## generates the HTML ``option`` element. - result = xmlCheckedTag(e, "option", "selected value" & commonAttr) - -macro p*(e: expr): expr = - ## generates the HTML ``p`` element. - result = xmlCheckedTag(e, "p", commonAttr) - -macro param*(e: expr): expr = - ## generates the HTML ``param`` element. - result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true) - -macro pre*(e: expr): expr = - ## generates the HTML ``pre`` element. - result = xmlCheckedTag(e, "pre", commonAttr) - -macro q*(e: expr): expr = - ## generates the HTML ``q`` element. - result = xmlCheckedTag(e, "q", "cite" & commonAttr) - -macro samp*(e: expr): expr = - ## generates the HTML ``samp`` element. - result = xmlCheckedTag(e, "samp", commonAttr) - -macro script*(e: expr): expr = - ## generates the HTML ``script`` element. - result = xmlCheckedTag(e, "script", "src charset defer", "type", false) - -macro select*(e: expr): expr = - ## generates the HTML ``select`` element. - result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & - commonAttr) - -macro small*(e: expr): expr = - ## generates the HTML ``small`` element. - result = xmlCheckedTag(e, "small", commonAttr) - -macro span*(e: expr): expr = - ## generates the HTML ``span`` element. - result = xmlCheckedTag(e, "span", commonAttr) - -macro strong*(e: expr): expr = - ## generates the HTML ``strong`` element. - result = xmlCheckedTag(e, "strong", commonAttr) - -macro style*(e: expr): expr = - ## generates the HTML ``style`` element. - result = xmlCheckedTag(e, "style", "media title", "type") - -macro sub*(e: expr): expr = - ## generates the HTML ``sub`` element. - result = xmlCheckedTag(e, "sub", commonAttr) - -macro sup*(e: expr): expr = - ## generates the HTML ``sup`` element. - result = xmlCheckedTag(e, "sup", commonAttr) - -macro table*(e: expr): expr = - ## generates the HTML ``table`` element. - result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" & - " frame rules width" & commonAttr) - -macro tbody*(e: expr): expr = - ## generates the HTML ``tbody`` element. - result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr) - -macro td*(e: expr): expr = - ## generates the HTML ``td`` element. - result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" & - " align valign" & commonAttr) - -macro textarea*(e: expr): expr = - ## generates the HTML ``textarea`` element. - result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" & - " tabindex" & commonAttr, "rows cols", false) - -macro tfoot*(e: expr): expr = - ## generates the HTML ``tfoot`` element. - result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr) - -macro th*(e: expr): expr = - ## generates the HTML ``th`` element. - result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" & - " align valign" & commonAttr) - -macro thead*(e: expr): expr = - ## generates the HTML ``thead`` element. - result = xmlCheckedTag(e, "thead", "align valign" & commonAttr) - -macro title*(e: expr): expr = - ## generates the HTML ``title`` element. - result = xmlCheckedTag(e, "title") - -macro tr*(e: expr): expr = - ## generates the HTML ``tr`` element. - result = xmlCheckedTag(e, "tr", "align valign" & commonAttr) - -macro tt*(e: expr): expr = - ## generates the HTML ``tt`` element. - result = xmlCheckedTag(e, "tt", commonAttr) - -macro ul*(e: expr): expr = - ## generates the HTML ``ul`` element. - result = xmlCheckedTag(e, "ul", commonAttr) - -macro `var`*(e: expr): expr = - ## generates the HTML ``var`` element. - result = xmlCheckedTag(e, "var", commonAttr) - -when isMainModule: - var nim = "Nimrod" - echo h1(a(href="http://force7.de/nimrod", nim)) - diff --git a/lib/system/threads.nim b/lib/system/threads.nim index ccca85cb7..a458dffe9 100755 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -254,7 +254,7 @@ type ## that should not be part of a message! Use ## a ``TThreadId`` for that. emptyFn: proc () - dataFn: proc (p: TMsg) + dataFn: proc (m: TMsg) data: TMsg TThreadId*[TMsg] = ptr TThread[TMsg] ## the current implementation uses ## a pointer as a thread ID. diff --git a/tests/accept/run/tgenericprocvar.nim b/tests/accept/run/tgenericprocvar.nim new file mode 100644 index 000000000..7fdc58ca4 --- /dev/null +++ b/tests/accept/run/tgenericprocvar.nim @@ -0,0 +1,19 @@ +discard """ + output: "0false" +""" + +# Test multiple generic instantiation of generic proc vars: + +proc threadProcWrapper[TMsg]() = + var x: TMsg + stdout.write($x) + +#var x = threadProcWrapper[int] +#x() + +#var y = threadProcWrapper[bool] +#y() + +threadProcWrapper[int]() +threadProcWrapper[bool]() + diff --git a/todo.txt b/todo.txt index 494603083..4ac2a5703 100755 --- a/todo.txt +++ b/todo.txt @@ -3,9 +3,9 @@ Version 0.8.14 - ``var T`` as a return type; easy to prove that location does not escape its stack frame -- strutils.unindent - document Nimrod's two phase symbol lookup for generics - make ^ available as operator +- optional indentation for 'case' statement - make threadvar efficient again on linux after testing - test the sort implementation again - export re-entrant and non-reentrant locks and condition vars diff --git a/tools/sunset.tmpl b/tools/sunset.tmpl index faa40a295..6127da568 100755 --- a/tools/sunset.tmpl +++ b/tools/sunset.tmpl @@ -65,7 +65,7 @@