mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-29 11:47:56 +00:00
Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
@@ -51,6 +51,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/idents.c -o build/1_1/idents.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/idents.c -o build/1_1/idents.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/astalgo.c -o build/1_1/astalgo.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/astalgo.c -o build/1_1/astalgo.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodutils.c -o build/1_1/rodutils.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodutils.c -o build/1_1/rodutils.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/extccomp.c -o build/1_1/extccomp.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/extccomp.c -o build/1_1/extccomp.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/osproc.c -o build/1_1/osproc.o
|
||||
@@ -146,8 +148,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/transf.c -o build/1_1/transf.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o
|
||||
|
||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
|
||||
ECHO SUCCESS
|
||||
|
||||
|
||||
@@ -45,16 +45,12 @@ doc.body_toc = """
|
||||
$tableofcontents
|
||||
<div class="content" id="content">
|
||||
$moduledesc
|
||||
<h1>Dependencies</h1>
|
||||
$deps
|
||||
$content
|
||||
</div>
|
||||
"""
|
||||
|
||||
doc.body_no_toc = """
|
||||
$moduledesc
|
||||
<h1>Dependencies</h1>
|
||||
$deps
|
||||
$content
|
||||
"""
|
||||
|
||||
|
||||
@@ -30,17 +30,11 @@ doc.toc = r"\tableofcontents \newpage"
|
||||
doc.body_toc = """
|
||||
$tableofcontents
|
||||
$moduledesc
|
||||
|
||||
Dependencies: $deps
|
||||
|
||||
$content
|
||||
"""
|
||||
|
||||
doc.body_no_toc = """
|
||||
$moduledesc
|
||||
|
||||
Dependencies: $deps
|
||||
|
||||
$content
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Configuration file for the Nimrod Compiler.
|
||||
# (c) 2010 Andreas Rumpf
|
||||
# (c) 2011 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
@@ -14,6 +14,7 @@ cc = gcc
|
||||
lib = "nimlib"
|
||||
@end
|
||||
|
||||
path="$lib/core"
|
||||
path="$lib/pure"
|
||||
path="$lib/impure"
|
||||
path="$lib/wrappers"
|
||||
|
||||
@@ -31,6 +31,9 @@ Core
|
||||
implicitly by the compiler. Do not import it directly. It relies on compiler
|
||||
magic to work.
|
||||
|
||||
* `threads <threads.html>`_
|
||||
Nimrod thread support.
|
||||
|
||||
* `macros <macros.html>`_
|
||||
Contains the AST API and documentation of Nimrod for writing macros.
|
||||
|
||||
|
||||
@@ -70,13 +70,24 @@ However, the generated C code is not platform independent. C code generated for
|
||||
Linux does not compile on Windows, for instance. The comment on top of the
|
||||
C file lists the OS, CPU and CC the file has been compiled for.
|
||||
|
||||
|
||||
Cross compilation
|
||||
=================
|
||||
|
||||
To `cross compile`:idx:, use for example::
|
||||
|
||||
nimrod c --cpu:i386 --os:linux --compile_only --gen_script myproject.nim
|
||||
|
||||
Then move the C code and the compile script ``compile_myproject.sh`` to your
|
||||
Linux i386 machine and run the script.
|
||||
|
||||
|
||||
DLL generation
|
||||
==============
|
||||
|
||||
Nimrod supports the generation of DLLs. However, there must be only one
|
||||
instance of the GC per process/address space. This instance is contained in
|
||||
``nimrtl.dll``. This means that every generated Nimrod DLL depends
|
||||
``nimrtl.dll``. This means that every generated Nimrod `DLL`:idx: depends
|
||||
on ``nimrtl.dll``. To generate the "nimrtl.dll" file, use the command::
|
||||
|
||||
nimrod c -d:release lib/nimrtl.nim
|
||||
|
||||
20
install.sh
20
install.sh
@@ -321,6 +321,8 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/system/sysstr.nim
|
||||
cp lib/system/systhread.nim $libdir/system/systhread.nim
|
||||
chmod 644 $libdir/system/systhread.nim
|
||||
cp lib/pure/base64.nim $libdir/pure/base64.nim
|
||||
chmod 644 $libdir/pure/base64.nim
|
||||
cp lib/pure/browsers.nim $libdir/pure/browsers.nim
|
||||
chmod 644 $libdir/pure/browsers.nim
|
||||
cp lib/pure/cgi.nim $libdir/pure/cgi.nim
|
||||
@@ -329,12 +331,12 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/colors.nim
|
||||
cp lib/pure/complex.nim $libdir/pure/complex.nim
|
||||
chmod 644 $libdir/pure/complex.nim
|
||||
cp lib/pure/cookies.nim $libdir/pure/cookies.nim
|
||||
chmod 644 $libdir/pure/cookies.nim
|
||||
cp lib/pure/dynlib.nim $libdir/pure/dynlib.nim
|
||||
chmod 644 $libdir/pure/dynlib.nim
|
||||
cp lib/pure/hashes.nim $libdir/pure/hashes.nim
|
||||
chmod 644 $libdir/pure/hashes.nim
|
||||
cp lib/pure/hashtabs.nim $libdir/pure/hashtabs.nim
|
||||
chmod 644 $libdir/pure/hashtabs.nim
|
||||
cp lib/pure/htmlparser.nim $libdir/pure/htmlparser.nim
|
||||
chmod 644 $libdir/pure/htmlparser.nim
|
||||
cp lib/pure/httpclient.nim $libdir/pure/httpclient.nim
|
||||
@@ -347,8 +349,6 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/lexbase.nim
|
||||
cp lib/pure/logging.nim $libdir/pure/logging.nim
|
||||
chmod 644 $libdir/pure/logging.nim
|
||||
cp lib/pure/macros.nim $libdir/pure/macros.nim
|
||||
chmod 644 $libdir/pure/macros.nim
|
||||
cp lib/pure/math.nim $libdir/pure/math.nim
|
||||
chmod 644 $libdir/pure/math.nim
|
||||
cp lib/pure/md5.nim $libdir/pure/md5.nim
|
||||
@@ -377,6 +377,10 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/regexprs.nim
|
||||
cp lib/pure/ropes.nim $libdir/pure/ropes.nim
|
||||
chmod 644 $libdir/pure/ropes.nim
|
||||
cp lib/pure/scgi.nim $libdir/pure/scgi.nim
|
||||
chmod 644 $libdir/pure/scgi.nim
|
||||
cp lib/pure/smtp.nim $libdir/pure/smtp.nim
|
||||
chmod 644 $libdir/pure/smtp.nim
|
||||
cp lib/pure/sockets.nim $libdir/pure/sockets.nim
|
||||
chmod 644 $libdir/pure/sockets.nim
|
||||
cp lib/pure/streams.nim $libdir/pure/streams.nim
|
||||
@@ -391,8 +395,6 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/times.nim
|
||||
cp lib/pure/unicode.nim $libdir/pure/unicode.nim
|
||||
chmod 644 $libdir/pure/unicode.nim
|
||||
cp lib/pure/variants.nim $libdir/pure/variants.nim
|
||||
chmod 644 $libdir/pure/variants.nim
|
||||
cp lib/pure/xmldom.nim $libdir/pure/xmldom.nim
|
||||
chmod 644 $libdir/pure/xmldom.nim
|
||||
cp lib/pure/xmldomparser.nim $libdir/pure/xmldomparser.nim
|
||||
@@ -421,10 +423,14 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/impure/osinfo_win.nim
|
||||
cp lib/impure/re.nim $libdir/impure/re.nim
|
||||
chmod 644 $libdir/impure/re.nim
|
||||
cp lib/impure/ssl.nim $libdir/impure/ssl.nim
|
||||
chmod 644 $libdir/impure/ssl.nim
|
||||
cp lib/impure/web.nim $libdir/impure/web.nim
|
||||
chmod 644 $libdir/impure/web.nim
|
||||
cp lib/impure/zipfiles.nim $libdir/impure/zipfiles.nim
|
||||
chmod 644 $libdir/impure/zipfiles.nim
|
||||
cp lib/wrappers/claro.nim $libdir/wrappers/claro.nim
|
||||
chmod 644 $libdir/wrappers/claro.nim
|
||||
cp lib/wrappers/expat.nim $libdir/wrappers/expat.nim
|
||||
chmod 644 $libdir/wrappers/expat.nim
|
||||
cp lib/wrappers/iup.nim $libdir/wrappers/iup.nim
|
||||
@@ -435,6 +441,8 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/wrappers/mysql.nim
|
||||
cp lib/wrappers/odbcsql.nim $libdir/wrappers/odbcsql.nim
|
||||
chmod 644 $libdir/wrappers/odbcsql.nim
|
||||
cp lib/wrappers/openssl.nim $libdir/wrappers/openssl.nim
|
||||
chmod 644 $libdir/wrappers/openssl.nim
|
||||
cp lib/wrappers/pcre.nim $libdir/wrappers/pcre.nim
|
||||
chmod 644 $libdir/wrappers/pcre.nim
|
||||
cp lib/wrappers/postgres.nim $libdir/wrappers/postgres.nim
|
||||
|
||||
259
lib/core/marshal.nim
Normal file
259
lib/core/marshal.nim
Normal file
@@ -0,0 +1,259 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains procs for serialization and deseralization of
|
||||
## arbitrary Nimrod data structures. XXX This is not implemented yet!
|
||||
|
||||
import streams
|
||||
|
||||
proc load*[T](s: PStream, data: var T) {.magic: "Load".}
|
||||
## loads `data` from the stream `s`. Raises `EIO` in case of an error.
|
||||
|
||||
proc store*[T](s: PStream, data: T) {.magic: "Store".}
|
||||
## stores `data` into the stream `s`. Raises `EIO` in case of an error.
|
||||
|
||||
|
||||
proc reprInt(x: int64): string {.compilerproc.} = return $x
|
||||
proc reprFloat(x: float): string {.compilerproc.} = return $x
|
||||
|
||||
proc reprPointer(x: pointer): string {.compilerproc.} =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%p", x)
|
||||
return $buf
|
||||
|
||||
proc reprStrAux(result: var string, s: string) =
|
||||
if cast[pointer](s) == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
add result, reprPointer(cast[pointer](s)) & "\""
|
||||
for c in items(s):
|
||||
case c
|
||||
of '"': add result, "\\\""
|
||||
of '\\': add result, "\\\\" # BUGFIX: forgotten
|
||||
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
|
||||
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
|
||||
add result, "\\" & reprInt(ord(c))
|
||||
else: result.add(c)
|
||||
add result, "\""
|
||||
|
||||
proc reprStr(s: string): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprStrAux(result, s)
|
||||
|
||||
proc reprBool(x: bool): string {.compilerRtl.} =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc reprChar(x: char): string {.compilerRtl.} =
|
||||
result = "\'"
|
||||
case x
|
||||
of '"': add result, "\\\""
|
||||
of '\\': add result, "\\\\"
|
||||
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
|
||||
else: add result, x
|
||||
add result, "\'"
|
||||
|
||||
proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
|
||||
if e <% typ.node.len: # BUGFIX
|
||||
result = $typ.node.sons[e].name
|
||||
else:
|
||||
result = $e & " (invalid data!)"
|
||||
|
||||
type
|
||||
pbyteArray = ptr array[0.. 0xffff, byte]
|
||||
|
||||
proc addSetElem(result: var string, elem: int, typ: PNimType) =
|
||||
case typ.kind
|
||||
of tyEnum: add result, reprEnum(elem, typ)
|
||||
of tyBool: add result, reprBool(bool(elem))
|
||||
of tyChar: add result, reprChar(chr(elem))
|
||||
of tyRange: addSetElem(result, elem, typ.base)
|
||||
of tyInt..tyInt64: add result, reprInt(elem)
|
||||
else: # data corrupt --> inform the user
|
||||
add result, " (invalid data!)"
|
||||
|
||||
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
||||
# "typ.slots.len" field is for sets the "first" field
|
||||
var elemCounter = 0 # we need this flag for adding the comma at
|
||||
# the right places
|
||||
add result, "{"
|
||||
var u: int64
|
||||
case typ.size
|
||||
of 1: u = ze64(cast[ptr int8](p)^)
|
||||
of 2: u = ze64(cast[ptr int16](p)^)
|
||||
of 4: u = ze64(cast[ptr int32](p)^)
|
||||
of 8: u = cast[ptr int64](p)^
|
||||
else:
|
||||
var a = cast[pbyteArray](p)
|
||||
for i in 0 .. typ.size*8-1:
|
||||
if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
if typ.size <= 8:
|
||||
for i in 0..sizeof(int64)*8-1:
|
||||
if (u and (1 shl i)) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
add result, "}"
|
||||
|
||||
proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprSetAux(result, p, typ)
|
||||
|
||||
type
|
||||
TReprClosure {.final.} = object # we cannot use a global variable here
|
||||
# as this wouldn't be thread-safe
|
||||
marked: TCellSet
|
||||
recdepth: int # do not recurse endless
|
||||
indent: int # indentation
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc initReprClosure(cl: var TReprClosure) =
|
||||
Init(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
Deinit(cl.marked)
|
||||
|
||||
proc reprBreak(result: var string, cl: TReprClosure) =
|
||||
add result, "\n"
|
||||
for i in 0..cl.indent-1: add result, ' '
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure)
|
||||
|
||||
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
var bs = typ.base.size
|
||||
for i in 0..typ.size div bs - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if p == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
result.add(reprPointer(p) & "[")
|
||||
var bs = typ.base.size
|
||||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
cl: var TReprClosure) =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
add result, $n.name
|
||||
add result, " = "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
if i > 0: add result, ",\n"
|
||||
reprRecordAux(result, p, n.sons[i], cl)
|
||||
of nkCase:
|
||||
var m = selectBranch(p, n)
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
if m != nil: reprRecordAux(result, p, m, cl)
|
||||
|
||||
proc reprRecord(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
reprRecordAux(result, p, typ.node, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRef(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
# we know that p is not nil here:
|
||||
when defined(boehmGC) or defined(nogc):
|
||||
var cell = cast[PCell](p)
|
||||
else:
|
||||
var cell = usrToCell(p)
|
||||
add result, "ref " & reprPointer(p)
|
||||
if cell notin cl.marked:
|
||||
# only the address is shown:
|
||||
incl(cl.marked, cell)
|
||||
add result, " --> "
|
||||
reprAux(result, p, typ.base, cl)
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if cl.recdepth == 0:
|
||||
add result, "..."
|
||||
return
|
||||
dec(cl.recdepth)
|
||||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
|
||||
of tyObject:
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
assert(p != nil)
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)^, typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)^, typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)^)
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)^)
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)^)
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)^)
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)^)
|
||||
of tyFloat: add result, $(cast[ptr float](p)^)
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)^)
|
||||
of tyFloat64: add result, $(cast[ptr float64](p)^)
|
||||
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
|
||||
of tyBool: add result, reprBool(cast[ptr bool](p)^)
|
||||
of tyChar: add result, reprChar(cast[ptr char](p)^)
|
||||
of tyString: reprStrAux(result, cast[ptr string](p)^)
|
||||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)^)
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
|
||||
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
|
||||
compilerRtl.} =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = "["
|
||||
var bs = elemtyp.size
|
||||
for i in 0..length - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), elemtyp, cl)
|
||||
add result, "]"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc reprAny(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
var p = p
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
174
lib/core/threads.nim
Normal file
174
lib/core/threads.nim
Normal file
@@ -0,0 +1,174 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Basic thread support for Nimrod. Note that Nimrod's default GC is still
|
||||
## single-threaded. This means that either your threads should not allocate
|
||||
## GC'ed memory, or you should compile with ``--gc:none`` or ``--gc:boehm``.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## var
|
||||
## thr: array [0..4, TThread]
|
||||
## L: TLock
|
||||
##
|
||||
## proc threadFunc(c: pointer) {.procvar.} =
|
||||
## for i in 0..9:
|
||||
## Aquire(L) # lock stdout
|
||||
## echo i
|
||||
## Release(L)
|
||||
##
|
||||
## InitLock(L)
|
||||
##
|
||||
## for i in 0..high(thr):
|
||||
## createThread(thr[i], threadFunc)
|
||||
## for i in 0..high(thr):
|
||||
## joinThread(thr[i])
|
||||
|
||||
|
||||
# We jump through some hops here to ensure that Nimrod thread procs can have
|
||||
# the Nimrod calling convention. This is needed because thread procs are
|
||||
# ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
|
||||
# use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway. However,
|
||||
# the current approach will likely result in less problems later when we have
|
||||
# GC'ed closures in Nimrod.
|
||||
|
||||
type
|
||||
TThreadProc* = proc (closure: pointer) ## Standard Nimrod thread proc.
|
||||
TThreadProcClosure {.pure, final.} = object
|
||||
fn: TThreadProc
|
||||
data: pointer
|
||||
|
||||
when defined(Windows):
|
||||
type
|
||||
THandle = int
|
||||
TSysThread = THandle
|
||||
TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
|
||||
DebugInfo: pointer
|
||||
LockCount: int32
|
||||
RecursionCount: int32
|
||||
OwningThread: int
|
||||
LockSemaphore: int
|
||||
Reserved: int32
|
||||
|
||||
TWinThreadProc = proc (x: pointer): int32 {.stdcall.}
|
||||
|
||||
TLock* = TSysLock ## Standard Nimrod Lock type.
|
||||
|
||||
proc InitLock*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
||||
## Initializes the lock `L`.
|
||||
|
||||
proc Aquire*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
||||
## Aquires the lock `L`.
|
||||
|
||||
proc Release*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
||||
## Releases the lock `L`.
|
||||
|
||||
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
|
||||
lpStartAddress: TWinThreadProc,
|
||||
lpParameter: Pointer,
|
||||
dwCreationFlags: int32, lpThreadId: var int32): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
||||
when false:
|
||||
proc winSuspendThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SuspendThread".}
|
||||
|
||||
proc winResumeThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "ResumeThread".}
|
||||
|
||||
proc WaitForMultipleObjects(nCount: int32,
|
||||
lpHandles: ptr array[0..10, THandle],
|
||||
bWaitAll: int32,
|
||||
dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||
|
||||
proc WaitForSingleObject(hHandle: THANDLE, dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
|
||||
|
||||
proc TerminateThread(hThread: THandle, dwExitCode: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "TerminateThread".}
|
||||
|
||||
proc threadProcWrapper(closure: pointer): int32 {.stdcall.} =
|
||||
var c = cast[ptr TThreadProcClosure](closure)
|
||||
c.fn(c.data)
|
||||
# implicitely return 0
|
||||
|
||||
else:
|
||||
type
|
||||
TSysLock {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
|
||||
TSysThread {.importc: "pthread_t", header: "<sys/types.h>".} = int
|
||||
|
||||
TLock* = TSysLock
|
||||
|
||||
proc InitLockAux(L: var TSysLock, attr: pointer = nil) {.
|
||||
importc: "pthread_mutex_init", header: "<pthread.h>".}
|
||||
|
||||
proc InitLock*(L: var TLock) {.inline.} =
|
||||
InitLockAux(L)
|
||||
proc Aquire*(L: var TLock) {.
|
||||
importc: "pthread_mutex_lock", header: "<pthread.h>".}
|
||||
proc Release*(L: var TLock) {.
|
||||
importc: "pthread_mutex_unlock", header: "<pthread.h>".}
|
||||
|
||||
proc pthread_create(a1: var TSysThread, a2: ptr int,
|
||||
a3: proc (x: pointer) {.noconv.},
|
||||
a4: pointer): cint {.importc: "pthread_create",
|
||||
header: "<pthread.h>".}
|
||||
proc pthread_join(a1: TSysThread, a2: ptr pointer): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_cancel(a1: TSysThread): cint {.
|
||||
importc: "pthread_cancel", header: "<pthread.h>".}
|
||||
|
||||
proc threadProcWrapper(closure: pointer) {.noconv.} =
|
||||
var c = cast[ptr TThreadProcClosure](closure)
|
||||
c.fn(c.data)
|
||||
|
||||
{.passL: "-pthread".}
|
||||
{.passC: "-pthread".}
|
||||
|
||||
type
|
||||
TThread* = object of TObject ## Nimrod thread.
|
||||
sys: TSysThread
|
||||
c: TThreadProcClosure
|
||||
|
||||
|
||||
proc createThread*(t: var TThread, tp: TThreadProc,
|
||||
closure: pointer = nil) =
|
||||
## creates a new thread `t` and starts its execution. Entry point is the
|
||||
## proc `tp`. `closure` is passed to `tp`.
|
||||
t.c.data = closure
|
||||
t.c.fn = tp
|
||||
when defined(windows):
|
||||
var dummyThreadId: int32
|
||||
t.sys = CreateThread(nil, 0'i32, threadProcWrapper, addr(t.c), 0'i32,
|
||||
dummyThreadId)
|
||||
else:
|
||||
discard pthread_create(t.sys, nil, threadProcWrapper, addr(t.c))
|
||||
|
||||
proc joinThread*(t: TThread) =
|
||||
## waits for the thread `t` until it has terminated.
|
||||
when defined(windows):
|
||||
discard WaitForSingleObject(t.sys, -1'i32)
|
||||
else:
|
||||
discard pthread_join(t.sys, nil)
|
||||
|
||||
proc destroyThread*(t: var TThread) =
|
||||
## forces the thread `t` to terminate. This is potentially dangerous if
|
||||
## you don't have full control over `t` and its aquired ressources.
|
||||
when defined(windows):
|
||||
discard TerminateThread(t.sys, 1'i32)
|
||||
else:
|
||||
discard pthread_cancel(t.sys)
|
||||
|
||||
@@ -71,7 +71,11 @@ __TINYC__
|
||||
# define NIM_CONST const
|
||||
#endif
|
||||
|
||||
#define NIM_THREADVAR __thread
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||
# define NIM_THREADVAR __declspec(thread)
|
||||
#else
|
||||
# define NIM_THREADVAR __thread
|
||||
#endif
|
||||
|
||||
/* --------------- how int64 constants should be declared: ----------- */
|
||||
#if defined(__GNUC__) || defined(__LCC__) || \
|
||||
@@ -415,8 +419,9 @@ struct TFrame {
|
||||
NI len;
|
||||
};
|
||||
|
||||
/*
|
||||
extern TFrame* framePtr;
|
||||
/*extern TSafePoint* excHandler; */
|
||||
extern TSafePoint* excHandler; */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct NimException {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
## Coding conventions:
|
||||
## ALL types are named the same as in the POSIX standard except that they start
|
||||
## with 'T' or 'P' (if they are pointers) and without the '_t' prefix to be
|
||||
## with 'T' or 'P' (if they are pointers) and without the '_t' suffix to be
|
||||
## consistent with Nimrod conventions. If an identifier is a Nimrod keyword
|
||||
## the \`identifier\` notation is used.
|
||||
##
|
||||
## This library relies on the header files of your C compiler. Thus the
|
||||
## This library relies on the header files of your C compiler. The
|
||||
## resulting C code will just include <XYZ.h> and *not* define the
|
||||
## symbols declared here.
|
||||
|
||||
|
||||
@@ -1259,6 +1259,18 @@ var
|
||||
## each executed instruction. This should only be used by debuggers!
|
||||
## Only code compiled with the ``debugger:on`` switch calls this hook.
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl, final.} = object
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
var
|
||||
framePtr {.threadvar, compilerproc.}: PFrame
|
||||
|
||||
when not defined(ECMAScript):
|
||||
{.push overflow_checks:off}
|
||||
proc add* (x: var string, y: cstring) =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -40,10 +40,10 @@ type
|
||||
context: C_JmpBuf
|
||||
|
||||
var
|
||||
excHandler {.compilerproc.}: PSafePoint = nil
|
||||
excHandler {.threadvar, compilerproc.}: PSafePoint = nil
|
||||
# list of exception handlers
|
||||
# a global variable for the root of all try blocks
|
||||
currException: ref E_Base
|
||||
currException {.threadvar.}: ref E_Base
|
||||
|
||||
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||
s.prev = excHandler
|
||||
@@ -107,23 +107,11 @@ when nativeStacktrace:
|
||||
# interested in
|
||||
enabled = true
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl, final.} = object
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
var
|
||||
buf: string # cannot be allocated on the stack!
|
||||
assertBuf: string # we need a different buffer for
|
||||
# assert, as it raises an exception and
|
||||
# exception handler needs the buffer too
|
||||
|
||||
framePtr {.exportc.}: PFrame
|
||||
|
||||
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
|
||||
@@ -61,8 +61,9 @@ type
|
||||
decStack: TCellSeq # cells in the stack that are to decref again
|
||||
cycleRoots: TCellSet
|
||||
tempStack: TCellSeq # temporary stack for recursion elimination
|
||||
cycleRootsLock: TSysLock
|
||||
zctLock: TSysLock
|
||||
when hasThreadSupport:
|
||||
cycleRootsLock: TSysLock
|
||||
zctLock: TSysLock
|
||||
stat: TGcStat
|
||||
|
||||
var
|
||||
@@ -281,8 +282,9 @@ proc initGC() =
|
||||
init(gch.tempStack)
|
||||
Init(gch.cycleRoots)
|
||||
Init(gch.decStack)
|
||||
InitLock(gch.cycleRootsLock)
|
||||
InitLock(gch.zctLock)
|
||||
when hasThreadSupport:
|
||||
InitLock(gch.cycleRootsLock)
|
||||
InitLock(gch.zctLock)
|
||||
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
|
||||
|
||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -44,72 +44,4 @@ proc atomicDec(memLoc: var int, x: int): int =
|
||||
else:
|
||||
dec(memLoc, x)
|
||||
result = memLoc
|
||||
|
||||
when defined(Windows):
|
||||
type
|
||||
THandle = int
|
||||
TSysThread = THandle
|
||||
TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
|
||||
DebugInfo: pointer
|
||||
LockCount: int32
|
||||
RecursionCount: int32
|
||||
OwningThread: int
|
||||
LockSemaphore: int
|
||||
Reserved: int32
|
||||
|
||||
proc InitLock(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
||||
proc Aquire(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
||||
proc Release(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
||||
|
||||
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
|
||||
lpStartAddress: pointer, lpParameter: Pointer,
|
||||
dwCreationFlags: int32, lpThreadId: var int32): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
||||
|
||||
else:
|
||||
type
|
||||
TSysLock {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
|
||||
TSysThread {.importc: "pthread_t", header: "<sys/types.h>".} = int
|
||||
|
||||
proc InitLock(L: var TSysLock, attr: pointer = nil) {.
|
||||
importc: "pthread_mutex_init", header: "<pthread.h>".}
|
||||
proc Aquire(L: var TSysLock) {.
|
||||
importc: "pthread_mutex_lock", header: "<pthread.h>".}
|
||||
proc Release(L: var TSysLock) {.
|
||||
importc: "pthread_mutex_unlock", header: "<pthread.h>".}
|
||||
|
||||
|
||||
type
|
||||
TThread* = TSysThread
|
||||
TLock* = TSysLock
|
||||
TThreadFunc* = proc (closure: pointer) {.cdecl.}
|
||||
|
||||
#DWORD WINAPI SuspendThread(
|
||||
# __in HANDLE hThread
|
||||
#);
|
||||
#DWORD WINAPI ResumeThread(
|
||||
# __in HANDLE hThread
|
||||
#);
|
||||
#DWORD WINAPI ThreadProc(
|
||||
# __in LPVOID lpParameter
|
||||
#);
|
||||
|
||||
proc createThread*(t: var TThread, fn: TThreadFunc, closure: pointer) =
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
nil
|
||||
#pthread_create(
|
||||
|
||||
proc joinThread*(t: TThread) =
|
||||
nil
|
||||
|
||||
#proc pthread_exit(void *value_ptr)
|
||||
|
||||
proc destroyThread*(t: var TThread) =
|
||||
nil
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ type
|
||||
skParam, # a parameter
|
||||
skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()``
|
||||
skTemp, # a temporary variable (introduced by compiler)
|
||||
skModule, # module identifier
|
||||
skType, # a type
|
||||
skConst, # a constant
|
||||
skVar, # a variable
|
||||
@@ -293,7 +294,6 @@ type
|
||||
skField, # a field in a record or object
|
||||
skEnumField, # an identifier in an enum
|
||||
skForVar, # a for loop variable
|
||||
skModule, # module identifier
|
||||
skLabel, # a label (for block statement)
|
||||
skStub # symbol is a stub and not yet loaded from the ROD
|
||||
# file (it is loaded on demand, which may mean: never)
|
||||
|
||||
@@ -16,7 +16,7 @@ proc eatNewLine(p: var TParser, n: PNode) =
|
||||
if p.tok.xkind == pxLineComment:
|
||||
skipCom(p, n)
|
||||
if p.tok.xkind == pxNewLine: getTok(p)
|
||||
else:
|
||||
elif p.tok.xkind == pxNewLine:
|
||||
eat(p, pxNewLine)
|
||||
|
||||
proc skipLine(p: var TParser) =
|
||||
|
||||
@@ -9,6 +9,15 @@ extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef void (*callback_t) (int rc);
|
||||
|
||||
int aw_callback_set (AW_CALLBACK c, callback_t callback );
|
||||
int aw_instance_callback_set (AW_CALLBACK c, callback_t callback);
|
||||
|
||||
#define AW_BUILD 85 // AW 5.0
|
||||
// Limits
|
||||
#define AW_MAX_AVCHANGE_PER_SECOND 10
|
||||
|
||||
#private expatDll
|
||||
|
||||
#if !defined(expatDll)
|
||||
|
||||
@@ -477,7 +477,7 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||
rethrowFlag = getTempName()
|
||||
appf(p.s[cpsLocals], "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
|
||||
if optStackTrace in p.Options:
|
||||
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
|
||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
||||
app(p.s[cpsStmts], "try {" & tnl)
|
||||
add(p.nestedTryStmts, t)
|
||||
genStmts(p, t.sons[0])
|
||||
@@ -542,7 +542,7 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||
if optStackTrace in p.Options:
|
||||
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
|
||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
||||
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
||||
var length = sonsLen(t)
|
||||
add(p.nestedTryStmts, t)
|
||||
|
||||
23
rod/cgen.nim
23
rod/cgen.nim
@@ -386,10 +386,10 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
useHeader(p.module, s)
|
||||
if lfNoDecl in s.loc.flags: return
|
||||
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], "NIM_THREADVAR ")
|
||||
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
|
||||
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
|
||||
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
||||
if {optStackTrace, optEndb} * p.module.module.options ==
|
||||
{optStackTrace, optEndb}:
|
||||
@@ -550,19 +550,12 @@ proc retIsNotVoid(s: PSym): bool =
|
||||
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||
inc(p.labels, 5)
|
||||
result = ropeff("F.procname = $1;$n" & "F.prev = framePtr;$n" &
|
||||
"F.filename = $2;$n" & "F.line = 0;$n" & "framePtr = (TFrame*)&F;$n",
|
||||
"%LOC$3 = getelementptr %TF %F, %NI 1$n" &
|
||||
"%LOC$4 = getelementptr %TF %F, %NI 0$n" &
|
||||
"%LOC$5 = getelementptr %TF %F, %NI 3$n" &
|
||||
"%LOC$6 = getelementptr %TF %F, %NI 2$n" & "store i8* $1, i8** %LOC$3$n" &
|
||||
"store %TFrame* @framePtr, %TFrame** %LOC$4$n" &
|
||||
"store i8* $2, i8** %LOC$5$n" & "store %NI 0, %NI* %LOC$6$n" &
|
||||
"%LOC$7 = bitcast %TF* %F to %TFrame*$n" &
|
||||
"store %TFrame* %LOC$7, %TFrame** @framePtr$n", [procname, filename,
|
||||
toRope(p.labels), toRope(p.labels - 1), toRope(p.labels - 2),
|
||||
toRope(p.labels - 3), toRope(p.labels - 4)])
|
||||
result = ropecg(p.module,
|
||||
"F.procname = $1;$n" &
|
||||
"F.prev = #framePtr;$n" &
|
||||
"F.filename = $2;$n" &
|
||||
"F.line = 0;$n" &
|
||||
"framePtr = (TFrame*)&F;$n", [procname, filename])
|
||||
|
||||
proc deinitFrame(p: BProc): PRope =
|
||||
inc(p.labels, 3)
|
||||
@@ -693,10 +686,10 @@ proc genVarPrototype(m: BModule, sym: PSym) =
|
||||
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
|
||||
else:
|
||||
app(m.s[cfsVars], "extern ")
|
||||
if sfThreadVar in sym.flags: app(m.s[cfsVars], "NIM_THREADVAR ")
|
||||
app(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
|
||||
if sfRegister in sym.flags: app(m.s[cfsVars], " register")
|
||||
if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile")
|
||||
if sfThreadVar in sym.flags: app(m.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(m.s[cfsVars], " $1;$n", [sym.loc.r])
|
||||
|
||||
proc genConstPrototype(m: BModule, sym: PSym) =
|
||||
|
||||
@@ -32,7 +32,6 @@ type
|
||||
filename*: string # filename of the source file; without extension
|
||||
basedir*: string # base directory (where to put the documentation)
|
||||
modDesc*: PRope # module description
|
||||
deps*: PRope # dependencies
|
||||
id*: int # for generating IDs
|
||||
splitAfter*: int # split too long entries in the TOC
|
||||
tocPart*: seq[TTocEntry]
|
||||
@@ -765,9 +764,12 @@ proc getModuleFile(n: PNode): string =
|
||||
result = ""
|
||||
|
||||
proc traceDeps(d: PDoc, n: PNode) =
|
||||
if d.deps != nil: app(d.deps, ", ")
|
||||
app(d.deps, getModuleFile(n))
|
||||
|
||||
const k = skModule
|
||||
if d.section[k] != nil: app(d.section[k], ", ")
|
||||
dispA(d.section[k],
|
||||
"<a class=\"reference external\" href=\"$1.html\">$1</a>",
|
||||
"$1", [toRope(getModuleFile(n))])
|
||||
|
||||
proc generateDoc(d: PDoc, n: PNode) =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
@@ -802,8 +804,12 @@ proc generateDoc(d: PDoc, n: PNode) =
|
||||
else: nil
|
||||
|
||||
proc genSection(d: PDoc, kind: TSymKind) =
|
||||
const sectionNames: array[skModule..skTemplate, string] = [
|
||||
"Imports", "Types", "Consts", "Vars", "Procs", "Methods",
|
||||
"Iterators", "Converters", "Macros", "Templates"
|
||||
]
|
||||
if d.section[kind] == nil: return
|
||||
var title = toRope(copy($kind, 2) & 's')
|
||||
var title = toRope(sectionNames[kind])
|
||||
d.section[kind] = ropeFormatNamedVars(getConfigVar("doc.section"), [
|
||||
"sectionid", "sectionTitle", "sectionTitleID", "content"], [
|
||||
toRope(ord(kind)), title, toRope(ord(kind) + 50), d.section[kind]])
|
||||
@@ -833,14 +839,14 @@ proc genOutFile(d: PDoc): PRope =
|
||||
if d.hasToc: bodyname = "doc.body_toc"
|
||||
else: bodyname = "doc.body_no_toc"
|
||||
content = ropeFormatNamedVars(getConfigVar(bodyname), ["title",
|
||||
"tableofcontents", "moduledesc", "deps", "date", "time", "content"],
|
||||
[title, toc, d.modDesc, d.deps, toRope(getDateStr()),
|
||||
"tableofcontents", "moduledesc", "date", "time", "content"],
|
||||
[title, toc, d.modDesc, toRope(getDateStr()),
|
||||
toRope(getClockStr()), code])
|
||||
if optCompileOnly notin gGlobalOptions:
|
||||
code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
|
||||
"tableofcontents", "moduledesc", "deps", "date", "time",
|
||||
"tableofcontents", "moduledesc", "date", "time",
|
||||
"content", "author", "version"],
|
||||
[title, toc, d.modDesc, d.deps, toRope(getDateStr()),
|
||||
[title, toc, d.modDesc, toRope(getDateStr()),
|
||||
toRope(getClockStr()), content, d.meta[metaAuthor],
|
||||
d.meta[metaVersion]])
|
||||
else:
|
||||
|
||||
@@ -94,6 +94,7 @@ type
|
||||
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
||||
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue,
|
||||
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
|
||||
errInvalidOrderInArrayConstructor,
|
||||
errInvalidOrderInEnumX, errEnumXHasWholes, errExceptExpected, errInvalidTry,
|
||||
errOptionExpected, errXisNoLabel, errNotAllCasesCovered,
|
||||
errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable,
|
||||
@@ -214,6 +215,7 @@ const
|
||||
"value returned by statement has to be discarded",
|
||||
"statement returns no value that can be discarded",
|
||||
"conversion from $1 to $2 is invalid", "cannot bind parameter \'$1\' twice",
|
||||
"invalid order in array constructor",
|
||||
"invalid order in enum \'$1\'", "enum \'$1\' has wholes",
|
||||
"\'except\' or \'finally\' expected",
|
||||
"after catch all \'except\' or \'finally\' no section may follow",
|
||||
|
||||
@@ -260,11 +260,29 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 0:
|
||||
addSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
else:
|
||||
addSon(result, semExprWithType(c, n.sons[0]))
|
||||
var x = n.sons[0]
|
||||
var lastIndex: biggestInt = 0
|
||||
var indexType = getSysType(tyInt)
|
||||
if x.kind == nkExprColonExpr:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
lastIndex = getOrdValue(idx)
|
||||
indexType = idx.typ
|
||||
x = x.sons[1]
|
||||
|
||||
addSon(result, semExprWithType(c, x))
|
||||
var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i])
|
||||
x = n.sons[i]
|
||||
if x.kind == nkExprColonExpr:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
idx = fitNode(c, indexType, idx)
|
||||
if lastIndex+1 != getOrdValue(idx):
|
||||
liMessage(x.info, errInvalidOrderInArrayConstructor)
|
||||
x = x.sons[1]
|
||||
|
||||
n.sons[i] = semExprWithType(c, x)
|
||||
addSon(result, fitNode(c, typ, n.sons[i]))
|
||||
inc(lastIndex)
|
||||
addSon(result.typ, typ)
|
||||
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ tack.nim;125
|
||||
tambsym2.nim;7
|
||||
tambsys.nim;
|
||||
tarray.nim;10012
|
||||
tarraycons.nim;6
|
||||
tarray2.nim;[16, 25, 36]
|
||||
tarray3.nim;3
|
||||
tassert.nim;assertion failure!this shall be always written
|
||||
|
||||
|
17
tests/accept/run/tarraycons.nim
Normal file
17
tests/accept/run/tarraycons.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
type
|
||||
TEnum = enum
|
||||
eA, eB, eC, eD, eE, eF
|
||||
|
||||
const
|
||||
myMapping: array[TEnum, array[0..1, int]] = [
|
||||
eA: [1, 2],
|
||||
eB: [3, 4],
|
||||
[5, 6],
|
||||
eD: [0: 8, 1: 9],
|
||||
eE: [0: 8, 9],
|
||||
eF: [2, 1: 9]
|
||||
]
|
||||
|
||||
echo myMapping[eC][1]
|
||||
|
||||
21
tests/gc/tthreads.nim
Normal file
21
tests/gc/tthreads.nim
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import threads
|
||||
|
||||
var
|
||||
thr: array [0..4, TThread]
|
||||
L: TLock
|
||||
|
||||
proc threadFunc(c: pointer) {.procvar.} =
|
||||
for i in 0..9:
|
||||
Aquire(L)
|
||||
echo i
|
||||
Release(L)
|
||||
|
||||
InitLock(L)
|
||||
|
||||
for i in 0..high(thr):
|
||||
createThread(thr[i], threadFunc)
|
||||
for i in 0..high(thr):
|
||||
joinThread(thr[i])
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ tadrdisc.nim;15;for a 'var' type a variable needs to be passed
|
||||
tambsym.nim;6;ambiguous identifier
|
||||
tambsym2.nim;4;undeclared identifier: 'CreateRGBSurface'
|
||||
tambsym3.nim;6;ambiguous identifier
|
||||
tarraycons.nim;9;invalid order in array constructor
|
||||
tatomic.nim;2;identifier expected, but found 'atomic'
|
||||
tbind2.nim;7;ambiguous call
|
||||
tbind4.nim;4;undeclared identifier: 'lastId'
|
||||
|
||||
|
17
tests/reject/tarraycons.nim
Normal file
17
tests/reject/tarraycons.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
type
|
||||
TEnum = enum
|
||||
eA, eB, eC, eD, eE, eF
|
||||
|
||||
const
|
||||
myMapping: array[TEnum, array[0..1, int]] = [
|
||||
eA: [1, 2],
|
||||
eC: [3, 4],
|
||||
eB: [5, 6],
|
||||
eD: [0: 8, 1: 9],
|
||||
eE: [0: 8, 9],
|
||||
eF: [2, 1: 9]
|
||||
]
|
||||
|
||||
echo myMapping[eC][1]
|
||||
|
||||
12
todo.txt
12
todo.txt
@@ -1,11 +1,16 @@
|
||||
- built-in serialization
|
||||
- thread support: threadvar on Windows seems broken;
|
||||
add --deadlock_prevention:on|off switch
|
||||
|
||||
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
|
||||
|
||||
- we need a way to disable tests
|
||||
- deprecate ^ and make it available as operator
|
||||
- test branch coverage
|
||||
- checked exceptions
|
||||
- explicit indices for array literals
|
||||
- built-in serialization
|
||||
- do not ambiguity error for methods if amibiguity only affects the same
|
||||
- do not ambiguity error for methods if ambiguity only affects the same
|
||||
dispatcher anyway
|
||||
- slicing
|
||||
|
||||
|
||||
High priority (version 0.9.0)
|
||||
@@ -23,6 +28,7 @@ Bugs
|
||||
- proc (x: int) is passable to proc (x: var int) !?
|
||||
- detected by pegs module 64bit: p(result, result) should use a temporary!
|
||||
- the parser allows empty object case branches
|
||||
- Exception matching needs to take subclasses into account
|
||||
|
||||
|
||||
To implement
|
||||
|
||||
@@ -47,6 +47,9 @@ Additions
|
||||
- A field in an ``enum`` may be given an explicit string representation.
|
||||
This yields more maintainable code than using a constant
|
||||
``array[TMyEnum, string]`` mapping.
|
||||
- Indices in array literals may be explicitly given, enhancing readability:
|
||||
``[enumValueA: "a", enumValueB: "b"]``.
|
||||
- Added basic thread support via the ``threads`` core module.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,13 +24,14 @@ file: ticker
|
||||
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview"
|
||||
doc: "tools;c2nim;niminst"
|
||||
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
|
||||
srcdoc: "core/macros;core/threads;core/marshal"
|
||||
srcdoc: "impure/graphics;pure/sockets"
|
||||
srcdoc: "system.nim;pure/os;pure/strutils;pure/math"
|
||||
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
|
||||
srcdoc: "pure/parseopt;pure/hashes;pure/strtabs;pure/lexbase"
|
||||
srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"
|
||||
srcdoc: "pure/streams;pure/terminal;pure/cgi;impure/web;pure/unicode"
|
||||
srcdoc: "impure/zipfiles;pure/xmlgen;pure/macros;pure/parseutils;pure/browsers"
|
||||
srcdoc: "impure/zipfiles;pure/xmlgen;pure/parseutils;pure/browsers"
|
||||
srcdoc: "impure/db_postgres;impure/db_mysql;impure/db_sqlite"
|
||||
srcdoc: "pure/httpserver;pure/httpclient;pure/stmp;impure/ssl"
|
||||
srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
|
||||
|
||||
Reference in New Issue
Block a user