Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq
2013-05-20 02:22:11 +02:00
4 changed files with 303 additions and 4 deletions

View File

@@ -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))

View File

@@ -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

View File

@@ -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
--------

View File

@@ -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>