summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/core/macros.nim239
-rw-r--r--web/community.txt44
-rw-r--r--web/news.txt19
-rw-r--r--web/ticker.txt5
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>