diff options
-rw-r--r-- | lib/core/macros.nim | 239 | ||||
-rw-r--r-- | web/community.txt | 44 | ||||
-rw-r--r-- | web/news.txt | 19 | ||||
-rw-r--r-- | web/ticker.txt | 5 |
4 files changed, 303 insertions, 4 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 949719316..046a4be16 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -112,7 +112,7 @@ proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".} proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".} ## set `n`'s `i`'th child to `child`. -proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent".} +proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent", deprecated.} ## constructs an identifier from the string `s` proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".} @@ -410,3 +410,240 @@ macro dumpTreeImm*(s: stmt): stmt {.immediate.} = echo s.treeRepr macro dumpLispImm*(s: stmt): stmt {.immediate.} = echo s.lispRepr ## The ``immediate`` version of `dumpLisp`. + +proc newEmptyNode*(): PNimrodNode {.compileTime, noSideEffect.} = + ## Create a new empty node + result = newNimNode(nnkEmpty) + +proc newStmtList*(stmts: varargs[PNimrodNode]): PNimrodNode {.compileTime.}= + ## Create a new statement list + result = newNimNode(nnkStmtList).add(stmts) + +proc newBlockStmt*(label: PNimrodNode; body: PNimrodNode): PNimrodNode {.compileTime.} = + ## Create a new block statement with label + return newNimNode(nnkBlockStmt).add(label, body) +proc newBlockStmt*(body: PNimrodNode): PNimrodNode {.compiletime.} = + ## Create a new block: stmt + return newNimNode(nnkBlockStmt).add(newEmptyNode(), body) + +proc newLetStmt*(name, value: PNimrodNode): PNimrodNode{.compiletime.} = + ## Create a new let stmt + return newNimNode(nnkLetSection).add( + newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value)) + +proc newAssignment*(lhs, rhs: PNimrodNode): PNimrodNode {.compileTime, inline.} = + return newNimNode(nnkAsgn).add(lhs, rhs) + +proc newDotExpr* (a, b: PNimrodNode): PNimrodNode {.compileTime, inline.} = + ## Create new dot expression + ## a.dot(b) -> `a.b` + return newNimNode(nnkDotExpr).add(a, b) + + +proc newIdentDefs*(name, kind: PNimrodNode; default = newEmptyNode()): PNimrodNode{. + compileTime.} = newNimNode(nnkIdentDefs).add(name, kind, default) + +proc newNilLit*(): PNimrodNode {.compileTime.} = + ## New nil literal shortcut + result = newNimNode(nnkNilLit) + + +proc high*(node: PNimrodNode): int {.compileTime.} = len(node) - 1 + ## Return the highest index available for a node +proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high] + ## Return the last item in nodes children. Same as `node[node.high()]` + + +const + RoutineNodes* = { + nnkProcDef, nnkMethodDef, nnkDo, nnkLambda } + AtomicNodes* = { + nnkNone .. nnkNilLit } + CallNodes* = { + nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, + nnkCallStrLit, nnkHiddenCallConv} + + +from strutils import cmpIgnoreStyle, format + +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] = []; + body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} = + ## shortcut for creating a new proc + assert procType in RoutineNodes + result = newNimNode(procType).add( + name, + newEmptyNode(), + newEmptyNode(), + newNimNode(nnkFormalParams).add(params), ##params + newEmptyNode(), ## pragmas + newEmptyNode(), + body) + +proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}= + ## Copy all children from `src` to `dest` + for i in 0 .. < src.len: + dest.add src[i].copyNimTree + +template expectRoutine(node: PNimrodNode): stmt = + expectKind(node, routineNodes) + +proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = + someProc.expectRoutine + result = someProc[0] +proc `name=`*(someProc: PNimrodNode; val: PNimrodNode) {.compileTime.} = + someProc.expectRoutine + someProc[0] = val + +proc params*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = + someProc.expectRoutine + result = someProc[3] +proc `params=`* (someProc: PNimrodNode; params: PNimrodNode) {.compileTime.}= + someProc.expectRoutine + assert params.kind == nnkFormalParams + someProc[3] = params + +proc pragma*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = + ## Get the pragma of a proc type + ## These will be expanded + someProc.expectRoutine + result = someProc[4] +proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}= + ## Set the pragma of a proc type + someProc.expectRoutine + assert val.kind in {nnkEmpty, nnkPragma} + someProc[4] = val + + +template badnodekind(k; f): stmt{.immediate.} = + assert false, "Invalid node kind $# for macros.`$2`".format(k, f) + +proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = + case someProc.kind: + of routineNodes: + return someProc[6] + of nnkBlockStmt, nnkWhileStmt: + return someproc[1] + of nnkForStmt: + return someProc.last + else: + badNodeKind someproc.kind, "body" + +proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} = + case someProc.kind + of routineNodes: + someProc[6] = val + of nnkBlockStmt, nnkWhileStmt: + someProc[1] = val + of nnkForStmt: + someProc[high(someProc)] = val + else: + badNodeKind someProc.kind, "body=" + + +proc `$`*(node: PNimrodNode): string {.compileTime.} = + ## Get the string of an identifier node + case node.kind + of nnkIdent: + result = $node.ident + of nnkStrLit: + result = node.strval + else: + badNodeKind node.kind, "$" + +proc ident*(name: string): PNimrodNode {.compileTime,inline.} = newIdentNode(name) + ## Create a new ident node from a string + +iterator children*(n: PNimrodNode): PNimrodNode {.inline.}= + for i in 0 .. high(n): + yield n[i] + +template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.} = + ## Find the first child node matching condition (or nil) + ## var res = findChild(n, it.kind == nnkPostfix and it.basename.ident == !"foo") + + block: + var result: PNimrodNode + for it in n.children: + if cond: + result = it + break + result + +proc insert*(a: PNimrodNOde; pos: int; b: PNimrodNode) {.compileTime.} = + ## Insert node B into A at pos + if high(a) < pos: + ## add some empty nodes first + for i in high(a)..pos-2: + a.add newEmptyNode() + a.add b + else: + ## push the last item onto the list again + ## and shift each item down to pos up one + a.add(a[a.high]) + for i in countdown(high(a) - 2, pos): + a[i + 1] = a[i] + a[pos] = b + +proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} = + ## Pull an identifier from prefix/postfix expressions + case a.kind + of nnkIdent: return a + of nnkPostfix, nnkPrefix: return a[1] + else: + quit "Do not know how to get basename of ("& treerepr(a) &")\n"& repr(a) +proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}= + case a.kind + of nnkIdent: macros.`ident=`(a, !val) + of nnkPostfix, nnkPrefix: a[1] = ident(val) + else: + quit "Do not know how to get basename of ("& treerepr(a)& ")\n"& repr(a) + +proc postfix*(node: PNimrodNode; op: string): PNimrodNode {. + compileTime.} = newNimNode(nnkPostfix).add(ident(op), node) +proc prefix*(node: PNimrodNode; op: string): PNimrodNode {. + compileTime.} = newNimNode(nnkPrefix).add(ident(op), node) +proc infix*(a: PNimrodNode; op: string; b: PNimrodNode): PNimrodNode {. + compileTime.} = newNimNode(nnkInfix).add(ident(op), a, b) + +proc unpackPostfix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. + compileTime.} = + node.expectKind nnkPostfix + result = (node[0], $node[1]) +proc unpackPrefix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. + compileTime.} = + node.expectKind nnkPrefix + result = (node[0], $node[1]) +proc unpackInfix*(node: PNimrodNode): tuple[left: PNimrodNode; op: string; right: PNimrodNode] {. + compileTime.} = + assert node.kind == nnkInfix + result = (node[0], $node[1], node[2]) + +proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} = + ## An alias for copyNimTree() + return node.copyNimTree() + +proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0 + ## Check if two idents are identical + +proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}= + ## Search nnkFormalParams for an argument + assert params.kind == nnkFormalParams + for i in 1 .. <params.len: + template node: expr = params[i] + if name.eqIdent( $ node[0]): + return true + +proc addIdentIfAbsent* (dest: PNimrodNode, ident: string) {.compiletime.} = + ## Add ident to dest if it is not present. This is intended for use with pragmas + for node in dest.children: + case node.kind + of nnkIdent: + if ident.eqIdent($node): return + of nnkExprColonExpr: + if ident.eqIdent($ node[0]): return + else: nil + dest.add(ident(ident)) + diff --git a/web/community.txt b/web/community.txt index 99338d084..bfa377a03 100644 --- a/web/community.txt +++ b/web/community.txt @@ -6,5 +6,47 @@ Wiki: http://github.com/Araq/Nimrod/wiki. Bug reports: http://github.com/Araq/Nimrod/issues. -For quickest feedback, join our IRC channel: irc://freenode/nimrod +For quickest feedback, join our IRC channel: irc://irc.freenode.net/nimrod +How to help +=========== + +There are always many things to be done in the main +`Nimrod repository <https://github.com/Araq/Nimrod>`_, check out the +`issues <https://github.com/Araq/Nimrod/issues>`_ for +things to do; pull requests are always welcome. You can +also contribute to the many other projects hosted by the +`nimrod-code <https://github.com/nimrod-code>`_ organisation on github. If you +can't find anything you fancy doing, you can always ask for inspiration on IRC +(irc.freenode.net #nimrod) or on the `Nimrod forums <http://forum.nimrod-code.org>`_. + +Donations +--------- + +If you love what we do and are feeling generous then you can always donate: + +Gittip +`````` + + .. raw:: html + + <iframe style="border: 0; margin: 0; padding: 0;" + src="https://www.gittip.com/Araq/widget.html" + width="48pt" height="22pt"></iframe> + +Paypal +`````` + + .. raw:: html + + <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> + <input type="hidden" name="cmd" value="_s-xclick"> + <input type="hidden" name="hosted_button_id" value="ZQC6CVEEYNTLN"> + <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"> + <img alt="" border="0" src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif" width="1" height="1"> + </form> + +Bitcoin +``````` + + Bitcoin address: 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ \ No newline at end of file diff --git a/web/news.txt b/web/news.txt index b8a767a64..8d0ed97c3 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,7 +2,7 @@ News ==== -New website design! +2013-05-20 New website design! =================== A brand new website is now live. All thanks go to Philip Witte and @@ -15,7 +15,22 @@ agree that Philip's design is beautiful. 2013-05-20 Version 0.9.2 released ================================= -Version 0.9.2 has been released! Get it `here <download.html>`_. +We are pleased to announce that version 0.9.2 of the Nimrod compiler has been +released. This release has attracted by far the most contributions in comparison +to any other release. + +This release can be downloaded from `here <download.html>`_. + +This release brings with it many new features and bug fixes, a list of which +can be seen later. One of the major new features is the effect system together +with exception tracking which allows for checked exceptions and more, +for further details check out the `manual <manual.html#effect-system>`_. +Another major new feature is the introduction of statement list expressions, +more details on these can be found `here <manual.html#statement-list-expression>`_. +The ability to exclude symbols from modules has also been +implemented, this feature can be used like so: ``import module except symbol``. + +Thanks to all `contributors <https://github.com/Araq/Nimrod/contributors>`_! Bugfixes -------- diff --git a/web/ticker.txt b/web/ticker.txt index b47c5642a..00bc6a125 100644 --- a/web/ticker.txt +++ b/web/ticker.txt @@ -1,3 +1,8 @@ +<a class="news" href="news.html#new-website-design"> + <h3>May 20, 2013</h3> + <p>New website design!</p> +</a> + <a class="news" href="news.html#Z2013-05-20-version-0-9-2-released"> <h3>May 20, 2013</h3> <p>Nimrod version 0.9.2 has been released!</p> |