diff options
-rw-r--r-- | compiler/nimconf.nim | 5 | ||||
-rw-r--r-- | compiler/nimrod.nimrod.cfg (renamed from compiler/nimrod.cfg) | 0 | ||||
-rw-r--r-- | compiler/sem.nim | 50 | ||||
-rw-r--r-- | compiler/semexprs.nim | 14 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | lib/core/macros.nim | 2 | ||||
-rw-r--r-- | lib/pure/fsmonitor.nim | 10 | ||||
-rw-r--r-- | lib/pure/htmlparser.nim | 30 | ||||
-rw-r--r-- | lib/system.nim | 53 | ||||
-rw-r--r-- | lib/system/channels.nim | 3 | ||||
-rw-r--r-- | lib/system/threads.nim | 3 | ||||
-rw-r--r-- | readme.md | 4 | ||||
-rw-r--r-- | readme.txt | 4 | ||||
-rw-r--r-- | tests/compile/tgeneric.nim | 8 | ||||
-rw-r--r-- | tests/run/tdrdobbs_examples.nim | 134 | ||||
-rw-r--r-- | tests/run/tvarious1.nim | 14 |
16 files changed, 273 insertions, 63 deletions
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index 507812d9c..7ec566a01 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -243,11 +243,6 @@ proc LoadConfigs*(cfg: string) = readConfigFile(pd / cfg) if gProjectName.len != 0: - var conffile = changeFileExt(gProjectFull, "cfg") - if conffile != pd / cfg and existsFile(conffile): - readConfigFile(conffile) - rawMessage(warnConfigDeprecated, conffile) - # new project wide config file: readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg")) diff --git a/compiler/nimrod.cfg b/compiler/nimrod.nimrod.cfg index ac8f732f1..ac8f732f1 100644 --- a/compiler/nimrod.cfg +++ b/compiler/nimrod.nimrod.cfg diff --git a/compiler/sem.nim b/compiler/sem.nim index ea53afbeb..3ace623bc 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -90,6 +90,24 @@ proc commonType*(x, y: PType): PType = let idx = ord(b.kind in {tyArray, tyArrayConstr}) if a.sons[idx].kind == tyEmpty: return y #elif b.sons[idx].kind == tyEmpty: return x + elif a.kind == tyRange and b.kind == tyRange: + # consider: (range[0..3], range[0..4]) here. We should make that + # range[0..4]. But then why is (range[0..4], 6) not range[0..6]? + # But then why is (2,4) not range[2..4]? But I think this would break + # too much code. So ... it's the same range or the base type. This means + # type(if b: 0 else 1) == int and not range[0..1]. For now. In the long + # run people expect ranges to work properly within a tuple. + if not sameType(a, b): + result = skipTypes(a, {tyRange}).skipIntLit + when false: + if a.kind != tyRange and b.kind == tyRange: + # XXX This really needs a better solution, but a proper fix now breaks + # code. + result = a #.skipIntLit + elif a.kind == tyRange and b.kind != tyRange: + result = b #.skipIntLit + elif a.kind in IntegralTypes and a.n != nil: + result = a #.skipIntLit else: var k = tyNone if a.kind in {tyRef, tyPtr}: @@ -103,7 +121,7 @@ proc commonType*(x, y: PType): PType = if result.isNil: return x if k != tyNone: let r = result - result = NewType(k, r.owner) + result = newType(k, r.owner) result.addSonSkipIntLit(r) proc isTopLevel(c: PContext): bool {.inline.} = @@ -140,26 +158,27 @@ proc IsOpImpl(c: PContext, n: PNode): PNode proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, semCheck: bool = true): PNode -proc symFromType(t: PType, info: TLineInfo): PSym = - if t.sym != nil: return t.sym - result = newSym(skType, getIdent"AnonType", t.owner, info) - result.flags.incl sfAnon - result.typ = t +when false: + proc symFromType(t: PType, info: TLineInfo): PSym = + if t.sym != nil: return t.sym + result = newSym(skType, getIdent"AnonType", t.owner, info) + result.flags.incl sfAnon + result.typ = t -proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode = - result = newSymNode(symFromType(t, info), info) - result.typ = makeTypeDesc(c, t) + proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode = + result = newSymNode(symFromType(t, info), info) + result.typ = makeTypeDesc(c, t) proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext = result = newEvalContext(c.module, mode) result.getType = proc (n: PNode): PNode = - var e = tryExpr(c, n) - if e == nil: - result = symNodeFromType(c, errorType(c), n.info) - elif e.typ == nil: + result = tryExpr(c, n) + if result == nil: + result = newSymNode(errorSym(c, n)) + elif result.typ == nil: result = newSymNode(getSysSym"void") else: - result = symNodeFromType(c, e.typ, n.info) + result.typ = makeTypeDesc(c, result.typ) result.handleIsOperator = proc (n: PNode): PNode = result = IsOpImpl(c, n) @@ -210,7 +229,8 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = of tyTypeDesc: if n.kind == nkStmtList: result.kind = nkStmtListType var typ = semTypeNode(c, result, nil) - result = symNodeFromType(c, typ, n.info) + result.typ = makeTypeDesc(c, typ) + #result = symNodeFromType(c, typ, n.info) else: result = semExpr(c, result) result = fitNode(c, s.typ.sons[0], result) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 337224aef..775d4e7a0 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -191,7 +191,7 @@ proc isCastable(dst, src: PType): bool = proc isSymChoice(n: PNode): bool {.inline.} = result = n.kind in nkSymChoices -proc semConv(c: PContext, n: PNode, s: PSym): PNode = +proc semConv(c: PContext, n: PNode): PNode = if sonsLen(n) != 2: LocalError(n.info, errConvNeedsOneArg) return n @@ -738,8 +738,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = elif t != nil and t.kind == tyTypeDesc: if n.len == 1: return semObjConstr(c, n, flags) let destType = t.skipTypes({tyTypeDesc, tyGenericInst}) - result = semConv(c, n, symFromType(destType, n.info)) - return + return semConv(c, n) else: result = overloadedCallOpr(c, n) # Now that nkSym does not imply an iteration over the proc/iterator space, @@ -1048,7 +1047,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = # The result so far is a tyTypeDesc bound # a tyGenericBody. The line below will substitute # it with the instantiated type. - result = symNodeFromType(c, semTypeNode(c, n, nil), n.info) + result = n + result.typ = makeTypeDesc(c, semTypeNode(c, n, nil)) + #result = symNodeFromType(c, semTypeNode(c, n, nil), n.info) of tyTuple: checkSonsLen(n, 2) n.sons[0] = makeDeref(n.sons[0]) @@ -1883,7 +1884,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = semExpr(c, n.sons[0], flags) of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy: var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc}) - result = symNodeFromType(c, typ, n.info) + result.typ = makeTypeDesc(c, typ) + #result = symNodeFromType(c, typ, n.info) of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: # check if it is an expression macro: checkMinSonsLen(n, 1) @@ -1906,7 +1908,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of skType: # XXX think about this more (``set`` procs) if n.len == 2: - result = semConv(c, n, s) + result = semConv(c, n) elif n.len == 1: result = semObjConstr(c, n, flags) elif Contains(c.AmbiguousSymbols, s.id): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index da8ba50a8..a1805fdec 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1087,6 +1087,8 @@ proc semIterator(c: PContext, n: PNode): PNode = # -- at least for 0.9.2. if s.typ.callConv == ccClosure: incl(s.typ.flags, tfCapturesEnv) + else: + s.typ.callConv = ccInline when false: if s.typ.callConv != ccInline: s.typ.callConv = ccClosure diff --git a/lib/core/macros.nim b/lib/core/macros.nim index fc93a157d..d01d4ebee 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -494,7 +494,7 @@ const from strutils import cmpIgnoreStyle, format -proc ExpectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} = +proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} = assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind) proc newProc*(name = newEmptyNode(); params: openarray[PNimrodNode] = []; diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim index a554cf963..d6584c1a0 100644 --- a/lib/pure/fsmonitor.nim +++ b/lib/pure/fsmonitor.nim @@ -64,10 +64,10 @@ const proc newMonitor*(): PFSMonitor = ## Creates a new file system monitor. new(result) - result.fd = inotifyInit() result.targets = initTable[cint, string]() + result.fd = inotifyInit() if result.fd < 0: - OSError() + OSError(OSLastError()) proc add*(monitor: PFSMonitor, target: string, filters = {MonitorAll}): cint {.discardable.} = @@ -93,7 +93,7 @@ proc add*(monitor: PFSMonitor, target: string, result = inotifyAddWatch(monitor.fd, target, INFilter.uint32) if result < 0: - OSError() + OSError(OSLastError()) monitor.targets.add(result, target) proc del*(monitor: PFSMonitor, wd: cint) = @@ -101,7 +101,7 @@ proc del*(monitor: PFSMonitor, wd: cint) = ## ## If ``wd`` is not a part of ``monitor`` an EOS error is raised. if inotifyRmWatch(monitor.fd, wd) < 0: - OSError() + OSError(OSLastError()) proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] = result = @[] @@ -184,7 +184,7 @@ proc FSMonitorRead(h: PObject) = proc toDelegate(m: PFSMonitor): PDelegate = result = newDelegate() result.deleVal = m - result.fd = m.fd + result.fd = (type(result.fd))(m.fd) result.mode = fmRead result.handleRead = FSMonitorRead result.open = true diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim index d60d2e583..060f0e386 100644 --- a/lib/pure/htmlparser.nim +++ b/lib/pure/htmlparser.nim @@ -17,11 +17,37 @@ ## ## echo loadHtml("mydirty.html") ## -## ## Every tag in the resulting tree is in lower case. ## ## **Note:** The resulting ``PXmlNode`` already uses the ``clientData`` field, ## so it cannot be used by clients of this library. +## +## Example: Transforming hyperlinks +## ================================ +## +## This code demonstrates how you can iterate over all the tags in an HTML file +## and write back the modified version. In this case we look for hyperlinks +## ending with the extension ``.rst`` and convert them to ``.html``. +## +## .. code-block:: nimrod +## +## import htmlparser +## import xmltree # To use '$' for PXmlNode +## import strtabs # To access PXmlAttributes +## import os # To use splitFile +## import strutils # To use cmpIgnoreCase +## +## proc transformHyperlinks() = +## let html = loadHTML("input.html") +## +## for a in html.findAll("a"): +## let href = a.attrs["href"] +## if not href.isNil: +## let (dir, filename, ext) = splitFile(href) +## if cmpIgnoreCase(ext, ".rst") == 0: +## a.attrs["href"] = dir / filename & ".html" +## +## writeFile("output.html", $html) import strutils, streams, parsexml, xmltree, unicode, strtabs @@ -528,7 +554,7 @@ proc parseHtml*(s: PStream, filename: string, ## parses the XML from stream `s` and returns a ``PXmlNode``. Every ## occured parsing error is added to the `errors` sequence. var x: TXmlParser - open(x, s, filename, {reportComments}) + open(x, s, filename, {reportComments, reportWhitespace}) next(x) # skip the DOCTYPE: if x.kind == xmlSpecial: next(x) diff --git a/lib/system.nim b/lib/system.nim index b2d19a885..dc5a406d1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -374,10 +374,10 @@ proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.} ## This is equivalent to ``s = @[]; setlen(s, len)``, but more ## efficient since no reallocation is needed. ## - ## Note that the sequence will be filled with uninitialized entries, which - ## can be a problem for sequences containing strings. After the creation of - ## the sequence you should assign entries to the sequence instead of adding - ## them. Example: + ## Note that the sequence will be filled with zeroed entries, which can be a + ## problem for sequences containing strings since their value will be + ## ``nil``. After the creation of the sequence you should assign entries to + ## the sequence instead of adding them. Example: ## ## .. code-block:: nimrod ## var inputStrings : seq[string] @@ -390,10 +390,10 @@ proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.} proc newSeq*[T](len = 0): seq[T] = ## creates a new sequence of type ``seq[T]`` with length ``len``. ## - ## Note that the sequence will be filled with uninitialized entries, which - ## can be a problem for sequences containing strings. After the creation of - ## the sequence you should assign entries to the sequence instead of adding - ## them. Example: + ## Note that the sequence will be filled with zeroed entries, which can be a + ## problem for sequences containing strings since their value will be + ## ``nil``. After the creation of the sequence you should assign entries to + ## the sequence instead of adding them. Example: ## ## .. code-block:: nimrod ## var inputStrings = newSeq[string](3) @@ -999,11 +999,17 @@ type ## platform-dependant in general. when defined(windows): - type clong* {.importc: "long", nodecl.} = int32 - ## This is the same as the type ``long`` in *C*. + type + clong* {.importc: "long", nodecl.} = int32 + ## This is the same as the type ``long`` in *C*. + culong* {.importc: "unsigned long", nodecl.} = uint32 + ## This is the same as the type ``unsigned long`` in *C*. else: - type clong* {.importc: "long", nodecl.} = int - ## This is the same as the type ``long`` in *C*. + type + clong* {.importc: "long", nodecl.} = int + ## This is the same as the type ``long`` in *C*. + culong* {.importc: "unsigned long", nodecl.} = uint + ## This is the same as the type ``unsigned long`` in *C*. type # these work for most platforms: cchar* {.importc: "char", nodecl.} = char @@ -1032,8 +1038,6 @@ type # these work for most platforms: ## This is the same as the type ``unsigned short`` in *C*. cuint* {.importc: "int", nodecl.} = uint32 ## This is the same as the type ``unsigned int`` in *C*. - culong* {.importc: "unsigned long", nodecl.} = uint - ## This is the same as the type ``unsigned long`` in *C*. culonglong* {.importc: "unsigned long long", nodecl.} = uint64 ## This is the same as the type ``unsigned long long`` in *C*. @@ -1042,10 +1046,10 @@ type # these work for most platforms: ## high value is large enough to disable bounds checking in practice. ## Use `cstringArrayToSeq` to convert it into a ``seq[string]``. - PFloat32* = ptr Float32 ## an alias for ``ptr float32`` - PFloat64* = ptr Float64 ## an alias for ``ptr float64`` - PInt64* = ptr Int64 ## an alias for ``ptr int64`` - PInt32* = ptr Int32 ## an alias for ``ptr int32`` + PFloat32* = ptr float32 ## an alias for ``ptr float32`` + PFloat64* = ptr float64 ## an alias for ``ptr float64`` + PInt64* = ptr int64 ## an alias for ``ptr int64`` + PInt32* = ptr int32 ## an alias for ``ptr int32`` proc toFloat*(i: int): float {. magic: "ToFloat", noSideEffect, importc: "toFloat".} @@ -2615,12 +2619,13 @@ type PNimrodNode* {.magic: "PNimrodNode".} = ref TNimrodNode ## represents a Nimrod AST node. Macros operate on this type. -template eval*(blk: stmt): stmt = - ## executes a block of code at compile time just as if it was a macro - ## optionally, the block can return an AST tree that will replace the - ## eval expression - macro payload: stmt {.gensym.} = blk - payload() +when false: + template eval*(blk: stmt): stmt = + ## executes a block of code at compile time just as if it was a macro + ## optionally, the block can return an AST tree that will replace the + ## eval expression + macro payload: stmt {.gensym.} = blk + payload() when hostOS != "standalone": proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} = diff --git a/lib/system/channels.nim b/lib/system/channels.nim index d0294322a..9c3cc93e0 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -13,6 +13,9 @@ ## ## **Note:** The current implementation of message passing is slow and does ## not work with cyclic data structures. + +when not defined(NimString): + {.error: "You must not import this module explicitly".} type pbytes = ptr array[0.. 0xffff, byte] diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 7d74de92d..104ca63c1 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -39,6 +39,9 @@ ## createThread(thr[i], threadFunc, (i*10, i*10+5)) ## joinThreads(thr) +when not defined(NimString): + {.error: "You must not import this module explicitly".} + const maxRegisters = 256 # don't think there is an arch with more registers useStackMaskHack = false ## use the stack mask hack for better performance diff --git a/readme.md b/readme.md index c49e24f4e..8d42c66db 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,7 @@ the C source of an older version of the compiler are needed to bootstrap the latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources). Pre-compiled snapshots of the compiler are also available on -[Nimbuild](http://build.nimrod-code.org/). Your platform however may not +[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not currently be built for. The compiler currently supports the following platform and architecture @@ -47,7 +47,7 @@ The above steps can be performed on Windows in a similar fashion, the instead of ``build.sh``. ## Getting help -A [forum](http://forum.nimrod-code.org/) is available if you have any +A [forum](http://forum.nimrod-lang.org/) is available if you have any questions, and you can also get help in the IRC channel on [Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on [StackOverflow use the nimrod diff --git a/readme.txt b/readme.txt index c49e24f4e..8d42c66db 100644 --- a/readme.txt +++ b/readme.txt @@ -9,7 +9,7 @@ the C source of an older version of the compiler are needed to bootstrap the latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources). Pre-compiled snapshots of the compiler are also available on -[Nimbuild](http://build.nimrod-code.org/). Your platform however may not +[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not currently be built for. The compiler currently supports the following platform and architecture @@ -47,7 +47,7 @@ The above steps can be performed on Windows in a similar fashion, the instead of ``build.sh``. ## Getting help -A [forum](http://forum.nimrod-code.org/) is available if you have any +A [forum](http://forum.nimrod-lang.org/) is available if you have any questions, and you can also get help in the IRC channel on [Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on [StackOverflow use the nimrod diff --git a/tests/compile/tgeneric.nim b/tests/compile/tgeneric.nim index 8bda15c42..9292b729f 100644 --- a/tests/compile/tgeneric.nim +++ b/tests/compile/tgeneric.nim @@ -8,4 +8,12 @@ proc foo(models: seq[TTable[string, float]]): seq[float] = for model in models.items: result.add model["foobar"] +# bug #686 +type TType[T; A] = array[A, T] + +proc foo[T](p: TType[T, range[0..1]]) = + echo "foo" +proc foo[T](p: TType[T, range[0..2]]) = + echo "bar" + diff --git a/tests/run/tdrdobbs_examples.nim b/tests/run/tdrdobbs_examples.nim new file mode 100644 index 000000000..d1e0585d2 --- /dev/null +++ b/tests/run/tdrdobbs_examples.nim @@ -0,0 +1,134 @@ +discard """ + output: '''108 +11 -1 1936 +4.000000000000002-e001 +true +truefalse''' +""" + +proc `++`(x: var int; y: int = 1; z: int = 0) = + x = x + y + z + +var g = 70 +++g +g ++ 7 +g.`++`(10, 20) +echo g + + +#let lv = stdin.readline +#var vv = stdin.readline +#vv = "abc" # valid, reassignment allowed +#lv = "abc" # fails at compile time + +#proc square(x: int): int = x*x + +template square(x: int): int = + # ensure 'x' is only evaluated once: + let y = x + y * y + +proc mostSignificantBit(n: int): int = + # naive algorithm: + var n = n + while n != 0: + n = n shr 1 + result += 1 + result -= 1 + +const msb3999 = mostSignificantBit(3999) + +echo msb3999, " ", mostSignificantBit(0), " ", square(44) + +proc filter[T](a: openarray[T], predicate: proc (x: T): bool): seq[T] = + result = @[] # @[] constructs the empty seq + for x in a: + if predicate(x): result.add(x) + +proc map[T, S](a: openarray[T], fn: proc (x: T): S): seq[S] = + newSeq(result, a.len) + for i in 0 .. <a.len: result[i] = fn(a[i]) + + +type + FormulaKind = enum + fkVar, ## element is a variable like 'X' + fkLit, ## element is a literal like 0.1 + fkAdd, ## element is an addition operation + fkMul, ## element is a multiplication operation + fkExp ## element is an exponentiation operation + +type + Formula = ref object + case kind: FormulaKind + of fkVar: name: string + of fkLit: value: float + of fkAdd, fkMul, fkExp: left, right: Formula + +from math import pow + +proc evaluate(n: Formula, varToVal: proc (name: string): float): float = + case n.kind + of fkVar: varToVal(n.name) + of fkLit: n.value + of fkAdd: evaluate(n.left, varToVal) + evaluate(n.right, varToVal) + of fkMul: evaluate(n.left, varToVal) * evaluate(n.right, varToVal) + of fkExp: pow(evaluate(n.left, varToVal), evaluate(n.right, varToVal)) + +echo evaluate(Formula(kind: fkLit, value: 0.4), nil) + +proc isPolyTerm(n: Formula): bool = + n.kind == fkMul and n.left.kind == fkLit and (let e = n.right; + e.kind == fkExp and e.left.kind == fkVar and e.right.kind == fkLit) + +proc isPolynomial(n: Formula): bool = + isPolyTerm(n) or + (n.kind == fkAdd and isPolynomial(n.left) and isPolynomial(n.right)) + +let myFormula = Formula(kind: fkMul, + left: Formula(kind: fkLit, value: 2.0), + right: Formula(kind: fkExp, + left: Formula(kind: fkVar, name: "x"), + right: Formula(kind: fkLit, value: 5.0))) + +echo isPolyTerm(myFormula) + +proc pat2kind(pattern: string): FormulaKind = + case pattern + of "^": fkExp + of "*": fkMul + of "+": fkAdd + of "x": fkVar + of "c": fkLit + else: fkVar # no error reporting for reasons of simplicity + +import macros + +proc matchAgainst(n, pattern: PNimrodNode): PNimrodNode {.compileTime.} = + template `@`(current, field: expr): expr = + newDotExpr(current, newIdentNode(astToStr(field))) + + template `==@`(n, pattern: expr): expr = + newCall("==", n@kind, newIdentNode($pat2kind($pattern.ident))) + + case pattern.kind + of CallNodes: + result = newCall("and", + n ==@ pattern[0], + matchAgainst(n@left, pattern[1])) + if pattern.len == 3: + result = newCall("and", result.copy, + matchAgainst(n@right, pattern[2])) + of nnkIdent: + result = n ==@ pattern + of nnkPar: + result = matchAgainst(n, pattern[0]) + else: + error "invalid pattern" + +macro `=~` (n: Formula, pattern: expr): bool = + result = matchAgainst(n, pattern) + +proc isPolyTerm2(n: Formula): bool = n =~ c * x^c + +echo isPolyTerm2(myFormula), isPolyTerm2(Formula(kind: fkLit, value: 0.7)) diff --git a/tests/run/tvarious1.nim b/tests/run/tvarious1.nim index 9dd4af606..6e4612ae3 100644 --- a/tests/run/tvarious1.nim +++ b/tests/run/tvarious1.nim @@ -2,7 +2,8 @@ discard """ file: "tlenopenarray.nim" output: '''1 0 -Whopie''' +Whopie +12''' """ echo len([1_000_000]) #OUT 1 @@ -27,3 +28,14 @@ var w = TWidget(names: initQueue[string]()) add(w.names, "Whopie") for n in w.names: echo(n) + +# bug #681 + +type TSomeRange = object + hour: range[0..23] + +var value: string +var val12 = TSomeRange(hour: 12) + +value = $(if val12.hour > 12: val12.hour - 12 else: val12.hour) +echo value |