documentation improvements; higher level Mongodb wrapper
This commit is contained in:
parent
e9260e6c4d
commit
c53ad1b39f
15 changed files with 1109 additions and 686 deletions
|
|
@ -66,6 +66,8 @@ hint[LineTooLong]=off
|
||||||
@else:
|
@else:
|
||||||
# BSD got posix_spawn only recently, so we deactivate it for osproc:
|
# BSD got posix_spawn only recently, so we deactivate it for osproc:
|
||||||
define:useFork
|
define:useFork
|
||||||
|
# at least NetBSD has problems with thread local storage:
|
||||||
|
tlsEmulation:on
|
||||||
@end
|
@end
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -340,8 +340,11 @@ Database support
|
||||||
A higher level SQLite database wrapper. The same interface is implemented
|
A higher level SQLite database wrapper. The same interface is implemented
|
||||||
for other databases too.
|
for other databases too.
|
||||||
|
|
||||||
|
* `db_mongo <db_mongo.html>`_
|
||||||
|
A higher level **mongodb** wrapper.
|
||||||
|
|
||||||
* `mongodb <mongo.html>`_
|
* `mongodb <mongo.html>`_
|
||||||
Wrapper for the **mongodb** client C library.
|
Lower level wrapper for the **mongodb** client C library.
|
||||||
|
|
||||||
|
|
||||||
Other
|
Other
|
||||||
|
|
|
||||||
855
doc/theindex.txt
855
doc/theindex.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,6 @@
|
||||||
# Test/show CGI module
|
# Test/show CGI module
|
||||||
import strtabs, cgi
|
import strtabs, cgi
|
||||||
|
|
||||||
|
|
||||||
#setTestData("name", "the andreas", "password", "rumpf\t\ttab")
|
|
||||||
|
|
||||||
var myData = readData()
|
var myData = readData()
|
||||||
validateData(myData, "name", "password")
|
validateData(myData, "name", "password")
|
||||||
writeContentType()
|
writeContentType()
|
||||||
|
|
|
||||||
213
lib/impure/db_mongo.nim
Normal file
213
lib/impure/db_mongo.nim
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nimrod's Runtime Library
|
||||||
|
# (c) Copyright 2012 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## This module implements a higher level wrapper for `mongodb`:idx:. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
##
|
||||||
|
## import mongo, db_mongo, oids, json
|
||||||
|
##
|
||||||
|
## var conn = db_mongo.open()
|
||||||
|
##
|
||||||
|
## # construct JSON data:
|
||||||
|
## var data = %{"a": %13, "b": %"my string value",
|
||||||
|
## "inner": %{"i": %71} }
|
||||||
|
##
|
||||||
|
## var id = insertID(conn, "test.test", data)
|
||||||
|
##
|
||||||
|
## for v in find(conn, "test.test", "this.a == 13"):
|
||||||
|
## print v
|
||||||
|
##
|
||||||
|
## delete(conn, "test.test", id)
|
||||||
|
## close(conn)
|
||||||
|
|
||||||
|
import mongo, oids, json
|
||||||
|
|
||||||
|
type
|
||||||
|
EDb* = object of EIO ## exception that is raised if a database error occurs
|
||||||
|
TDbConn* = TMongo ## a database connection; alias for ``TMongo``
|
||||||
|
|
||||||
|
proc dbError*(db: TDbConn, msg: string) {.noreturn.} =
|
||||||
|
## raises an EDb exception with message `msg`.
|
||||||
|
var e: ref EDb
|
||||||
|
new(e)
|
||||||
|
if db.errstr[0] != '\0':
|
||||||
|
e.msg = $db.errstr
|
||||||
|
else:
|
||||||
|
e.msg = $db.err & " " & msg
|
||||||
|
raise e
|
||||||
|
|
||||||
|
proc Close*(db: var TDbConn) =
|
||||||
|
## closes the database connection.
|
||||||
|
disconnect(db)
|
||||||
|
destroy(db)
|
||||||
|
|
||||||
|
proc Open*(host: string = defaultHost, port: int = defaultPort): TDbConn =
|
||||||
|
## opens a database connection. Raises `EDb` if the connection could not
|
||||||
|
## be established.
|
||||||
|
init(result)
|
||||||
|
|
||||||
|
let x = connect(result, host, port.cint)
|
||||||
|
if x != 0'i32:
|
||||||
|
dbError(result, "cannot open: " & host)
|
||||||
|
|
||||||
|
proc jsonToBSon(b: var TBSon, key: string, j: PJsonNode) =
|
||||||
|
case j.kind
|
||||||
|
of JString:
|
||||||
|
add(b, key, j.str)
|
||||||
|
of JInt:
|
||||||
|
add(b, key, j.num)
|
||||||
|
of JFloat:
|
||||||
|
add(b, key, j.fnum)
|
||||||
|
of JBool:
|
||||||
|
addBool(b, key, ord(j.bval))
|
||||||
|
of JNull:
|
||||||
|
addNull(b, key)
|
||||||
|
of JObject:
|
||||||
|
addStartObject(b, key)
|
||||||
|
for k, v in items(j.fields):
|
||||||
|
jsonToBSon(b, k, v)
|
||||||
|
addFinishObject(b)
|
||||||
|
of JArray:
|
||||||
|
addStartArray(b, key)
|
||||||
|
for i, e in pairs(j.elems):
|
||||||
|
jsonToBSon(b, $i, e)
|
||||||
|
addFinishArray(b)
|
||||||
|
|
||||||
|
proc jsonToBSon*(j: PJsonNode, oid: TOid): TBSon =
|
||||||
|
## converts a JSON value into the BSON format. The result must be
|
||||||
|
## ``destroyed`` explicitely!
|
||||||
|
init(result)
|
||||||
|
assert j.kind == JObject
|
||||||
|
add(result, "_id", oid)
|
||||||
|
for key, val in items(j.fields):
|
||||||
|
jsonToBSon(result, key, val)
|
||||||
|
finish(result)
|
||||||
|
|
||||||
|
proc `[]`*(obj: var TBSon, fieldname: cstring): TBSon =
|
||||||
|
## retrieves the value belonging to `fieldname`. Raises `EInvalidKey` if
|
||||||
|
## the attribute does not exist.
|
||||||
|
var it = initIter(obj)
|
||||||
|
let res = find(it, result, fieldname)
|
||||||
|
if res == bkEOO:
|
||||||
|
raise newException(EInvalidIndex, "key not in object")
|
||||||
|
|
||||||
|
proc getId*(obj: var TBSon): TOid =
|
||||||
|
## retrieves the ``_id`` attribute of `obj`.
|
||||||
|
var it = initIter(obj)
|
||||||
|
var b: TBSon
|
||||||
|
let res = find(it, b, "_id")
|
||||||
|
if res == bkOID:
|
||||||
|
result = oidVal(it)[]
|
||||||
|
else:
|
||||||
|
raise newException(EInvalidIndex, "_id not in object")
|
||||||
|
|
||||||
|
proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid =
|
||||||
|
## converts `data` to BSON format and inserts it in `namespace`. Returns
|
||||||
|
## the generated OID for the ``_id`` field.
|
||||||
|
result = genOid()
|
||||||
|
var x = jsonToBSon(data, result)
|
||||||
|
insert(db, namespace, x)
|
||||||
|
destroy(x)
|
||||||
|
|
||||||
|
proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) =
|
||||||
|
## converts `data` to BSON format and inserts it in `namespace`.
|
||||||
|
discard InsertID(db, namespace, data)
|
||||||
|
|
||||||
|
proc update*(db: var TDbConn, namespace: string, obj: var TBSon) =
|
||||||
|
## updates `obj` in `namespace`.
|
||||||
|
var cond: TBson
|
||||||
|
init(cond)
|
||||||
|
cond.add("_id", getId(obj))
|
||||||
|
finish(cond)
|
||||||
|
update(db, namespace, cond, obj, ord(UPDATE_UPSERT))
|
||||||
|
destroy(cond)
|
||||||
|
|
||||||
|
proc update*(db: var TDbConn, namespace: string, oid: TOid, obj: PJsonNode) =
|
||||||
|
## updates the data with `oid` to have the new data `obj`.
|
||||||
|
var a = jsonToBSon(obj, oid)
|
||||||
|
Update(db, namespace, a)
|
||||||
|
destroy(a)
|
||||||
|
|
||||||
|
proc delete*(db: var TDbConn, namespace: string, oid: TOid) =
|
||||||
|
## Deletes the object belonging to `oid`.
|
||||||
|
var cond: TBson
|
||||||
|
init(cond)
|
||||||
|
cond.add("_id", oid)
|
||||||
|
finish(cond)
|
||||||
|
discard remove(db, namespace, cond)
|
||||||
|
destroy(cond)
|
||||||
|
|
||||||
|
proc delete*(db: var TDbConn, namespace: string, obj: var TBSon) =
|
||||||
|
## Deletes the object `obj`.
|
||||||
|
delete(db, namespace, getId(obj))
|
||||||
|
|
||||||
|
iterator find*(db: var TDbConn, namespace: string): var TBSon =
|
||||||
|
## iterates over any object in `namespace`.
|
||||||
|
var cursor: TCursor
|
||||||
|
init(cursor, db, namespace)
|
||||||
|
while next(cursor) == mongo.OK:
|
||||||
|
yield bson(cursor)[]
|
||||||
|
destroy(cursor)
|
||||||
|
|
||||||
|
iterator find*(db: var TDbConn, namespace: string,
|
||||||
|
query, fields: var TBSon): var TBSon =
|
||||||
|
## yields the `fields` of any document that suffices `query`.
|
||||||
|
var cursor = find(db, namespace, query, fields, 0'i32, 0'i32, 0'i32)
|
||||||
|
if cursor != nil:
|
||||||
|
while next(cursor[]) == mongo.OK:
|
||||||
|
yield bson(cursor[])[]
|
||||||
|
destroy(cursor[])
|
||||||
|
|
||||||
|
proc setupFieldnames(fields: openArray[string]): TBSon =
|
||||||
|
init(result)
|
||||||
|
for x in fields: add(result, x, 1'i32)
|
||||||
|
finish(result)
|
||||||
|
|
||||||
|
iterator find*(db: var TDbConn, namespace: string,
|
||||||
|
query: var TBSon, fields: openArray[string]): var TBSon =
|
||||||
|
## yields the `fields` of any document that suffices `query`. If `fields`
|
||||||
|
## is ``[]`` the whole document is yielded.
|
||||||
|
var f = setupFieldnames(fields)
|
||||||
|
var cursor = find(db, namespace, query, f, 0'i32, 0'i32, 0'i32)
|
||||||
|
if cursor != nil:
|
||||||
|
while next(cursor[]) == mongo.OK:
|
||||||
|
yield bson(cursor[])[]
|
||||||
|
destroy(cursor[])
|
||||||
|
destroy(f)
|
||||||
|
|
||||||
|
proc setupQuery(query: string): TBSon =
|
||||||
|
init(result)
|
||||||
|
add(result, "$where", query)
|
||||||
|
finish(result)
|
||||||
|
|
||||||
|
iterator find*(db: var TDbConn, namespace: string,
|
||||||
|
query: string, fields: openArray[string]): var TBSon =
|
||||||
|
## yields the `fields` of any document that suffices `query`. If `fields`
|
||||||
|
## is ``[]`` the whole document is yielded.
|
||||||
|
var f = setupFieldnames(fields)
|
||||||
|
var q = setupQuery(query)
|
||||||
|
var cursor = find(db, namespace, q, f, 0'i32, 0'i32, 0'i32)
|
||||||
|
if cursor != nil:
|
||||||
|
while next(cursor[]) == mongo.OK:
|
||||||
|
yield bson(cursor[])[]
|
||||||
|
destroy(cursor[])
|
||||||
|
destroy(q)
|
||||||
|
destroy(f)
|
||||||
|
|
||||||
|
when false:
|
||||||
|
# this doesn't work this way; would require low level hacking
|
||||||
|
iterator fieldPairs*(obj: var TBSon): tuple[key: cstring, value: TBSon] =
|
||||||
|
## iterates over `obj` and yields all (key, value)-Pairs.
|
||||||
|
var it = initIter(obj)
|
||||||
|
var v: TBSon
|
||||||
|
while next(it) != bkEOO:
|
||||||
|
let key = key(it)
|
||||||
|
discard init(v, value(it))
|
||||||
|
yield (key, v)
|
||||||
|
|
@ -495,16 +495,16 @@ type
|
||||||
JArray
|
JArray
|
||||||
|
|
||||||
PJsonNode* = ref TJsonNode ## JSON node
|
PJsonNode* = ref TJsonNode ## JSON node
|
||||||
TJsonNode* {.final, pure.} = object
|
TJsonNode* {.final, pure, acyclic.} = object
|
||||||
case kind*: TJsonNodeKind
|
case kind*: TJsonNodeKind
|
||||||
of JString:
|
of JString:
|
||||||
str*: String
|
str*: string
|
||||||
of JInt:
|
of JInt:
|
||||||
num*: biggestInt
|
num*: biggestInt
|
||||||
of JFloat:
|
of JFloat:
|
||||||
fnum: Float
|
fnum*: float
|
||||||
of JBool:
|
of JBool:
|
||||||
bval*: Bool
|
bval*: bool
|
||||||
of JNull:
|
of JNull:
|
||||||
nil
|
nil
|
||||||
of JObject:
|
of JObject:
|
||||||
|
|
@ -558,6 +558,45 @@ proc newJArray*(): PJsonNode =
|
||||||
result.kind = JArray
|
result.kind = JArray
|
||||||
result.elems = @[]
|
result.elems = @[]
|
||||||
|
|
||||||
|
|
||||||
|
proc `%`*(s: string): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JString PJsonNode`.
|
||||||
|
new(result)
|
||||||
|
result.kind = JString
|
||||||
|
result.str = s
|
||||||
|
|
||||||
|
proc `%`*(n: biggestInt): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JInt PJsonNode`.
|
||||||
|
new(result)
|
||||||
|
result.kind = JInt
|
||||||
|
result.num = n
|
||||||
|
|
||||||
|
proc `%`*(n: float): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JFloat PJsonNode`.
|
||||||
|
new(result)
|
||||||
|
result.kind = JFloat
|
||||||
|
result.fnum = n
|
||||||
|
|
||||||
|
proc `%`*(b: bool): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JBool PJsonNode`.
|
||||||
|
new(result)
|
||||||
|
result.kind = JBool
|
||||||
|
result.bval = b
|
||||||
|
|
||||||
|
proc `%`*(keyVals: openArray[tuple[key: string, val: PJsonNode]]): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JObject PJsonNode`
|
||||||
|
new(result)
|
||||||
|
result.kind = JObject
|
||||||
|
newSeq(result.fields, keyVals.len)
|
||||||
|
for i, p in pairs(keyVals): result.fields[i] = p
|
||||||
|
|
||||||
|
proc `%`*(elements: openArray[PJSonNode]): PJsonNode =
|
||||||
|
## Generic constructor for JSON data. Creates a new `JArray PJsonNode`
|
||||||
|
new(result)
|
||||||
|
result.kind = JArray
|
||||||
|
newSeq(result.elems, elements.len)
|
||||||
|
for i, p in pairs(elements): result.elems[i] = p
|
||||||
|
|
||||||
proc len*(n: PJsonNode): int =
|
proc len*(n: PJsonNode): int =
|
||||||
## If `n` is a `JArray`, it returns the number of elements.
|
## If `n` is a `JArray`, it returns the number of elements.
|
||||||
## If `n` is a `JObject`, it returns the number of pairs.
|
## If `n` is a `JObject`, it returns the number of pairs.
|
||||||
|
|
|
||||||
|
|
@ -1355,6 +1355,7 @@ when defined(macosx):
|
||||||
|
|
||||||
proc getAppFilename*(): string {.rtl, extern: "nos$1".} =
|
proc getAppFilename*(): string {.rtl, extern: "nos$1".} =
|
||||||
## Returns the filename of the application's executable.
|
## Returns the filename of the application's executable.
|
||||||
|
## **Note**: This does not work reliably on BSD.
|
||||||
|
|
||||||
# Linux: /proc/<pid>/exe
|
# Linux: /proc/<pid>/exe
|
||||||
# Solaris:
|
# Solaris:
|
||||||
|
|
@ -1410,6 +1411,7 @@ proc getApplicationDir*(): string {.rtl, extern: "nos$1", deprecated.} =
|
||||||
|
|
||||||
proc getAppDir*(): string {.rtl, extern: "nos$1".} =
|
proc getAppDir*(): string {.rtl, extern: "nos$1".} =
|
||||||
## Returns the directory of the application's executable.
|
## Returns the directory of the application's executable.
|
||||||
|
## **Note**: This does not work reliably on BSD.
|
||||||
result = splitFile(getAppFilename()).dir
|
result = splitFile(getAppFilename()).dir
|
||||||
|
|
||||||
proc sleep*(milsecs: int) {.rtl, extern: "nos$1".} =
|
proc sleep*(milsecs: int) {.rtl, extern: "nos$1".} =
|
||||||
|
|
|
||||||
|
|
@ -1486,10 +1486,10 @@ proc primary(p: var TPegParser): TPeg =
|
||||||
return !primary(p)
|
return !primary(p)
|
||||||
of tkAt:
|
of tkAt:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
return @primary(p)
|
return @(primary(p))
|
||||||
of tkCurlyAt:
|
of tkCurlyAt:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
return @@primary(p).token(p)
|
return @@(primary(p).token(p))
|
||||||
else: nil
|
else: nil
|
||||||
case p.tok.kind
|
case p.tok.kind
|
||||||
of tkIdentifier:
|
of tkIdentifier:
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
16
tests/compile/tmongo.nim
Normal file
16
tests/compile/tmongo.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
import mongo, db_mongo, oids, json
|
||||||
|
|
||||||
|
var conn = db_mongo.open()
|
||||||
|
|
||||||
|
var data = %{"a": %13, "b": %"my string value",
|
||||||
|
"inner": %{"i": %71} }
|
||||||
|
|
||||||
|
var id = insertID(conn, "test.test", data)
|
||||||
|
|
||||||
|
for v in find(conn, "test.test", "this.a == 13"):
|
||||||
|
print v
|
||||||
|
|
||||||
|
delete(conn, "test.test", id)
|
||||||
|
|
||||||
|
close(conn)
|
||||||
31
todo.txt
31
todo.txt
|
|
@ -1,6 +1,7 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
- sigil-like operator: @x.abc parsed as (@x).abc
|
||||||
- document AVR/embedded systems better
|
- document AVR/embedded systems better
|
||||||
- implement ``--script:sh|bat`` command line option
|
- implement ``--script:sh|bat`` command line option
|
||||||
- make GC realtime capable: GC_step(ms: int)
|
- make GC realtime capable: GC_step(ms: int)
|
||||||
|
|
@ -14,7 +15,6 @@ version 0.9.0
|
||||||
- test constant closures
|
- test constant closures
|
||||||
|
|
||||||
- dead code elim for JS backend; 'of' operator for JS backend
|
- dead code elim for JS backend; 'of' operator for JS backend
|
||||||
- const ptr/ref
|
|
||||||
- unsigned ints and bignums; requires abstract integer literal type:
|
- unsigned ints and bignums; requires abstract integer literal type:
|
||||||
use tyInt+node for that
|
use tyInt+node for that
|
||||||
- implement the high level optimizer
|
- implement the high level optimizer
|
||||||
|
|
@ -25,10 +25,7 @@ version 0.9.0
|
||||||
- we need to support iteration of 2 different data structures in parallel
|
- we need to support iteration of 2 different data structures in parallel
|
||||||
- make exceptions compatible with C++ exceptions
|
- make exceptions compatible with C++ exceptions
|
||||||
- change how comments are part of the AST
|
- change how comments are part of the AST
|
||||||
- optional indentation for 'case' statement; hm, keep in mind other syntax
|
|
||||||
changes that people want; may turn out to be a bad idea
|
|
||||||
- activate more thread tests
|
- activate more thread tests
|
||||||
- optimize method dispatchers
|
|
||||||
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
||||||
indentation handling is quite complex too; problem with exception handling
|
indentation handling is quite complex too; problem with exception handling
|
||||||
is that often the scope of ``try`` is wrong and apart from that ``try`` is
|
is that often the scope of ``try`` is wrong and apart from that ``try`` is
|
||||||
|
|
@ -63,18 +60,11 @@ version 0.9.XX
|
||||||
- implicit ref/ptr->var conversion; the compiler may store an object
|
- implicit ref/ptr->var conversion; the compiler may store an object
|
||||||
implicitly on the heap for write barrier efficiency; better:
|
implicitly on the heap for write barrier efficiency; better:
|
||||||
proc specialization in the code gen
|
proc specialization in the code gen
|
||||||
- shared memory heap: ``shared ref`` etc. The only hard part in the GC is to
|
|
||||||
"stop the world". However, it may be worthwhile to generate explicit
|
|
||||||
(or implicit) syncGC() calls in loops. Automatic loop injection seems
|
|
||||||
troublesome, but maybe we can come up with a simple heuristic. (All procs
|
|
||||||
that `new` shared memory are syncGC() candidates...)
|
|
||||||
- EcmaScript needs a new and better code gen: simply adapt the C code gen to it
|
- EcmaScript needs a new and better code gen: simply adapt the C code gen to it
|
||||||
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
||||||
- nested tuple unpacking; tuple unpacking in non-var-context
|
- nested tuple unpacking; tuple unpacking in non-var-context
|
||||||
- 'nimrod def': does not always work?
|
- 'nimrod def': does not always work?
|
||||||
- implement/generalize the effect system
|
|
||||||
- test branch coverage
|
- test branch coverage
|
||||||
- checked exceptions
|
|
||||||
- make pegs support a compile-time option and make c2nim use regexes instead
|
- make pegs support a compile-time option and make c2nim use regexes instead
|
||||||
per default?
|
per default?
|
||||||
- 'const' objects including case objects
|
- 'const' objects including case objects
|
||||||
|
|
@ -103,7 +93,6 @@ version 0.9.XX
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- wrappers for mongodb
|
|
||||||
- suffix trees
|
- suffix trees
|
||||||
- locale support; i18n module
|
- locale support; i18n module
|
||||||
- bignums
|
- bignums
|
||||||
|
|
@ -144,6 +133,7 @@ Low priority
|
||||||
- implement explicit varargs; **but** ``len(varargs)`` problem remains!
|
- implement explicit varargs; **but** ``len(varargs)`` problem remains!
|
||||||
--> solve by implicit conversion from varargs to openarray
|
--> solve by implicit conversion from varargs to openarray
|
||||||
- implement closures that support nesting > 1
|
- implement closures that support nesting > 1
|
||||||
|
- optimize method dispatchers
|
||||||
|
|
||||||
|
|
||||||
Further optimization ideas
|
Further optimization ideas
|
||||||
|
|
@ -153,8 +143,21 @@ Further optimization ideas
|
||||||
information inlining would provide, but don't inline for code size reasons.
|
information inlining would provide, but don't inline for code size reasons.
|
||||||
|
|
||||||
|
|
||||||
Version 2
|
Version 2 and beyond
|
||||||
=========
|
====================
|
||||||
|
|
||||||
|
|
||||||
|
- shared memory heap: ``shared ref`` etc. The only hard part in the GC is to
|
||||||
|
"stop the world". However, it may be worthwhile to generate explicit
|
||||||
|
(or implicit) syncGC() calls in loops. Automatic loop injection seems
|
||||||
|
troublesome, but maybe we can come up with a simple heuristic. (All procs
|
||||||
|
that `new` shared memory are syncGC() candidates...)
|
||||||
|
|
||||||
|
- implement/generalize the effect system; checked exceptions
|
||||||
|
- const ptr/ref
|
||||||
|
|
||||||
|
- optional indentation for 'case' statement; hm, keep in mind other syntax
|
||||||
|
changes that people want; may turn out to be a bad idea
|
||||||
|
|
||||||
- language change: inheritance should only work with reference types, so that
|
- language change: inheritance should only work with reference types, so that
|
||||||
the ``type`` field is not needed for objects! --> zero overhead aggregation
|
the ``type`` field is not needed for objects! --> zero overhead aggregation
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ Please choose your platform:
|
||||||
|
|
||||||
The source-based installation has been tested on these systems:
|
The source-based installation has been tested on these systems:
|
||||||
* Linux: i386, AMD64, PowerPC
|
* Linux: i386, AMD64, PowerPC
|
||||||
|
* BSD: AMD64
|
||||||
* Mac OS X: i386, AMD64
|
* Mac OS X: i386, AMD64
|
||||||
|
|
||||||
Other UNIX-based operating systems may work. An older version was tested on
|
Other UNIX-based operating systems may work.
|
||||||
FreeBSD (i386).
|
|
||||||
|
|
||||||
.. include:: ../install.txt
|
.. include:: ../install.txt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,11 @@ Welcome to Nimrod
|
||||||
*Nimrod looks like this:*
|
*Nimrod looks like this:*
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
# Filter key=value pairs
|
import strutils
|
||||||
import re
|
|
||||||
|
echo "List of ints (separate by whitespace): "
|
||||||
for x in lines("myfile.txt"):
|
echo stdin.readLine.split.each(parseInt).max,
|
||||||
if x =~ re"(\w+)=(.*)":
|
" is the maximum"
|
||||||
echo "Key: ", matches[0],
|
|
||||||
" Value: ", matches[1]
|
|
||||||
|
|
||||||
**Nimrod** is a new statically typed, imperative
|
**Nimrod** is a new statically typed, imperative
|
||||||
programming language, that supports procedural, object oriented, functional
|
programming language, that supports procedural, object oriented, functional
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ Library Additions
|
||||||
- Added ``macros.emit`` that can emit an arbitrary computed string as nimrod
|
- Added ``macros.emit`` that can emit an arbitrary computed string as nimrod
|
||||||
code during compilation.
|
code during compilation.
|
||||||
- Added ``strutils.parseEnum``.
|
- Added ``strutils.parseEnum``.
|
||||||
|
- Added ``json.%`` constructor operator.
|
||||||
- The stdlib can now be avoided to a point where C code generation for 16bit
|
- The stdlib can now be avoided to a point where C code generation for 16bit
|
||||||
micro controllers is feasible.
|
micro controllers is feasible.
|
||||||
- Added module ``oids``.
|
- Added module ``oids``.
|
||||||
|
|
@ -55,6 +56,8 @@ Compiler Additions
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- Win64 is now an officially supported target.
|
- Win64 is now an officially supported target.
|
||||||
|
- The Nimrod compiler works on BSD again, but has some issues
|
||||||
|
as ``os.getAppFilename`` and ``os.getAppDir`` cannot work reliably on BSD.
|
||||||
- The compiler can detect and evaluate calls that can be evaluated at compile
|
- The compiler can detect and evaluate calls that can be evaluated at compile
|
||||||
time for optimization purposes with the ``--implicitStatic`` command line
|
time for optimization purposes with the ``--implicitStatic`` command line
|
||||||
option or pragma.
|
option or pragma.
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ srcdoc: "pure/parseopt;pure/hashes;pure/strtabs;pure/lexbase"
|
||||||
srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"
|
srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"
|
||||||
srcdoc: "pure/streams;pure/terminal;pure/cgi;impure/web;pure/unicode"
|
srcdoc: "pure/streams;pure/terminal;pure/cgi;impure/web;pure/unicode"
|
||||||
srcdoc: "impure/zipfiles;pure/htmlgen;pure/parseutils;pure/browsers"
|
srcdoc: "impure/zipfiles;pure/htmlgen;pure/parseutils;pure/browsers"
|
||||||
srcdoc: "impure/db_postgres;impure/db_mysql;impure/db_sqlite"
|
srcdoc: "impure/db_postgres;impure/db_mysql;impure/db_sqlite;impure/db_mongo"
|
||||||
srcdoc: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl"
|
srcdoc: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl"
|
||||||
srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
|
srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
|
||||||
srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors"
|
srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue