diff options
author | Araq <rumpf_a@web.de> | 2012-07-20 08:49:42 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-07-20 08:49:42 +0200 |
commit | 1c6f14deeeb3dc6acb41efba886e4999a8621a4a (patch) | |
tree | fc7d16bef573ed2423bc8961f9b6ebba681ea4ed | |
parent | 43f057c5aa23cf2cc441906737cd53fda90811c7 (diff) | |
download | Nim-1c6f14deeeb3dc6acb41efba886e4999a8621a4a.tar.gz |
added system.compiles
-rwxr-xr-x | compiler/ast.nim | 3 | ||||
-rwxr-xr-x | compiler/msgs.nim | 8 | ||||
-rwxr-xr-x | compiler/semdata.nim | 3 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 30 | ||||
-rwxr-xr-x | lib/system.nim | 10 | ||||
-rw-r--r-- | tests/compile/tcompiles.nim | 12 | ||||
-rwxr-xr-x | todo.txt | 2 | ||||
-rwxr-xr-x | web/news.txt | 2 |
8 files changed, 65 insertions, 5 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index c826dfad9..669b45159 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -381,7 +381,8 @@ const type TMagic* = enum # symbols that require compiler magic: mNone, - mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, + mDefined, mDefinedInScope, mCompiles, + mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mEcho, mShallowCopy, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst, mExpandToAst, mUnaryLt, mSucc, diff --git a/compiler/msgs.nim b/compiler/msgs.nim index a661da0e1..30066d376 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -458,6 +458,7 @@ var gHintCounter*: int = 0 gWarnCounter*: int = 0 gErrorMax*: int = 1 # stop after gErrorMax errors + gSilence*: int # == 0 if we produce any output at all # this format is understood by many text editors: it is the same that # Borland and Freepascal use @@ -528,12 +529,13 @@ proc addCheckpoint*(filename: string, line: int) = proc OutWriteln*(s: string) = ## Writes to stdout. Always. - Writeln(stdout, s) + if gSilence == 0: Writeln(stdout, s) proc MsgWriteln*(s: string) = ## Writes to stdout. If --stdout option is given, writes to stderr instead. - if optStdout in gGlobalOptions: Writeln(stderr, s) - else: Writeln(stdout, s) + if gSilence == 0: + if optStdout in gGlobalOptions: Writeln(stderr, s) + else: Writeln(stdout, s) proc coordToStr(coord: int): string = if coord == -1: result = "???" diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 74e82db61..76ceafecf 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -63,6 +63,7 @@ type # store this info in the syms themselves!) InGenericContext*: int # > 0 if we are in a generic InUnrolledContext*: int # > 0 if we are unrolling a loop + InCompilesContext*: int # > 0 if we are in a ``compiles`` magic converters*: TSymSeq # sequence of converters optionStack*: TLinkedList libs*: TLinkedList # all libs used by this module @@ -100,7 +101,7 @@ proc PushOwner*(owner: PSym) proc PopOwner*() # implementation -var gOwners: seq[PSym] = @[] +var gOwners*: seq[PSym] = @[] proc getCurrOwner(): PSym = # owner stack (used for initializing the diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a0e7c329c..63a19c879 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1103,12 +1103,42 @@ proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, else: result = semDirectOp(c, n, flags) +proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode = + # we replace this node by a 'true' or 'false' node: + if sonsLen(n) != 2: return semDirectOp(c, n, flags) + result = newIntNode(nkIntLit, 0) + result.info = n.info + result.typ = getSysType(tyBool) + # watch out, hacks ahead: + let oldErrorCount = msgs.gErrorCounter + let oldErrorMax = msgs.gErrorMax + inc c.InCompilesContext + inc msgs.gSilence + # do not halt after first error: + msgs.gErrorMax = high(int) + + let oldTos = c.tab.tos + let oldOwnerLen = len(gOwners) + try: + discard semExpr(c, n.sons[1]) + result.intVal = ord(msgs.gErrorCounter == oldErrorCount) + except ERecoverableError: + nil + # undo symbol table changes (as far as it's possible): + setlen(gOwners, oldOwnerLen) + while c.tab.tos > oldTos: rawCloseScope(c.tab) + dec c.InCompilesContext + dec msgs.gSilence + msgs.gErrorCounter = oldErrorCount + msgs.gErrorMax = oldErrorMax + proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = # this is a hotspot in the compiler! result = n case s.magic # magics that need special treatment of mDefined: result = semDefined(c, setMs(n, s), false) of mDefinedInScope: result = semDefined(c, setMs(n, s), true) + of mCompiles: result = semCompiles(c, setMs(n, s), flags) of mLow: result = semLowHigh(c, setMs(n, s), mLow) of mHigh: result = semLowHigh(c, setMs(n, s), mHigh) of mSizeOf: result = semSizeof(c, setMs(n, s)) diff --git a/lib/system.nim b/lib/system.nim index 32e338c5f..8f19f93f1 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -2350,5 +2350,15 @@ proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} = x[j+i] = item[j] inc(j) +proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} = + ## Special compile-time procedure that checks whether `x` can be compiled + ## without any semantic error. + ## This can be used to check whether a type supports some operation: + ## + ## .. code-block:: Nimrod + ## when not compiles(3 + 4): + ## echo "'+' for integers is available" + nil + when defined(initDebugger): initDebugger() diff --git a/tests/compile/tcompiles.nim b/tests/compile/tcompiles.nim new file mode 100644 index 000000000..4b72d8bd8 --- /dev/null +++ b/tests/compile/tcompiles.nim @@ -0,0 +1,12 @@ +discard """ + output: '''no''' +""" + +# test the new 'compiles' feature: + +when compiles(4+5.0 * "hallo"): + echo "yes" +else: + echo "no" + + diff --git a/todo.txt b/todo.txt index 143775de7..4cd1eed4f 100755 --- a/todo.txt +++ b/todo.txt @@ -18,6 +18,8 @@ New pragmas: - fix evals.nim with closures - implement "closure tuple consists of a single 'ref'" optimization - make closure default calling convention for proc types + - make 'raiseHook' take a closure and provide push and pop for this + --> Lisp-style exception system - document 'do' notation - rethink the syntax: distinction between expr and stmt is unfortunate; diff --git a/web/news.txt b/web/news.txt index fc879f474..b99d97f91 100755 --- a/web/news.txt +++ b/web/news.txt @@ -61,6 +61,8 @@ Library Additions for managing time. - Added ``system.@`` for converting an ``openarray`` to a ``seq`` (it used to only support fixed length arrays). +- Added ``system.compiles`` which can be used to check whether a type supports + some operation. Changes affecting backwards compatibility |