added tools and web dirs

This commit is contained in:
Andreas Rumpf 2009-09-15 23:22:22 +02:00
commit 66a7e3d37c
489 changed files with 4593 additions and 9878 deletions

0
.bzrignore Normal file → Executable file
View file

0
Nimrod.geany Normal file → Executable file
View file

4
boot.nim Normal file → Executable file
View file

@ -27,9 +27,9 @@ proc exec(cmd: string) =
proc writePlatdefC = proc writePlatdefC =
var f: TFile var f: TFile
if openFile(f, "build/platdef.c", fmWrite): if open(f, "build/platdef.c", fmWrite):
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU]) write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
closeFile(f) close(f)
else: else:
quit("Cannot write 'build/platdef.c'\n") quit("Cannot write 'build/platdef.c'\n")

0
cogapp.py Normal file → Executable file
View file

0
config/my_nimrod.cfg Normal file → Executable file
View file

0
config/nimdoc.cfg Normal file → Executable file
View file

8
config/nimrod.cfg Normal file → Executable file
View file

@ -24,21 +24,23 @@ path="$lib/windows"
path="$lib/posix" path="$lib/posix"
path="$lib/ecmas" path="$lib/ecmas"
@if release: @if release or quick:
obj_checks:off obj_checks:off
field_checks:off field_checks:off
range_checks:off range_checks:off
bound_checks:off bound_checks:off
overflow_checks:off overflow_checks:off
assertions:off assertions:off
stacktrace:off stacktrace:off
debugger:off debugger:off
line_dir:off line_dir:off
opt:speed
dead_code_elim:on dead_code_elim:on
@end @end
@if release:
opt:speed
@end
# additional options always passed to the compiler: # additional options always passed to the compiler:
--verbosity: "1" --verbosity: "1"

0
configure vendored Normal file → Executable file
View file

0
copying.txt Normal file → Executable file
View file

1
data/advopt.txt Normal file → Executable file
View file

@ -14,6 +14,7 @@ Advanced options:
--lib:PATH set the system library path --lib:PATH set the system library path
-c, --compile_only compile only; do not assemble or link -c, --compile_only compile only; do not assemble or link
--no_linking compile but do not link --no_linking compile but do not link
--no_main do not generate a main procedure
--gen_script generate a compile script (in the 'nimcache' --gen_script generate a compile script (in the 'nimcache'
subdirectory named 'compile_$project$scriptext') subdirectory named 'compile_$project$scriptext')
--os:SYMBOL set the target operating system (cross-compilation) --os:SYMBOL set the target operating system (cross-compilation)

35
data/ast.yml Normal file → Executable file
View file

@ -57,11 +57,12 @@
'TypeKind': [ # order is important! 'TypeKind': [ # order is important!
# Don't forget to change hti.nim if you make a change here # Don't forget to change hti.nim if you make a change here
'tyNone', 'tyBool', 'tyChar', 'tyNone', 'tyBool', 'tyChar',
'tyEmpty', 'tyArrayConstr', 'tyNil', 'tyEmpty', 'tyArrayConstr', 'tyNil', 'tyExpr', 'tyStmt', 'tyTypeDesc',
'tyGeneric', 'tyGenericInvokation', # ``T[a, b]`` for types to invoke
'tyGenericInst', # instantiated generic type 'tyGenericBody', # ``T[a, b, body]`` last parameter is the body
'tyGenericParam', 'tyGenericInst', # ``T[a, b, realInstance]`` instantiated generic type
'tyAbstract', # abstract type 'tyGenericParam', # ``a`` in the example
'tyDistinct',
'tyEnum', 'tyEnum',
'tyOrdinal', 'tyOrdinal',
'tyArray', 'tyArray',
@ -123,8 +124,9 @@
# for transforming ``s.len`` to ``len(s)`` # for transforming ``s.len`` to ``len(s)``
'nkCommand', # a call like ``p 2, 4`` without parenthesis 'nkCommand', # a call like ``p 2, 4`` without parenthesis
'nkCall', # a call like p(x, y) or an operation like +(a, b) 'nkCall', # a call like p(x, y) or an operation like +(a, b)
'nkGenericCall', # a call with given type parameters 'nkCallStrLit', # a call with a string literal
'nkExplicitTypeListCall', # a call with given explicit typelist # x"abc" has two sons: nkIdent, nkRStrLit
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
'nkExprEqExpr', # a named parameter with equals: ''expr = expr'' 'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
'nkExprColonExpr', # a named parameter with colon: ''expr: expr'' 'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
'nkIdentDefs', # a definition like `a, b: typeDesc = expr` 'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
@ -174,7 +176,6 @@
'nkAsgn', # a = b 'nkAsgn', # a = b
'nkFastAsgn', # internal node for a fast ``a = b`` (no string copy) 'nkFastAsgn', # internal node for a fast ``a = b`` (no string copy)
'nkDefaultTypeParam', # `ident = typeDesc` in generic parameters
'nkGenericParams', # generic parameters 'nkGenericParams', # generic parameters
'nkFormalParams', # formal parameters 'nkFormalParams', # formal parameters
'nkOfInherit', # inherited from symbol 'nkOfInherit', # inherited from symbol
@ -215,7 +216,6 @@
'nkStmtList', # a list of statements 'nkStmtList', # a list of statements
'nkImportStmt', # an import statement 'nkImportStmt', # an import statement
'nkFromStmt', # a from * import statement 'nkFromStmt', # a from * import statement
'nkImportAs', # an `import xyx as abc` section
'nkIncludeStmt', # an include statement 'nkIncludeStmt', # an include statement
'nkCommentStmt', # a comment statement 'nkCommentStmt', # a comment statement
'nkStmtListExpr', # a statement list followed by an expr; this is used 'nkStmtListExpr', # a statement list followed by an expr; this is used
@ -225,20 +225,18 @@
# temporary scope # temporary scope
'nkStmtListType', # a statement list ending in a type; for macros 'nkStmtListType', # a statement list ending in a type; for macros
'nkBlockType', # a statement block ending in a type; for macros 'nkBlockType', # a statement block ending in a type; for macros
'nkVm', # indicates a virtual instruction; integer field is
# used for the concrete opcode
# types as syntactic trees: # types as syntactic trees:
'nkTypeOfExpr', 'nkTypeOfExpr',
'nkObjectTy', 'nkObjectTy',
'nkTupleTy', 'nkTupleTy',
'nkRecList', # list of record/object parts 'nkRecList', # list of object parts
'nkRecCase', # case section of record/object 'nkRecCase', # case section of object
'nkRecWhen', # when section of record/object 'nkRecWhen', # when section of object
'nkRefTy', 'nkRefTy',
'nkPtrTy', 'nkPtrTy',
'nkVarTy', 'nkVarTy',
'nkAbstractTy', # abstract type 'nkDistinctTy', # distinct type
'nkProcTy', 'nkProcTy',
'nkEnumTy', 'nkEnumTy',
'nkEnumFieldDef', # `ident = expr` in an enumeration 'nkEnumFieldDef', # `ident = expr` in an enumeration
@ -248,12 +246,13 @@
'SymKind': [ 'SymKind': [
# the different symbols (start with the prefix sk); # the different symbols (start with the prefix sk);
# order is important for the documentation generator! # order is important for the documentation generator!
'skUnknownSym', # unknown symbol: used for parsing assembler blocks 'skUnknown', # unknown symbol: used for parsing assembler blocks
# and first phase symbol lookup in generics
'skConditional', # symbol for the preprocessor (may become obsolete) 'skConditional', # symbol for the preprocessor (may become obsolete)
'skDynLib', # symbol represents a dynamic library; this is used 'skDynLib', # symbol represents a dynamic library; this is used
# internally; it does not exist in Nimrod code # internally; it does not exist in Nimrod code
'skParam', # a parameter 'skParam', # a parameter
'skTypeParam', # a type parameter; example: proc x[T]() <- `T` 'skGenericParam', # a generic parameter; eq in ``proc x[eq=`==`]()``
'skTemp', # a temporary variable (introduced by compiler) 'skTemp', # a temporary variable (introduced by compiler)
'skType', # a type 'skType', # a type
'skConst', # a constant 'skConst', # a constant

1
data/basicopt.txt Normal file → Executable file
View file

@ -5,6 +5,7 @@ Command::
compile_to_c, cc compile project with C code generator compile_to_c, cc compile project with C code generator
doc generate the documentation for inputfile doc generate the documentation for inputfile
rst2html converts a reStructuredText file to HTML rst2html converts a reStructuredText file to HTML
rst2tex converts a reStructuredText file to TeX
Arguments: Arguments:
arguments are passed to the program being run (if --run option is selected) arguments are passed to the program being run (if --run option is selected)
Options: Options:

0
data/ccomps.txt Normal file → Executable file
View file

4
data/keywords.txt Normal file → Executable file
View file

@ -1,7 +1,7 @@
abstract addr and as asm addr and as asm
bind block break bind block break
case cast const continue converter case cast const continue converter
discard div discard distinct div
elif else end enum except elif else end enum except
finally for from generic finally for from generic
if implies import in include is isnot iterator if implies import in include is isnot iterator

5
data/magic.yml Normal file → Executable file
View file

@ -3,6 +3,7 @@
[ [
'None', 'None',
'Defined', 'Defined',
'DefinedInScope',
'Low', 'Low',
'High', 'High',
'SizeOf', 'SizeOf',
@ -17,7 +18,6 @@
'New', 'New',
'NewFinalize', 'NewFinalize',
'NewSeq', 'NewSeq',
'RegisterFinalizer',
'LengthOpenArray', 'LengthOpenArray',
'LengthStr', 'LengthStr',
'LengthArray', 'LengthArray',
@ -203,6 +203,9 @@
'EmptySet', 'EmptySet',
'IntSetBaseType', 'IntSetBaseType',
'Nil', 'Nil',
'Expr',
'Stmt',
'TypeDesc',
# magic constants: # magic constants:
'IsMainModule', 'IsMainModule',

22
data/messages.yml Normal file → Executable file
View file

@ -31,15 +31,14 @@
{'errOperatorExpected': "operator expected, but found '$1'"}, {'errOperatorExpected': "operator expected, but found '$1'"},
{'errTokenExpected': "'$1' expected"}, {'errTokenExpected': "'$1' expected"},
{'errStringAfterIncludeExpected': "string after 'include' expected"}, {'errStringAfterIncludeExpected': "string after 'include' expected"},
{'errRecursiveInclude': "recursive include file: '$1'"}, {'errRecursiveDependencyX': "recursive dependency: '$1'"},
{'errOnOrOffExpected': "'on' or 'off' expected"}, {'errOnOrOffExpected': "'on' or 'off' expected"},
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"}, {'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
{'errInvalidPragma': 'invalid pragma'}, {'errInvalidPragma': 'invalid pragma'},
{'errUnknownPragma': "unknown pragma: '$1'"}, {'errUnknownPragma': "unknown pragma: '$1'"},
{'errUnknownDirective': "unknown directive: '$1'"}, {'errInvalidDirectiveX': "invalid directive: '$1'"},
{'errInvalidDirective': 'invalid directive'},
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"}, {'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
{'errEmptyAsm': 'empty asm statement makes no sense'}, {'errEmptyAsm': 'empty asm statement'},
{'errInvalidIndentation': 'invalid indentation'}, {'errInvalidIndentation': 'invalid indentation'},
{'errExceptionExpected': 'exception expected'}, {'errExceptionExpected': 'exception expected'},
{'errExceptionAlreadyHandled': 'exception already handled'}, {'errExceptionAlreadyHandled': 'exception already handled'},
@ -93,9 +92,6 @@
{'errCannotEvalXBecauseIncompletelyDefined': {'errCannotEvalXBecauseIncompletelyDefined':
"cannot evalutate '$1' because type is not defined completely"}, "cannot evalutate '$1' because type is not defined completely"},
{'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"}, {'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"},
{'errStaticAssertFailed': "'staticAssert' failed: condition is false"},
{'errStaticAssertCannotBeEval':
"argument to 'staticAssert' cannot be evaluated at compile time"},
{'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"}, {'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"},
{'errUndeclaredFieldX': "undeclared field: '$1'"}, {'errUndeclaredFieldX': "undeclared field: '$1'"},
{'errNilAccess': 'attempt to access a nil address'}, {'errNilAccess': 'attempt to access a nil address'},
@ -155,7 +151,7 @@
{'errButExpected': 'but expected one of: '}, {'errButExpected': 'but expected one of: '},
{'errButExpectedX': "but expected '$1'"}, {'errButExpectedX': "but expected '$1'"},
{'errAmbiguousCallXYZ': 'ambiguous call; both $1 and $2 match for: $3'}, {'errAmbiguousCallXYZ': 'ambiguous call; both $1 and $2 match for: $3'},
{'errWrongNumberOfTypeParams': 'wrong number of type parameters'}, {'errWrongNumberOfArguments': 'wrong number of arguments'},
{'errInlineProcHasNoAddress': 'an inline proc has no address'}, {'errInlineProcHasNoAddress': 'an inline proc has no address'},
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'}, {'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
{'errPragmaOnlyInHeaderOfProc': {'errPragmaOnlyInHeaderOfProc':
@ -198,16 +194,14 @@
{'errNamedExprNotAllowed': 'named expression not allowed here'}, {'errNamedExprNotAllowed': 'named expression not allowed here'},
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"}, {'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'}, {'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
{'errInvalidVisibilityX': "invalid invisibility: '$1'"}, {'errInvalidVisibilityX': "invalid visibility: '$1'"},
{'errInitHereNotAllowed': 'initialization not allowed here'}, {'errInitHereNotAllowed': 'initialization not allowed here'},
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"}, {'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
{'errIteratorNotAllowed': {'errIteratorNotAllowed':
"iterators can only be defined at the module's top level"}, "iterators can only be defined at the module's top level"},
{'errIteratorNeedsImplementation': 'iterator needs an implementation'}, {'errXNeedsReturnType': '$1 needs a return type'},
{'errIteratorNeedsReturnType': 'iterator needs a return type'},
{'errInvalidCommandX': "invalid command: '$1'"}, {'errInvalidCommandX': "invalid command: '$1'"},
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"}, {'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
{'errTypeXNeedsImplementation': "type '$1' needs an implementation"},
{'errTemplateInstantiationTooNested': 'template instantiation too nested'}, {'errTemplateInstantiationTooNested': 'template instantiation too nested'},
{'errInstantiationFrom': 'instantiation from here'}, {'errInstantiationFrom': 'instantiation from here'},
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'}, {'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
@ -230,12 +224,12 @@
{'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"}, {'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"},
{'errAssertionFailed': "assertion failed"}, {'errAssertionFailed': "assertion failed"},
{'errCannotGenerateCodeForX': "cannot generate code for '$1'"}, {'errCannotGenerateCodeForX': "cannot generate code for '$1'"},
{'errXNeedsReturnType': "converter needs return type"}, {'errXRequiresOneArgument': "$1 requires one parameter"},
{'errXRequiresOneArgument': "converter requires one parameter"},
{'errUnhandledExceptionX': "unhandled exception: $1"}, {'errUnhandledExceptionX': "unhandled exception: $1"},
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"}, {'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
{'errXisNoMacroOrTemplate': "'$1' is no macro or template"}, {'errXisNoMacroOrTemplate': "'$1' is no macro or template"},
{'errXhasSideEffects': "'$1' can have side effects"}, {'errXhasSideEffects': "'$1' can have side effects"},
{'errIteratorExpected': "iterator within for loop context expected"},
# user error message: # user error message:
{'errUser': '$1'}, {'errUser': '$1'},

0
data/pas_keyw.yml Normal file → Executable file
View file

0
data/readme.txt Normal file → Executable file
View file

0
diff/empty.txt Normal file → Executable file
View file

8
doc/abstypes.txt Normal file → Executable file
View file

@ -91,7 +91,7 @@ we define our own ``+`` for dollars:
result = TDollar(int(x) + int(y)) result = TDollar(int(x) + int(y))
It does not make sense to multiply a dollar with a dollar, but with a It does not make sense to multiply a dollar with a dollar, but with a
unit-less number; and the same holds for division: number without unit; and the same holds for division:
.. code-block:: .. code-block::
proc `*` (x: TDollar, y: int): TDollar = proc `*` (x: TDollar, y: int): TDollar =
@ -121,7 +121,7 @@ But it seems we still have to repeat all this boilerplate code for
the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism: the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
.. code-block:: nimrod .. code-block:: nimrod
template Additive(typ: typeExpr): stmt = template Additive(typ: typeDesc): stmt =
proc `+` *(x, y: typ): typ {.borrow.} proc `+` *(x, y: typ): typ {.borrow.}
proc `-` *(x, y: typ): typ {.borrow.} proc `-` *(x, y: typ): typ {.borrow.}
@ -129,13 +129,13 @@ the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
proc `+` *(x: typ): typ {.borrow.} proc `+` *(x: typ): typ {.borrow.}
proc `-` *(x: typ): typ {.borrow.} proc `-` *(x: typ): typ {.borrow.}
template Multiplicative(typ, base: typeExpr): stmt = template Multiplicative(typ, base: typeDesc): stmt =
proc `*` *(x: typ, y: base): typ {.borrow.} proc `*` *(x: typ, y: base): typ {.borrow.}
proc `*` *(x: base, y: typ): typ {.borrow.} proc `*` *(x: base, y: typ): typ {.borrow.}
proc `div` *(x: typ, y: base): typ {.borrow.} proc `div` *(x: typ, y: base): typ {.borrow.}
proc `mod` *(x: typ, y: base): typ {.borrow.} proc `mod` *(x: typ, y: base): typ {.borrow.}
template Comparable(typ: typeExpr): stmt = template Comparable(typ: typeDesc): stmt =
proc `<` * (x, y: typ): bool {.borrow.} proc `<` * (x, y: typ): bool {.borrow.}
proc `<=` * (x, y: typ): bool {.borrow.} proc `<=` * (x, y: typ): bool {.borrow.}
proc `==` * (x, y: typ): bool {.borrow.} proc `==` * (x, y: typ): bool {.borrow.}

0
doc/astspec.txt Normal file → Executable file
View file

0
doc/docs.txt Normal file → Executable file
View file

0
doc/endb.txt Normal file → Executable file
View file

0
doc/filelist.txt Normal file → Executable file
View file

4
doc/grammar.txt Normal file → Executable file
View file

@ -135,10 +135,10 @@ fromStmt ::= 'from' filename 'import' symbol (comma symbol)*
pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}') pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}')
param ::= symbol (comma symbol)* ':' typeDesc param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr)
paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc] paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc]
genericParam ::= symbol [':' typeDesc] genericParam ::= symbol [':' typeDesc] ['=' expr]
genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']' genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']'
procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma] procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma]

129
doc/intern.txt Normal file → Executable file
View file

@ -17,7 +17,7 @@ The Nimrod project's directory structure is:
============ ============================================== ============ ==============================================
Path Purpose Path Purpose
============ ============================================== ============ ==============================================
``bin`` binary files go into here ``bin`` generated binary files
``build`` generated C code for the installation ``build`` generated C code for the installation
``nim`` Pascal sources of the Nimrod compiler; this ``nim`` Pascal sources of the Nimrod compiler; this
should be modified, not the Nimrod version in should be modified, not the Nimrod version in
@ -26,16 +26,16 @@ Path Purpose
automatically generated from the Pascal automatically generated from the Pascal
version version
``data`` data files that are used for generating source ``data`` data files that are used for generating source
code go into here code
``doc`` the documentation lives here; it is a bunch of ``doc`` the documentation lives here; it is a bunch of
reStructuredText files reStructuredText files
``dist`` additional packages for the distribution ``dist`` additional packages for the distribution
``config`` configuration files for Nimrod go into here ``config`` configuration files for Nimrod
``lib`` the Nimrod library lives here; ``rod`` depends ``lib`` the Nimrod library lives here; ``rod`` depends
on it! on it!
``web`` website of Nimrod; generated by ``koch.py`` ``web`` website of Nimrod; generated by ``koch.py``
from the ``*.txt`` and ``*.tmpl`` files from the ``*.txt`` and ``*.tmpl`` files
``obj`` generated ``*.obj`` files go into here ``obj`` generated ``*.obj`` files
============ ============================================== ============ ==============================================
@ -72,6 +72,18 @@ the same::
./boot [-d:release] ./boot [-d:release]
Coding Guidelines
=================
* Use CamelCase, not underscored_identifiers.
* Indent with two spaces.
* Max line length is 80 characters.
* Provide spaces around binary operators if that enhances readability.
* Use a space after a colon, but not before it.
* Start types with a capital ``T``, unless they are pointers which start with
``P``.
Pascal annotations Pascal annotations
================== ==================
There are some annotations that the Pascal sources use so that they can There are some annotations that the Pascal sources use so that they can
@ -153,9 +165,9 @@ Complex assignments
for any type that needs one. However, this would make the code bigger and for any type that needs one. However, this would make the code bigger and
the RTTI is likely already there for the GC. the RTTI is likely already there for the GC.
We already knew the type information as a graph in the compiler. We already know the type information as a graph in the compiler.
Thus we need to serialize this graph as RTTI for C code generation. Thus we need to serialize this graph as RTTI for C code generation.
Look at the file ``lib/hti.nim`` for more information. Look at the file ``lib/system/hti.nim`` for more information.
The Garbage Collector The Garbage Collector
@ -243,11 +255,8 @@ Consider this example:
# r is on the stack # r is on the stack
setRef(r.left) # here we should update the refcounts! setRef(r.left) # here we should update the refcounts!
Though it would be possible to produce code updating the refcounts (if We have to decide at runtime whether the reference is on the stack or not.
necessary) before and after the call to ``setRef``, it is a complex task to The generated code looks roughly like this:
do so in the code generator. So we don't and instead decide at runtime
whether the reference is on the stack or not. The generated code looks
roughly like this:
.. code-block:: C .. code-block:: C
void setref(TNode** ref) { void setref(TNode** ref) {
@ -260,13 +269,7 @@ roughly like this:
Note that for systems with a continous stack (which most systems have) Note that for systems with a continous stack (which most systems have)
the check whether the ref is on the stack is very cheap (only two the check whether the ref is on the stack is very cheap (only two
comparisons). Another advantage of this scheme is that the code produced is comparisons).
smaller.
The algorithm in pseudo-code
----------------------------
To be written.
The compiler's architecture The compiler's architecture
@ -332,3 +335,93 @@ underlying C compiler already does all the hard work for us. The problem is the
common runtime library, especially the memory manager. Note that Borland's common runtime library, especially the memory manager. Note that Borland's
Delphi had exactly the same problem. The workaround is to not link the GC with Delphi had exactly the same problem. The workaround is to not link the GC with
the Dll and provide an extra runtime dll that needs to be initialized. the Dll and provide an extra runtime dll that needs to be initialized.
Code generation for closures
============================
Example code:
.. code-block:: nimrod
proc add(x: int): proc (y: int): int {.closure.} =
return lambda (y: int): int =
return x + y
var add2 = add(2)
echo add2(5) #OUT 7
This should produce roughly this code:
.. code-block:: nimrod
type
PClosure = ref object
fn: proc (x: int, c: PClosure): int
x: int # data
proc wasLambda(y: int, c: PClosure): int =
return y + c.x
proc add(x: int): PClosure =
var c: PClosure
new(c)
c.x = x
c.fn = wasLambda
var add2 = add(2)
echo add2.fn(5, add2)
Beware of nesting:
.. code-block:: nimrod
proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} =
return lamba (y: int): proc (z: int): int {.closure.} =
return lambda (z: int): int =
return x + y + z
var add24 = add(2)(4)
echo add24(5) #OUT 11
This should produce roughly this code:
.. code-block:: nimrod
type
PClosure1 = ref object
fn: proc (x: int, c: PClosure1): int
x: int # data
PClosure2 = ref object
fn: proc (x: int, c: PClosure2): int
y: int
c1: PClosure1
proc innerLambda(z: int, c2: PClosure2): int =
return c2.c1.x + c2.y + z
proc outerLambda1(y: int, c1: PClosure1): PClosure2 =
new(result)
result.c1 = c1
result.y = y
result.fn = innerLambda
proc add(x: int): PClosure1 =
new(result)
result.x = x
result.fn = outerLambda
var tmp = add(2)
var tmp2 = tmp.fn(4, tmp)
var add24 = tmp2.fn(4, tmp2)
echo add24(5)
Accumulator
-----------
.. code-block:: nimrod
proc GetAccumulator(start: int): proc (): int {.closure} =
var i = start
return lambda: int =
inc i
return i

2
doc/lib.txt Normal file → Executable file
View file

@ -134,7 +134,7 @@ Impure libraries
Wrappers Wrappers
======== ========
Note that the generated HTML for some of these wrappers is so huge, that it is The generated HTML for some of these wrappers is so huge, that it is
not contained in the distribution. You can then find them on the website. not contained in the distribution. You can then find them on the website.
* `posix <posix.html>`_ * `posix <posix.html>`_

363
doc/manual.txt Normal file → Executable file
View file

@ -8,6 +8,10 @@ Nimrod Manual
.. contents:: .. contents::
"Complexity" seems to be a lot like "energy": you can transfer it from the end
user to one/some of the other players, but the total amount seems to remain
pretty much constant for a given task. -- Ran
About this document About this document
=================== ===================
@ -171,10 +175,10 @@ preferred. Another advantage is that it frees the programmer from remembering
the exact spelling of an identifier. the exact spelling of an identifier.
Literal strings String literals
--------------- ---------------
`Literal strings`:idx: can be delimited by matching double quotes, and can `String literals`:idx: can be delimited by matching double quotes, and can
contain the following `escape sequences`:idx:\ : contain the following `escape sequences`:idx:\ :
================== =================================================== ================== ===================================================
@ -202,12 +206,21 @@ contain the following `escape sequences`:idx:\ :
Strings in Nimrod may contain any 8-bit value, except embedded zeros. Strings in Nimrod may contain any 8-bit value, except embedded zeros.
Literal strings can also be delimited by three double squotes
Triple quoted string literals
-----------------------------
String literals can also be delimited by three double quotes
``"""`` ... ``"""``. ``"""`` ... ``"""``.
Literals in this form may run for several lines, may contain ``"`` and do not Literals in this form may run for several lines, may contain ``"`` and do not
interpret any escape sequences. interpret any escape sequences.
For convenience, when the opening ``"""`` is immediately followed by a newline, For convenience, when the opening ``"""`` is immediately followed by a newline,
the newline is not included in the string. the newline is not included in the string.
Raw string literals
-------------------
There are also `raw string literals` that are preceded with the letter ``r`` There are also `raw string literals` that are preceded with the letter ``r``
(or ``R``) and are delimited by matching double quotes (just like ordinary (or ``R``) and are delimited by matching double quotes (just like ordinary
string literals) and do not interpret the escape sequences. This is especially string literals) and do not interpret the escape sequences. This is especially
@ -218,7 +231,22 @@ convenient for regular expressions or Windows paths:
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
Literal characters Generalized raw string literals
-------------------------------
The construct ``identifier"string literal"`` (without whitespace between the
identifier and the opening quotation mark) is a
`generalized raw string literal`:idx:. It is a shortcut for the construct
``identifier(r"string literal")``, so it denotes a procedure call with a
raw string literal as its only argument. Generalized raw string literals
are especially convenient for embedding mini languages directly into Nimrod
(for example regular expressions).
The construct ``identifier"""string literal"""`` exists too. It is a shortcut
for ``identifier("""string literal""")``.
Character literals
------------------ ------------------
Character literals are enclosed in single quotes ``''`` and can contain the Character literals are enclosed in single quotes ``''`` and can contain the
@ -501,7 +529,7 @@ designed for this.
Another reason is that Nimrod can support ``array[char, int]`` or Another reason is that Nimrod can support ``array[char, int]`` or
``set[char]`` efficiently as many algorithms rely on this feature. The ``set[char]`` efficiently as many algorithms rely on this feature. The
`TRune` type is used for Unicode characters, it can represent any Unicode `TRune` type is used for Unicode characters, it can represent any Unicode
character. ``TRune`` is declared the ``unicode`` module. character. ``TRune`` is declared in the ``unicode`` module.
@ -548,7 +576,7 @@ Subrange types
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
A `subrange`:idx: type is a range of values from an ordinal type (the base A `subrange`:idx: type is a range of values from an ordinal type (the base
type). To define a subrange type, one must specify it's limiting values: the type). To define a subrange type, one must specify it's limiting values: the
highest and lowest value of the type: lowest and highest value of the type:
.. code-block:: nimrod .. code-block:: nimrod
type type
@ -764,7 +792,7 @@ basetype can only be an ordinal type. The reason is that sets are implemented
as high performance bit vectors. as high performance bit vectors.
Sets can be constructed via the set constructor: ``{}`` is the empty set. The Sets can be constructed via the set constructor: ``{}`` is the empty set. The
empty set is type combatible with any special set type. The constructor empty set is type compatible with any special set type. The constructor
can also be used to include elements (and ranges of elements) in the set: can also be used to include elements (and ranges of elements) in the set:
.. code-block:: nimrod .. code-block:: nimrod
@ -903,9 +931,8 @@ each other:
`closure`:idx: `closure`:idx:
indicates that the procedure expects a context, a closure that needs indicates that the procedure expects a context, a closure that needs
to be passed to the procedure. The implementation is the to be passed to the procedure. The calling convention ``nimcall`` is
same as ``cdecl``, but with a hidden pointer parameter (the compatible to ``closure``.
*closure*). The hidden parameter is always the last one.
`syscall`:idx: `syscall`:idx:
The syscall convention is the same as ``__syscall`` in C. It is used for The syscall convention is the same as ``__syscall`` in C. It is used for
@ -915,11 +942,108 @@ each other:
The generated C code will not have any explicit calling convention and thus The generated C code will not have any explicit calling convention and thus
use the C compiler's default calling convention. This is needed because use the C compiler's default calling convention. This is needed because
Nimrod's default calling convention for procedures is ``fastcall`` to Nimrod's default calling convention for procedures is ``fastcall`` to
improve speed. This is unlikely to be needed by the user. improve speed.
Most calling conventions exist only for the Windows 32-bit platform. Most calling conventions exist only for the Windows 32-bit platform.
Distinct type
~~~~~~~~~~~~~
A distinct type is new type derived from a `base type`:idx: that is
incompatible with its base type. In particular, it is an essential property
of a distinct type that it **does not** imply a subtype relation between it
and its base type. Explict type conversions from a distinct type to its
base type and vice versa are allowed.
A distinct type can be used to model different physical `units`:idx: with a
numerical base type, for example. The following example models currencies.
Different currencies should not be mixed in monetary calculations. Distinct
types are a perfect tool to model different currencies:
.. code-block:: nimrod
type
TDollar = distinct int
TEuro = distinct int
var
d: TDollar
e: TEuro
echo d + 12
# Error: cannot add a number with no unit and a ``TDollar``
Unfortunetaly, ``d + 12.TDollar`` is not allowed either,
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
a ``+`` for dollars needs to be defined:
.. code-block::
proc `+` (x, y: TDollar): TDollar =
result = TDollar(int(x) + int(y))
It does not make sense to multiply a dollar with a dollar, but with a
number without unit; and the same holds for division:
.. code-block::
proc `*` (x: TDollar, y: int): TDollar =
result = TDollar(int(x) * y)
proc `*` (x: int, y: TDollar): TDollar =
result = TDollar(x * int(y))
proc `div` ...
This quickly gets tedious. The implementations are trivial and the compiler
should not generate all this code only to optimize it away later - after all
``+`` for dollars should produce the same binary code as ``+`` for ints.
The pragma ``borrow`` has been designed to solve this problem; in principle
it generates the above trivial implementations:
.. code-block:: nimrod
proc `*` (x: TDollar, y: int): TDollar {.borrow.}
proc `*` (x: int, y: TDollar): TDollar {.borrow.}
proc `div` (x: TDollar, y: int): TDollar {.borrow.}
The ``borrow`` pragma makes the compiler use the same implementation as
the proc that deals with the distinct type's base type, so no code is
generated.
But it seems all this boilerplate code needs to be repeated for the ``TEuro``
currency. This can be solved with templates_.
.. code-block:: nimrod
template Additive(typ: typeDesc): stmt =
proc `+` *(x, y: typ): typ {.borrow.}
proc `-` *(x, y: typ): typ {.borrow.}
# unary operators:
proc `+` *(x: typ): typ {.borrow.}
proc `-` *(x: typ): typ {.borrow.}
template Multiplicative(typ, base: typeDesc): stmt =
proc `*` *(x: typ, y: base): typ {.borrow.}
proc `*` *(x: base, y: typ): typ {.borrow.}
proc `div` *(x: typ, y: base): typ {.borrow.}
proc `mod` *(x: typ, y: base): typ {.borrow.}
template Comparable(typ: typeDesc): stmt =
proc `<` * (x, y: typ): bool {.borrow.}
proc `<=` * (x, y: typ): bool {.borrow.}
proc `==` * (x, y: typ): bool {.borrow.}
template DefineCurrency(typ, base: expr): stmt =
type
typ* = distinct base
Additive(typ)
Multiplicative(typ, base)
Comparable(typ)
DefineCurrency(TDollar, int)
DefineCurrency(TEuro, int)
Type relations Type relations
-------------- --------------
@ -956,7 +1080,7 @@ algorithm determines type equality:
for i in 0..a.tupleLen-1: for i in 0..a.tupleLen-1:
if not typeEqualsAux(a[i], b[i], s): return false if not typeEqualsAux(a[i], b[i], s): return false
result = true result = true
of object, enum, abstract: of object, enum, distinct:
result = a == b result = a == b
of proc: of proc:
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
@ -973,7 +1097,7 @@ auxiliary set ``s`` to detect this case.
Subtype relation Subtype relation
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
If object ``b`` inherits from ``a``, ``b`` is a subtype of ``a``. This subtype If object ``a`` inherits from ``b``, ``a`` is a subtype of ``b``. This subtype
relation is extended to the types ``var``, ``ref``, ``ptr``: relation is extended to the types ``var``, ``ref``, ``ptr``:
.. code-block:: nimrod .. code-block:: nimrod
@ -987,27 +1111,70 @@ relation is extended to the types ``var``, ``ref``, ``ptr``:
of var, ref, ptr: of var, ref, ptr:
result = isSubtype(a.baseType, b.baseType) result = isSubtype(a.baseType, b.baseType)
XXX nil is a special value! .. XXX nil is a special value!
Convertible relation Convertible relation
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
A type ``a`` is convertible to type ``b`` iff the following algorithm returns A type ``a`` is **implicitely** convertible to type ``b`` iff the following
true: algorithm returns true:
.. code-block:: nimrod .. code-block:: nimrod
proc isConvertible(a, b: PType): bool = # XXX range types?
if a.kind == b.kind: proc isImplicitelyConvertible(a, b: PType): bool =
case a.kind case a.kind
of proc: of proc:
if b.kind == proc:
var x = a.parameterTuple var x = a.parameterTuple
var y = b.parameterTuple var y = b.parameterTuple
if x.tupleLen == y.tupleLen: if x.tupleLen == y.tupleLen:
for i in 0.. x.tupleLen-1: for i in 0.. x.tupleLen-1:
if not isSubtype(x[i], y[i]): return false if not isSubtype(x[i], y[i]): return false
result = isSubType(b.resultType, a.resultType) result = isSubType(b.resultType, a.resultType)
of int8: result = b.kind in {int16, int32, int64, int}
of int16: result = b.kind in {int32, int64, int}
of int32: result = b.kind in {int64, int}
of float: result = b.kind in {float32, float64}
of float32: result = b.kind in {float64, float}
of float64: result = b.kind in {float32, float}
of seq:
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
of array:
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
if a.baseType == char and a.indexType.rangeA == 0:
result = b.kind = cstring
of cstring, ptr:
result = b.kind == pointer
of string:
result = b.kind == cstring
A type ``a`` is **explicitely** convertible to type ``b`` iff the following
algorithm returns true:
.. code-block:: nimrod
proc isIntegralType(t: PType): bool =
result = isOrdinal(t) or t.kind in {float, float32, float64}
proc isExplicitelyConvertible(a, b: PType): bool =
if isImplicitelyConvertible(a, b): return true
if isIntegralType(a) and isIntegralType(b): return true
if isSubtype(a, b) or isSubtype(b, a): return true
if a.kind == distinct and typeEquals(a.baseType, b): return true
if b.kind == distinct and typeEquals(b.baseType, a): return true
return false
Assignment compability
~~~~~~~~~~~~~~~~~~~~~~
An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an
`l-value` and ``isImplicitelyConvertible(b.typ, a.typ)`` holds.
Overloading resolution
~~~~~~~~~~~~~~~~~~~~~~
To be written.
Statements and expressions Statements and expressions
@ -1095,7 +1262,7 @@ Type default value
============================ ============================================== ============================ ==============================================
any integer type 0 any integer type 0
any float 0.0 any float 0.0
char '\0' char '\\0'
bool false bool false
ref or pointer type nil ref or pointer type nil
procedural type nil procedural type nil
@ -1192,8 +1359,8 @@ a static error is given. This holds only for expressions of ordinal types.
If the expression is not of an ordinal type, and no ``else`` part is If the expression is not of an ordinal type, and no ``else`` part is
given, control just passes after the ``case`` statement. given, control just passes after the ``case`` statement.
To suppress the static error in the ordinal case the programmer needs To suppress the static error in the ordinal case an ``else`` part with a ``nil``
to write an ``else`` part with a ``nil`` statement. statement can be used.
When statement When statement
@ -1271,7 +1438,7 @@ Example:
# and tries to add them # and tries to add them
var var
f: TFile f: TFile
if openFile(f, "numbers.txt"): if open(f, "numbers.txt"):
try: try:
var a = readLine(f) var a = readLine(f)
var b = readLine(f) var b = readLine(f)
@ -1285,7 +1452,7 @@ Example:
except: except:
echo("Unknown exception!") echo("Unknown exception!")
finally: finally:
closeFile(f) close(f)
The statements after the `try`:idx: are executed in sequential order unless The statements after the `try`:idx: are executed in sequential order unless
an exception ``e`` is raised. If the exception type of ``e`` matches any an exception ``e`` is raised. If the exception type of ``e`` matches any
@ -1417,7 +1584,7 @@ Example:
The `while`:idx: statement is executed until the ``expr`` evaluates to false. The `while`:idx: statement is executed until the ``expr`` evaluates to false.
Endless loops are no error. ``while`` statements open an `implicit block`, Endless loops are no error. ``while`` statements open an `implicit block`,
so that they can be leaved with a ``break`` statement. so that they can be left with a ``break`` statement.
Continue statement Continue statement
@ -1562,8 +1729,9 @@ type `var`).
return intToStr(x) return intToStr(x)
Operators with one parameter are prefix operators, operators with two Operators with one parameter are prefix operators, operators with two
parameters are infix operators. There is no way to declare postfix parameters are infix operators. (However, the parser distinguishes these from
operators: All postfix operators are built-in and handled by the the operators position within an expression.) There is no way to declare
postfix operators: All postfix operators are built-in and handled by the
grammar explicitely. grammar explicitely.
Any operator can be called like an ordinary proc with the '`opr`' Any operator can be called like an ordinary proc with the '`opr`'
@ -1622,18 +1790,13 @@ return values. This can be done in a cleaner way by returning a tuple:
assert t.res == 1 assert t.res == 1
assert t.remainder = 3 assert t.remainder = 3
Even more elegant is to use `tuple unpacking` to access the tuple's fields: Even more elegant is to use `tuple unpacking`:idx: to access the tuple's fields:
.. code-block:: nimrod .. code-block:: nimrod
var (x, y) = divmod(8, 5) # tuple unpacking var (x, y) = divmod(8, 5) # tuple unpacking
assert x == 1 assert x == 1
assert y == 3 assert y == 3
Unfortunately, this form of tuple unpacking is not yet implemented.
..
XXX remove this as soon as tuple unpacking is implemented
Iterators and the for statement Iterators and the for statement
@ -1655,7 +1818,7 @@ Syntax::
The `for`:idx: statement is an abstract mechanism to iterate over the elements The `for`:idx: statement is an abstract mechanism to iterate over the elements
of a container. It relies on an `iterator`:idx: to do so. Like ``while`` of a container. It relies on an `iterator`:idx: to do so. Like ``while``
statements, ``for`` statements open an `implicit block`:idx:, so that they statements, ``for`` statements open an `implicit block`:idx:, so that they
can be leaved with a ``break`` statement. The ``for`` loop declares can be left with a ``break`` statement. The ``for`` loop declares
iteration variables (``x`` in the example) - their scope reaches until the iteration variables (``x`` in the example) - their scope reaches until the
end of the loop body. The iteration variables' types are inferred by the end of the loop body. The iteration variables' types are inferred by the
return type of the iterator. return type of the iterator.
@ -1737,8 +1900,6 @@ possible within a single ``type`` section.
Generics Generics
~~~~~~~~ ~~~~~~~~
`Version 0.7.10: Generic types like in the example do not work.`:red:
Example: Example:
.. code-block:: nimrod .. code-block:: nimrod
@ -1778,11 +1939,9 @@ Example:
# inorder traversal of a binary tree # inorder traversal of a binary tree
# recursive iterators are not yet implemented, so this does not work in # recursive iterators are not yet implemented, so this does not work in
# the current compiler! # the current compiler!
if root.le != nil: if root.le != nil: yield inorder(root.le)
yield inorder(root.le)
yield root.data yield root.data
if root.ri != nil: if root.ri != nil: yield inorder(root.ri)
yield inorder(root.ri)
var var
root: PBinaryTree[string] # instantiate a PBinaryTree with the type string root: PBinaryTree[string] # instantiate a PBinaryTree with the type string
@ -1799,12 +1958,11 @@ introduce type parameters or to instantiate a generic proc, iterator or type.
Templates Templates
~~~~~~~~~ ~~~~~~~~~
A `template`:idx: is a simple form of a macro. It operates on parse trees and is A `template`:idx: is a simple form of a macro: It is a simple substitution
processed in the semantic pass of the compiler. So they integrate well with the mechanism that operates on Nimrod's abstract syntax trees. It is processed in
rest of the language and share none of C's preprocessor macros flaws. However, the semantic pass of the compiler.
they may lead to code that is harder to understand and maintain. So one ought
to use them sparingly. The usage of ordinary procs, iterators or generics is The syntax to *invoke* a template is the same as calling a procedure.
preferred to the usage of templates.
Example: Example:
@ -1815,20 +1973,86 @@ Example:
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6)) assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
templates:
| ``a > b`` is transformed into ``b < a``.
| ``a in b`` is transformed into ``contains(b, a)``.
| ``notin`` and ``isnot`` have the obvious meanings.
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
description*). These are no real types, they just help the compiler parsing.
Real types can be used too; this implies that expressions are expected.
However, for parameter type checking the arguments are semantically checked
before being passed to the template. Other arguments are not semantically
checked before being passed to the template.
The template body does not open a new scope. To open a new scope a ``block``
statement can be used:
.. code-block:: nimrod
template declareInScope(x: expr, t: typeDesc): stmt =
var x: t
template declareInNewScope(x: expr, t: typeDesc): stmt =
# open a new scope:
block:
var x: t
declareInScope(a, int)
a = 42 # works, `a` is known here
declareInNewScope(b, int)
b = 42 # does not work, `b` is unknown
If there is a ``stmt`` parameter it should be the last in the template
declaration, because statements are passed to a template via a
special ``:`` syntax:
.. code-block:: nimrod
template withFile(f, fn, mode: expr, actions: stmt): stmt =
block:
var f: TFile
if open(f, fn, mode):
try:
actions
finally:
close(f)
else:
quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1")
txt.writeln("line 2")
In the example the two ``writeln`` statements are bound to the ``actions``
parameter.
**Style note**: For code readability, it is the best idea to use the least
powerful programming construct that still suffices. So the "check list" is:
(1) Use an ordinary proc/iterator, if possible.
(2) Else: Use a generic proc/iterator, if possible.
(3) Else: Use a template, if possible.
(4) Else: Use a macro.
Macros Macros
------ ------
`Macros`:idx: are the most powerful feature of Nimrod. They can be used `Macros`:idx: are the most powerful feature of Nimrod. They can be used
to implement `domain specific languages`:idx:. But they may lead to code to implement `domain specific languages`:idx:.
that is harder to understand and maintain. So one ought to use them sparingly.
While macros enable advanced compile-time code tranformations, they While macros enable advanced compile-time code tranformations, they
cannot change Nimrod's syntax. However, this is no real restriction because cannot change Nimrod's syntax. However, this is no real restriction because
Nimrod's syntax is flexible enough anyway. Nimrod's syntax is flexible enough anyway.
To write macros, one needs to know how the Nimrod concrete syntax is converted To write macros, one needs to know how the Nimrod concrete syntax is converted
to an abstract syntax tree. (Unfortunately the AST is not yet documented.) to an abstract syntax tree.
There are two ways to invoke a macro: There are two ways to invoke a macro:
(1) invoking a macro like a procedure call (`expression macros`) (1) invoking a macro like a procedure call (`expression macros`)
@ -1847,7 +2071,7 @@ variable number of arguments:
import macros import macros
macro debug(n: expr): stmt = macro debug(n: expr): stmt =
# `n` is a Nimrod AST that contains the whole macro expression # `n` is a Nimrod AST that contains the whole macro invokation
# this macro returns a list of statements: # this macro returns a list of statements:
result = newNimNode(nnkStmtList, n) result = newNimNode(nnkStmtList, n)
# iterate over any argument that is passed to this macro: # iterate over any argument that is passed to this macro:
@ -1948,6 +2172,7 @@ This is best illustrated by an example:
main() main()
.. code-block:: nimrod
# Module B # Module B
import A # A is not parsed here! Only the already known symbols import A # A is not parsed here! Only the already known symbols
# of A are imported. # of A are imported.
@ -1981,7 +2206,7 @@ Tuple or object scope
The field identifiers inside a tuple or object definition are valid in the The field identifiers inside a tuple or object definition are valid in the
following places: following places:
* To the end of the tuple/object definition * To the end of the tuple/object definition.
* Field designators of a variable of the given tuple/object type. * Field designators of a variable of the given tuple/object type.
* In all descendent types of the object type. * In all descendent types of the object type.
@ -2000,9 +2225,11 @@ iterator in which case the overloading resolution takes place:
# Module A # Module A
var x*: string var x*: string
.. code-block:: nimrod
# Module B # Module B
var x*: int var x*: int
.. code-block:: nimrod
# Module C # Module C
import A, B import A, B
write(stdout, x) # error: x is ambiguous write(stdout, x) # error: x is ambiguous
@ -2035,26 +2262,22 @@ processed on the fly during semantic checking. Pragmas are enclosed in the
special ``{.`` and ``.}`` curly brackets. special ``{.`` and ``.}`` curly brackets.
define pragma noSideEffect pragma
------------- -------------------
The `define`:idx: pragma defines a conditional symbol. This symbol may only be The `noSideEffect`:idx: pragma is used to mark a proc/iterator to have no side
used in other pragmas and in the ``defined`` expression and not in ordinary effects. This means that the proc/iterator only changes locations that are
Nimrod source code. The conditional symbols go into a special symbol table. reachable from its parameters and the return value only depends on the
The compiler defines the target processor and the target operating arguments. If none of its parameters have the type ``var T``
system as conditional symbols. or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static
error to mark a proc/iterator to have no side effect if the compiler cannot
Warning: The ``define`` pragma is deprecated as it conflicts with separate verify this.
compilation! One should use boolean constants as a replacement - this is
cleaner anyway.
undef pragma compileTime pragma
------------ ------------------
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a The `compileTime`:idx: pragma is used to mark a proc to be used at compile
conditional symbol. time only. No code will be generated for it. Compile time procs are useful
as helpers for macros.
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
compilation!
error pragma error pragma

0
doc/mytest.cfg Normal file → Executable file
View file

0
doc/nimdoc.css Normal file → Executable file
View file

65
doc/nimrodc.txt Normal file → Executable file
View file

@ -107,8 +107,8 @@ non-optional argument has to be the name of the dynamic library:
proc gtk_image_new(): PGtkWidget {.cdecl, dynlib: "libgtk-x11-2.0.so", importc.} proc gtk_image_new(): PGtkWidget {.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
In general, importing a dynamic library does not require any special linker In general, importing a dynamic library does not require any special linker
options or linking with import libraries. This also options or linking with import libraries. This also implies that no *devel*
implies that no *devel* packages need to be installed. packages need to be installed.
No_decl Pragma No_decl Pragma
@ -279,9 +279,7 @@ However, sometimes one has to optimize. Do it in the following order:
4. try to find a better algorithm 4. try to find a better algorithm
5. do low-level optimizations 5. do low-level optimizations
This section can only help you with the last item. Note that rewriting parts This section can only help you with the last item.
of your program in C is *never* necessary to speed up your program, because
everything that can be done in C can be done in Nimrod.
Optimizing string handling Optimizing string handling
@ -308,31 +306,32 @@ if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme. efficient than any hand-coded scheme.
The ECMAScript code generator ..
============================= The ECMAScript code generator
=============================
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested. Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested.
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since
it is the proper term. Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
since it is the proper term.
The ECMAScript code generator is experimental!
The ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module, Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Nimrod just generates a long ``.js`` file. Since ECMAScript does not have a portable means to include another module,
Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not
available. This includes: Features or modules that the ECMAScript platform does not support are not
available. This includes:
* manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.) * manual memory management (``alloc``, etc.)
* file management (``openfile``, etc.) * casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* most modules of the Standard library * file management
* proper 64 bit integer arithmetic * most modules of the Standard library
* proper unsigned integer arithmetic * proper 64 bit integer arithmetic
* proper unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
available! To access the DOM, use the `dom`:idx: module that is only available However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
for the ECMAScript platform. available! To access the DOM, use the `dom`:idx: module that is only
available for the ECMAScript platform.

0
doc/overview.txt Normal file → Executable file
View file

0
doc/readme.txt Normal file → Executable file
View file

0
doc/regexprs.txt Normal file → Executable file
View file

0
doc/rst.txt Normal file → Executable file
View file

View file

@ -1,24 +0,0 @@
==============================
First steps after installation
==============================
This document explains how to *use* the Nimrod compiler.
Open your favourite text editor and type (or download it
`here <download/code/hallo.nim>`_):
.. code-block:: nimrod
:file: ../tests/hallo.nim
Save this file as ``hallo.nim`` somewhere (I refer to the location as
``$yourloc``). Now open a console and call the Nimrod compiler::
nimrod compile --run $yourloc/hallo
The ``--run`` switch tells Nimrod that it should run the generated
executable after successful compilation. If things don't work,
check if Nimrod's ``bin`` directory is in your path environment
variable. On Windows the directory ``dist\llvm-gcc4.2\bin`` may
also be required in your path.
Note that Nimrod produced a standalone native executable in
``$yourloc`` that you can run without the Nimrod compiler.

1200
doc/theindex.txt Normal file → Executable file

File diff suppressed because it is too large Load diff

0
doc/tut1.txt Normal file → Executable file
View file

46
doc/tut2.txt Normal file → Executable file
View file

@ -311,11 +311,10 @@ class provides a constructor, etc.
c.draw() c.draw()
The code uses a ``draw`` procedure that is bound statically, but inside it The code uses a ``draw`` procedure that is bound statically, but inside it
the dynamic dispatch happens with the help of the ``fdraw`` field. This is the dynamic dispatch happens with the help of the ``fdraw`` field. Even though
slightly more inconvienent than in traditional OOP-languages, but has the this solution has its advantages compared to traditional OOP-languages, it is
advantage of being much more flexible (and somewhat faster). The above approach a **preliminary** solution. Multimethods are a planned language feature that
also allows some form *monkey patching* by modifying the ``fdraw`` field. provide a more flexible and efficient mechanism.
Exceptions Exceptions
@ -323,15 +322,13 @@ Exceptions
In Nimrod `exceptions`:idx: are objects. By convention, exception types are In Nimrod `exceptions`:idx: are objects. By convention, exception types are
prefixed with an 'E', not 'T'. The ``system`` module defines an exception prefixed with an 'E', not 'T'. The ``system`` module defines an exception
hierarchy that you should stick to. Reusing an existing exception type is hierarchy that you might want to stick to.
often better than defining a new exception type: It avoids a proliferation of
types.
Exceptions should be allocated on the heap because their lifetime is unknown. Exceptions should be allocated on the heap because their lifetime is unknown.
A convention is that exceptions should be raised in *exceptional* cases: A convention is that exceptions should be raised in *exceptional* cases:
For example, if a file cannot be opened, this should not raise an exception For example, if a file cannot be opened, this should not raise an
since this is quite common (the file may have been deleted). exception since this is quite common (the file may not exist).
Raise statement Raise statement
@ -359,7 +356,7 @@ The `try`:idx: statement handles exceptions:
# and tries to add them # and tries to add them
var var
f: TFile f: TFile
if openFile(f, "numbers.txt"): if open(f, "numbers.txt"):
try: try:
var a = readLine(f) var a = readLine(f)
var b = readLine(f) var b = readLine(f)
@ -375,7 +372,7 @@ The `try`:idx: statement handles exceptions:
# reraise the unknown exception: # reraise the unknown exception:
raise raise
finally: finally:
closeFile(f) close(f)
The statements after the ``try`` are executed unless an exception is The statements after the ``try`` are executed unless an exception is
raised. Then the appropriate ``except`` part is executed. raised. Then the appropriate ``except`` part is executed.
@ -396,8 +393,6 @@ is not executed (if an exception occurs).
Generics Generics
======== ========
`Version 0.7.10: Complex generic types like in the example do not work.`:red:
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types `Generics`:idx: are Nimrod's means to parametrize procs, iterators or types
with `type parameters`:idx:. They are most useful for efficient type safe with `type parameters`:idx:. They are most useful for efficient type safe
containers: containers:
@ -448,7 +443,7 @@ containers:
while stack.len > 0: while stack.len > 0:
var n = stack.pop() var n = stack.pop()
while n != nil: while n != nil:
yield n yield n.data
add(stack, n.ri) # push right subtree onto the stack add(stack, n.ri) # push right subtree onto the stack
n = n.le # and follow the left pointer n = n.le # and follow the left pointer
@ -472,8 +467,7 @@ Templates
Templates are a simple substitution mechanism that operates on Nimrod's Templates are a simple substitution mechanism that operates on Nimrod's
abstract syntax trees. Templates are processed in the semantic pass of the abstract syntax trees. Templates are processed in the semantic pass of the
compiler. They integrate well with the rest of the language and share none compiler. They integrate well with the rest of the language and share none
of C's preprocessor macros flaws. However, they may lead to code that is harder of C's preprocessor macros flaws.
to understand and maintain. So one should use them sparingly.
To *invoke* a template, call it like a procedure. To *invoke* a template, call it like a procedure.
@ -488,7 +482,8 @@ Example:
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
templates: This has the benefit that if you overload the ``==`` operator, templates: This has the benefit that if you overload the ``==`` operator,
the ``!=`` operator is available automatically and does the right thing. the ``!=`` operator is available automatically and does the right thing. (Except
for IEEE floating point numbers - NaN breaks basic boolean logic.)
``a > b`` is transformed into ``b < a``. ``a > b`` is transformed into ``b < a``.
``a in b`` is transformed into ``contains(b, a)``. ``a in b`` is transformed into ``contains(b, a)``.
@ -513,7 +508,7 @@ This code has a shortcoming: If ``debug`` is set to false someday, the quite
expensive ``$`` and ``&`` operations are still performed! (The argument expensive ``$`` and ``&`` operations are still performed! (The argument
evaluation for procedures is said to be *eager*). evaluation for procedures is said to be *eager*).
Turning the ``log`` proc into a template solves this problem in an elegant way: Turning the ``log`` proc into a template solves this problem:
.. code-block:: nimrod .. code-block:: nimrod
const const
@ -530,7 +525,7 @@ Turning the ``log`` proc into a template solves this problem in an elegant way:
The "types" of templates can be the symbols ``expr`` (stands for *expression*), The "types" of templates can be the symbols ``expr`` (stands for *expression*),
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type ``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
description*). These are no real types, they just help the compiler parsing. description*). These are no real types, they just help the compiler parsing.
In later versions, real types will be supported too. However, real types are supported too.
The template body does not open a new scope. To open a new scope The template body does not open a new scope. To open a new scope
use a ``block`` statement: use a ``block`` statement:
@ -557,7 +552,8 @@ via a special ``:`` syntax:
.. code-block:: nimrod .. code-block:: nimrod
template withFile(f, filename, mode: expr, actions: stmt): stmt = template withFile(f: expr, filename: string, mode: TFileMode,
actions: stmt): stmt =
block: block:
var fn = filename var fn = filename
var f: TFile var f: TFile
@ -583,11 +579,6 @@ once.
Macros Macros
====== ======
If the template mechanism scares you, you will be pleased to hear that
templates are not really necessary: Macros can do anything that templates can
do and much more. Macros are harder to write than templates and even harder
to get right :-). Now that you have been warned, lets see what a macro *is*.
Macros enable advanced compile-time code tranformations, but they Macros enable advanced compile-time code tranformations, but they
cannot change Nimrod's syntax. However, this is no real restriction because cannot change Nimrod's syntax. However, this is no real restriction because
Nimrod's syntax is flexible enough anyway. Nimrod's syntax is flexible enough anyway.
@ -598,7 +589,8 @@ to an abstract syntax tree (AST). The AST is documented in the
There are two ways to invoke a macro: There are two ways to invoke a macro:
(1) invoking a macro like a procedure call (`expression macros`:idx:) (1) invoking a macro like a procedure call (`expression macros`:idx:)
(2) invoking a macro with the special ``macrostmt`` syntax (`statement macros`:idx:) (2) invoking a macro with the special ``macrostmt``
syntax (`statement macros`:idx:)
Expression Macros Expression Macros

0
dos2unix.py Normal file → Executable file
View file

0
examples/hallo.nim Normal file → Executable file
View file

0
examples/htmlrefs.nim Normal file → Executable file
View file

0
examples/htmltitle.nim Normal file → Executable file
View file

0
examples/keyval.nim Normal file → Executable file
View file

0
examples/luaex.nim Normal file → Executable file
View file

2
examples/maximum.nim Normal file → Executable file
View file

@ -3,4 +3,4 @@
import strutils import strutils
echo "Give a list of numbers (separated by spaces): " echo "Give a list of numbers (separated by spaces): "
stdin.readLine.splitSeq.each(parseInt).max.`$`.echo(" is the maximum!") stdin.readLine.split.each(parseInt).max.`$`.echo(" is the maximum!")

0
examples/myfile.txt Normal file → Executable file
View file

0
examples/pythonex.nim Normal file → Executable file
View file

0
examples/readme.txt Normal file → Executable file
View file

0
examples/statcsv.nim Normal file → Executable file
View file

0
examples/tclex.nim Normal file → Executable file
View file

0
gcccpuopt.sh Normal file → Executable file
View file

0
gpl.html Normal file → Executable file
View file

0
ide/config.nim Normal file → Executable file
View file

0
ide/main.nim Normal file → Executable file
View file

0
ide/nimide.glade Normal file → Executable file
View file

0
ide/nimide.gladep Normal file → Executable file
View file

0
ide/nimide.nim Normal file → Executable file
View file

7
install.txt Normal file → Executable file
View file

@ -5,9 +5,6 @@ Installation
Installation on Linux/UNIX Installation on Linux/UNIX
-------------------------- --------------------------
Note:
A C compiler is required - knowledge of C is not!
The GNU C Compiler is fully supported, other compilers may work. The C compiler The GNU C Compiler is fully supported, other compilers may work. The C compiler
should be in your ``$PATH`` (most likely the case). Note that some few Linux should be in your ``$PATH`` (most likely the case). Note that some few Linux
distributions do not ship with a GCC compiler preinstalled - then you have to distributions do not ship with a GCC compiler preinstalled - then you have to
@ -31,8 +28,8 @@ manually. An alternative is to create a symbolic link in ``/usr/bin``::
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod [sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are
provided for distributing the files over the UNIX hierarchy. However, this provided for distributing the files over the UNIX hierarchy. However,
makes updating your Nimrod installation more cumbersome. updating your Nimrod installation is more cumbersome then.
Installation on the Macintosh Installation on the Macintosh

33
koch.py Normal file → Executable file
View file

@ -12,16 +12,17 @@ from pycompab import *
# --------------------- constants ---------------------------------------- # --------------------- constants ----------------------------------------
NIMROD_VERSION = '0.7.10' NIMROD_VERSION = '0.8.1'
# This string contains Nimrod's version. It is the only place # This string contains Nimrod's version. It is the only place
# where the version needs to be updated. The rest is done by # where the version needs to be updated. The rest is done by
# the build process automatically. It is replaced **everywhere**! # the build process automatically. It is replaced **everywhere**!
# Format is: Major.Minor.Patch # Format is: Major.Minor.Patch
# Major part: plan is to use number 1 for the first version that is stable; # Major part: plan is to use number 1 for the first version that is stable;
# higher versions may be incompatible with previous versions # higher versions may be incompatible with previous versions
# Minor part: incremented if new features are added (but is completely # Minor part: incremented if new features are added; unfortunately often
# backwards-compatible) # not backwards-compatible
# Patch level: is increased for every patch # Patch level: is increased for every patch; should be completely
# backwards-compatible
EXPLAIN = true EXPLAIN = true
force = false force = false
@ -209,14 +210,15 @@ def Glob(pattern): # needed because glob.glob() is buggy on Windows 95:
global _baseDir global _baseDir
(head, tail) = os.path.split(Path(pattern)) (head, tail) = os.path.split(Path(pattern))
result = [] result = []
try: if os.path.exists(head):
os.chdir(os.path.join(_baseDir, head))
try: try:
for f in glob.glob(tail): result.append(os.path.join(head, f)) os.chdir(os.path.join(_baseDir, head))
except OSError: try:
result = [] for f in glob.glob(tail): result.append(os.path.join(head, f))
finally: except OSError:
os.chdir(_baseDir) result = []
finally:
os.chdir(_baseDir)
return result return result
def FilenameNoExt(f): def FilenameNoExt(f):
@ -384,10 +386,10 @@ Possible Commands:
boot [options] bootstraps with given command line options boot [options] bootstraps with given command line options
rodsrc generates Nimrod version from Pascal version rodsrc generates Nimrod version from Pascal version
web generates the website web generates the website
profile profile the Nimrod compiler profile profiles the Nimrod compiler
csource [options] build the C sources for installation csource [options] builds the C sources for installation
zip build the installation ZIP package zip builds the installation ZIP package
inno build the Inno Setup installer inno builds the Inno Setup installer
""", NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version) """, NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
def main(args): def main(args):
@ -634,7 +636,6 @@ def getOSandProcessor():
return (host, processor) return (host, processor)
def writePlatdefC(nimrodpath): def writePlatdefC(nimrodpath):
import os
host, processor = getOSandProcessor() host, processor = getOSandProcessor()
f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+") f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+")
f.write(Subs('/* Generated by koch.py */\n' f.write(Subs('/* Generated by koch.py */\n'

0
lib/copying.txt Normal file → Executable file
View file

0
lib/cycle.h Normal file → Executable file
View file

0
lib/ecmas/dom.nim Normal file → Executable file
View file

0
lib/impure/dialogs.nim Normal file → Executable file
View file

0
lib/impure/web.nim Normal file → Executable file
View file

0
lib/impure/zipfiles.nim Normal file → Executable file
View file

0
lib/lgpl.txt Normal file → Executable file
View file

0
lib/nimbase.h Normal file → Executable file
View file

0
lib/posix/posix.nim Normal file → Executable file
View file

0
lib/pure/cgi.nim Normal file → Executable file
View file

0
lib/pure/complex.nim Normal file → Executable file
View file

0
lib/pure/dynlib.nim Normal file → Executable file
View file

0
lib/pure/hashes.nim Normal file → Executable file
View file

0
lib/pure/lexbase.nim Normal file → Executable file
View file

104
lib/pure/macros.nim Normal file → Executable file
View file

@ -8,10 +8,10 @@
# #
## This module contains the interface to the compiler's abstract syntax ## This module contains the interface to the compiler's abstract syntax
## tree (`AST`:idx:). Macros operate on this tree. ## tree (`AST`:idx:). Macros operate on this tree.
## .. include:: ../doc/astspec.txt ## .. include:: ../doc/astspec.txt
#[[[cog #[[[cog
#def toEnum(name, elems): #def toEnum(name, elems):
@ -39,38 +39,38 @@ type
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit, nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit, nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall, nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall, nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
nnkInfix, nnkPrefix, nnkPostfix, nnkPar, nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
nnkCurly, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda, nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
nnkAccQuoted, nnkTableConstr, nnkQualified, nnkBind, nnkTableConstr, nnkQualified, nnkBind, nnkSymChoice,
nnkSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv,
nnkConv, nnkCast, nnkAddr, nnkHiddenAddr, nnkCast, nnkAddr, nnkHiddenAddr, nnkHiddenDeref,
nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64,
nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString, nnkChckRange, nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray,
nnkPassAsOpenArray, nnkAsgn, nnkFastAsgn, nnkDefaultTypeParam, nnkAsgn, nnkFastAsgn, nnkGenericParams, nnkFormalParams,
nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkModule, nnkOfInherit, nnkModule, nnkProcDef, nnkConverterDef,
nnkProcDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef, nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch, nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
nnkElse, nnkMacroStmt, nnkAsmStmt, nnkPragma, nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt,
nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkWhileStmt, nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection,
nnkCaseStmt, nnkVarSection, nnkConstSection, nnkConstDef, nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef,
nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkTryStmt, nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkStmtList, nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
nnkImportStmt, nnkFromStmt, nnkImportAs, nnkIncludeStmt, nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
nnkBlockType, nnkVm, nnkTypeOfExpr, nnkObjectTy,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
nnkRefTy, nnkPtrTy, nnkVarTy, nnkAbstractTy, nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy,
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
TNimNodeKinds* = set[TNimrodNodeKind] TNimNodeKinds* = set[TNimrodNodeKind]
TNimrodTypeKind* = enum TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty, ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst, ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
ntyGenericParam, ntyAbstract, ntyEnum, ntyOrdinal, ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
ntyArray, ntyObject, ntyTuple, ntySet, ntyArray, ntyObject, ntyTuple, ntySet,
ntyRange, ntyPtr, ntyRef, ntyVar, ntyRange, ntyPtr, ntyRef, ntyVar,
ntySequence, ntyProc, ntyPointer, ntyOpenArray, ntySequence, ntyProc, ntyPointer, ntyOpenArray,
@ -79,8 +79,8 @@ type
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128 ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
TNimTypeKinds* = set[TNimrodTypeKind] TNimTypeKinds* = set[TNimrodTypeKind]
TNimrodSymKind* = enum TNimrodSymKind* = enum
nskUnknownSym, nskConditional, nskDynLib, nskParam, nskUnknown, nskConditional, nskDynLib, nskParam,
nskTypeParam, nskTemp, nskType, nskConst, nskGenericParam, nskTemp, nskType, nskConst,
nskVar, nskProc, nskIterator, nskConverter, nskVar, nskProc, nskIterator, nskConverter,
nskMacro, nskTemplate, nskField, nskEnumField, nskMacro, nskTemplate, nskField, nskEnumField,
nskForVar, nskModule, nskLabel, nskStub nskForVar, nskModule, nskLabel, nskStub
@ -91,7 +91,6 @@ type
TNimrodIdent = object of TObject TNimrodIdent = object of TObject
## represents a Nimrod identifier in the AST ## represents a Nimrod identifier in the AST
TNimrodNode {.final.} = object # hidden
TNimrodSymbol {.final.} = object # hidden TNimrodSymbol {.final.} = object # hidden
TNimrodType {.final.} = object # hidden TNimrodType {.final.} = object # hidden
@ -103,12 +102,9 @@ type
## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up ## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up
## *ident*. ## *ident*.
PNimrodNode* {.compilerproc.} = ref TNimrodNode PNimrodNode* = expr
## represents a Nimrod AST node. Macros operate on this type. ## represents a Nimrod AST node. Macros operate on this type.
expr* = PNimrodNode
stmt* = PNimrodNode
# Nodes should be reference counted to make the `copy` operation very fast! # Nodes should be reference counted to make the `copy` operation very fast!
# However, this is difficult to achieve: modify(n[0][1]) should propagate to # However, this is difficult to achieve: modify(n[0][1]) should propagate to
# its father. How to do this without back references? # its father. How to do this without back references?
@ -119,7 +115,7 @@ proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".} proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
## set `n`'s `i`'th child to `child`. ## set `n`'s `i`'th child to `child`.
proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".} proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
## constructs an identifier from the string `s` ## constructs an identifier from the string `s`
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".} proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
@ -159,8 +155,8 @@ proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".}
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".} proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
proc newNimNode*(kind: TNimrodNodeKind, proc newNimNode*(kind: TNimrodNodeKind,
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".} n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".} proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".} proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
@ -192,11 +188,11 @@ proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
## creates an identifier node from `i` ## creates an identifier node from `i`
result = newNimNode(nnkIdent) result = newNimNode(nnkIdent)
result.ident = i result.ident = i
proc newIdentNode*(i: string): PNimrodNode {.compileTime.} = proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
## creates an identifier node from `i` ## creates an identifier node from `i`
result = newNimNode(nnkIdent) result = newNimNode(nnkIdent)
result.ident = !i result.ident = !i
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} = proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
## converts the AST `n` to the concrete Nimrod code and wraps that ## converts the AST `n` to the concrete Nimrod code and wraps that
@ -227,7 +223,7 @@ proc newCall*(theProc: TNimrodIdent,
## the arguments ``args[0..]``. ## the arguments ``args[0..]``.
result = newNimNode(nnkCall) result = newNimNode(nnkCall)
result.add(newIdentNode(theProc)) result.add(newIdentNode(theProc))
result.add(args) result.add(args)
proc newCall*(theProc: string, proc newCall*(theProc: string,
args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} = args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
@ -236,14 +232,14 @@ proc newCall*(theProc: string,
result = newNimNode(nnkCall) result = newNimNode(nnkCall)
result.add(newIdentNode(theProc)) result.add(newIdentNode(theProc))
result.add(args) result.add(args)
proc nestList*(theProc: TNimrodIdent, proc nestList*(theProc: TNimrodIdent,
x: PNimrodNode): PNimrodNode {.compileTime.} = x: PNimrodNode): PNimrodNode {.compileTime.} =
## nests the list `x` into a tree of call expressions: ## nests the list `x` into a tree of call expressions:
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))`` ## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
var L = x.len var L = x.len
result = newCall(theProc, x[L-2], x[L-1]) result = newCall(theProc, x[L-2], x[L-1])
var a = result var a = result
for i in countdown(L-3, 0): for i in countdown(L-3, 0):
a = newCall(theProc, x[i], copyNimTree(a)) a = newCall(theProc, x[i], copyNimTree(a))

10
lib/pure/math.nim Normal file → Executable file
View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2009 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -83,10 +83,12 @@ proc nextPowerOfTwo*(x: int): int =
result = result or (result shr 1) result = result or (result shr 1)
Inc(result) Inc(result)
proc countBits*(n: int32): int {.noSideEffect.} proc countBits32*(n: int32): int {.noSideEffect.} =
## counts the set bits in `n`. ## counts the set bits in `n`.
var v = n
include "system/cntbits" v = v -% ((v shr 1'i32) and 0x55555555'i32)
v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32)
result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32
proc sum*[T](x: openarray[T]): T {.noSideEffect.} = proc sum*[T](x: openarray[T]): T {.noSideEffect.} =
## computes the sum of the elements in `x`. ## computes the sum of the elements in `x`.

0
lib/pure/md5.nim Normal file → Executable file
View file

16
lib/pure/os.nim Normal file → Executable file
View file

@ -58,10 +58,6 @@ when defined(Nimdoc): # only for proper documentation:
## The character used by the operating system to separate pathname ## The character used by the operating system to separate pathname
## components, for example, '/' for POSIX or ':' for the classic ## components, for example, '/' for POSIX or ':' for the classic
## Macintosh. ## Macintosh.
##
## Note that knowing this is not sufficient to be able to parse or
## concatenate pathnames -- use `splitPath` and `joinPath` instead --
## but it is occasionally useful.
AltSep* = '/' AltSep* = '/'
## An alternative character used by the operating system to separate ## An alternative character used by the operating system to separate
@ -80,10 +76,10 @@ when defined(Nimdoc): # only for proper documentation:
ExeExt* = "" ExeExt* = ""
## The file extension of native executables. For example: ## The file extension of native executables. For example:
## "" on UNIX, "exe" on Windows. ## "" for POSIX, "exe" on Windows.
ScriptExt* = "" ScriptExt* = ""
## The file extension of a script file. For example: "" on UNIX, ## The file extension of a script file. For example: "" for POSIX,
## "bat" on Windows. ## "bat" on Windows.
elif defined(macos): elif defined(macos):
@ -111,7 +107,7 @@ elif defined(macos):
# In full paths the first name (e g HD above) is the name of a mounted # In full paths the first name (e g HD above) is the name of a mounted
# volume. # volume.
# These names are not unique, because, for instance, two diskettes with the # These names are not unique, because, for instance, two diskettes with the
# same names could be inserted. This means that paths on MacOS is not # same names could be inserted. This means that paths on MacOS are not
# waterproof. In case of equal names the first volume found will do. # waterproof. In case of equal names the first volume found will do.
# Two colons "::" are the relative path to the parent. Three is to the # Two colons "::" are the relative path to the parent. Three is to the
# grandparent etc. # grandparent etc.
@ -551,7 +547,7 @@ proc sameFile*(path1, path2: string): bool =
proc sameFileContent*(path1, path2: string): bool = proc sameFileContent*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to files with identical ## Returns True if both pathname arguments refer to files with identical
## content. Content is compared byte for byte. ## binary content.
const const
bufSize = 8192 # 8K buffer bufSize = 8192 # 8K buffer
var var
@ -712,7 +708,7 @@ proc putEnv*(key, val: string) =
OSError() OSError()
iterator iterOverEnvironment*(): tuple[key, value: string] = iterator iterOverEnvironment*(): tuple[key, value: string] =
## Iterate over all environments varialbes. In the first component of the ## Iterate over all environments variables. In the first component of the
## tuple is the name of the current variable stored, in the second its value. ## tuple is the name of the current variable stored, in the second its value.
getEnvVarsC() getEnvVarsC()
for i in 0..high(environment): for i in 0..high(environment):
@ -760,7 +756,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
## walks over the directory `dir` and yields for each directory or file in ## walks over the directory `dir` and yields for each directory or file in
## `dir`. The component type and full path for each item is returned. ## `dir`. The component type and full path for each item is returned.
## Walking is not recursive. ## Walking is not recursive.
## Example: Assuming this directory structure:: ## Example: This directory structure::
## dirA / dirB / fileB1.txt ## dirA / dirB / fileB1.txt
## / dirC ## / dirC
## / fileA1.txt ## / fileA1.txt

0
lib/pure/osproc.nim Normal file → Executable file
View file

0
lib/pure/parsecfg.nim Normal file → Executable file
View file

0
lib/pure/parsecsv.nim Normal file → Executable file
View file

0
lib/pure/parseopt.nim Normal file → Executable file
View file

1
lib/pure/parsesql.nim Normal file → Executable file
View file

@ -571,6 +571,7 @@ proc getTok(p: var TSqlParser) =
proc sqlError(p: TSqlParser, msg: string) = proc sqlError(p: TSqlParser, msg: string) =
var e: ref EInvalidSql var e: ref EInvalidSql
new(e)
e.msg = errorStr(p, msg) e.msg = errorStr(p, msg)
raise e raise e

0
lib/pure/parsexml.nim Normal file → Executable file
View file

2
lib/pure/regexprs.nim Normal file → Executable file
View file

@ -54,10 +54,10 @@ proc find*(s, pattern: string, matches: var openarray[string],
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured ## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
## substrings in the array ``matches``. If it does not match, nothing ## substrings in the array ``matches``. If it does not match, nothing
## is written into ``matches``. ## is written into ``matches``.
proc find*(s, pattern: string, start: int = 0): bool proc find*(s, pattern: string, start: int = 0): bool
## returns ``true`` if ``pattern`` occurs in ``s``. ## returns ``true`` if ``pattern`` occurs in ``s``.
proc rawCompile(pattern: string, flags: cint): PPcre = proc rawCompile(pattern: string, flags: cint): PPcre =
var var
msg: CString msg: CString

4
lib/pure/streams.nim Normal file → Executable file
View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2009 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -42,7 +42,7 @@ proc write*(s: PStream, x: string) =
s.writeData(s, cstring(x), x.len) s.writeData(s, cstring(x), x.len)
proc read[T](s: PStream, result: var T) = proc read[T](s: PStream, result: var T) =
## generic write procedure. Reads `result` from the stream `s`. ## generic read procedure. Reads `result` from the stream `s`.
if s.readData(s, addr(result), sizeof(T)) != sizeof(T): if s.readData(s, addr(result), sizeof(T)) != sizeof(T):
raise newEIO("cannot read from stream") raise newEIO("cannot read from stream")

0
lib/pure/strtabs.nim Normal file → Executable file
View file

73
lib/pure/strutils.nim Normal file → Executable file
View file

@ -27,7 +27,7 @@ template newException(exceptn, message: expr): expr =
type type
TCharSet* = set[char] # for compability for Nim TCharSet* = set[char] # for compability with Nim
const const
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'} Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
@ -45,9 +45,9 @@ const
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'} IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
## the set of characters an identifier can start with ## the set of characters an identifier can start with
strStart* = 0 # this is only for bootstraping strStart* = 0 ## this is only for bootstraping
# XXX: remove this someday ## XXX: remove this someday
nl* = "\n" # this is only for bootstraping XXX: remove this somehow nl* = "\n" ## this is only for bootstraping XXX: remove this somehow
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.} proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
## The `substitution`:idx: operator performs string substitutions in ## The `substitution`:idx: operator performs string substitutions in
@ -64,8 +64,13 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
## .. code-block:: nimrod ## .. code-block:: nimrod
## "The cat eats fish." ## "The cat eats fish."
## ##
## The substitution variables (the thing after the ``$``) ## The substitution variables (the thing after the ``$``) are enumerated
## are enumerated from 1 to 9. ## from 1 to ``a.len``.
## The notation ``$#`` can be used to refer to the next substitution variable:
##
## .. code-block:: nimrod
## "$# eats $#." % ["The cat", "fish"]
##
## Substitution variables can also be words (that is ## Substitution variables can also be words (that is
## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even ## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even
## indices are keys and with odd indices are the corresponding values. ## indices are keys and with odd indices are the corresponding values.
@ -267,19 +272,43 @@ iterator splitLines*(s: string): string =
else: break # was '\0' else: break # was '\0'
first = last first = last
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect.} = template iterToProc(iter: expr): stmt =
## The same as `split`, but is a proc that returns a sequence of substrings.
result = @[] result = @[]
for line in splitLines(s): add(result, line) for x in iter: add(result, x)
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect, deprecated.} =
## The same as `splitLines`, but is a proc that returns a sequence
## of substrings.
## **Deprecated since version 0.8.0**: Use `splitLines` instead.
iterToProc(splitLines(s))
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {. proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
noSideEffect.} noSideEffect, deprecated.} =
## The same as `split`, but is a proc that returns a sequence of substrings. ## The same as `split`, but is a proc that returns a sequence of substrings.
## **Deprecated since version 0.8.0**: Use `split` instead.
iterToProc(split(s, seps))
proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect.} = proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect,
deprecated.} =
## The same as `split`, but is a proc that returns a sequence of substrings. ## The same as `split`, but is a proc that returns a sequence of substrings.
result = @[] ## **Deprecated since version 0.8.0**: Use `split` instead.
for sub in split(s, sep): add(result, sub) iterToProc(split(s, sep))
proc splitLines*(s: string): seq[string] {.noSideEffect.} =
## The same as the `splitLines` iterator, but is a proc that returns a
## sequence of substrings.
iterToProc(splitLines(s))
proc split*(s: string, seps: set[char] = Whitespace): seq[string] {.
noSideEffect.} =
## The same as the `split` iterator, but is a proc that returns a
## sequence of substrings.
iterToProc(split(s, seps))
proc split*(s: string, sep: char): seq[string] {.noSideEffect.} =
## The same as the `split` iterator, but is a proc that returns a sequence
## of substrings.
iterToProc(split(s, sep))
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.} proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.}
## Compares two strings in a case insensitive manner. Returns: ## Compares two strings in a case insensitive manner. Returns:
@ -308,7 +337,7 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.}
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.} proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.}
## Converts `x` to its hexadecimal representation. The resulting string ## Converts `x` to its hexadecimal representation. The resulting string
## will be exactly `len` characters long. No prefix like ``0x`` ## will be exactly `len` characters long. No prefix like ``0x``
## is generated. `x` is treated as unsigned value. ## is generated. `x` is treated as an unsigned value.
proc intToStr*(x: int, minchars: int = 1): string proc intToStr*(x: int, minchars: int = 1): string
## Converts `x` to its decimal representation. The resulting string ## Converts `x` to its decimal representation. The resulting string
@ -367,7 +396,7 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
proc allCharsInSet*(s: string, theSet: TCharSet): bool = proc allCharsInSet*(s: string, theSet: TCharSet): bool =
## returns true iff each character of `s` is in the set `theSet`. ## returns true iff each character of `s` is in the set `theSet`.
for c in items(s): for c in items(s):
if not (c in theSet): return false if c notin theSet: return false
return true return true
proc quoteIfContainsWhite*(s: string): string = proc quoteIfContainsWhite*(s: string): string =
@ -397,12 +426,12 @@ proc endsWith(s, suffix: string): bool =
when false: when false:
proc abbrev(s: string, possibilities: openarray[string]): int = proc abbrev(s: string, possibilities: openarray[string]): int =
## returns the index of the first item in `possibilities` if not ## returns the index of the first item in `possibilities` if not
## ambigious; -1 if no item has been found; -2 if multiple items ## ambiguous; -1 if no item has been found; -2 if multiple items
## match. ## match.
result = -1 # none found result = -1 # none found
for i in 0..possibilities.len-1: for i in 0..possibilities.len-1:
if possibilities[i].startsWith(s): if possibilities[i].startsWith(s):
if result >= 0: return -2 # ambigious if result >= 0: return -2 # ambiguous
result = i result = i
proc repeatChar(count: int, c: Char = ' '): string = proc repeatChar(count: int, c: Char = ' '): string =
@ -509,12 +538,6 @@ proc cmpIgnoreStyle(a, b: string): int =
{.pop.} {.pop.}
# ---------- splitting -----------------------------------------------------
proc splitSeq(s: string, seps: set[char]): seq[string] =
result = @[]
for sub in split(s, seps): add result, sub
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
proc join*(a: openArray[string], sep: string): string = proc join*(a: openArray[string], sep: string): string =
@ -732,7 +755,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
# one more valid negative than prositive integer. Thus we perform the # one more valid negative than prositive integer. Thus we perform the
# computation as a negative number and then change the sign at the end. # computation as a negative number and then change the sign at the end.
var var
i: int = index # a local i is more efficient than accessing a var parameter i = index # a local i is more efficient than accessing a var parameter
sign: BiggestInt = -1 sign: BiggestInt = -1
if s[i] == '+': if s[i] == '+':
inc(i) inc(i)
@ -758,7 +781,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
proc parseInt(s: string): int = proc parseInt(s: string): int =
var var
index: int = 0 index = 0
res = rawParseInt(s, index) res = rawParseInt(s, index)
if index == -1: if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s) raise newException(EInvalidValue, "invalid integer: " & s)

0
lib/pure/terminal.nim Normal file → Executable file
View file

6
lib/pure/times.nim Normal file → Executable file
View file

@ -25,13 +25,13 @@ type
when defined(posix): when defined(posix):
type type
TTime* = abstract int ## abstract type that represents a time TTime* = distinct int ## distinct type that represents a time
elif defined(windows): elif defined(windows):
when defined(vcc): when defined(vcc):
# newest version of Visual C++ defines time_t to be of 64 bits # newest version of Visual C++ defines time_t to be of 64 bits
type TTime* = abstract int64 type TTime* = distinct int64
else: else:
type TTime* = abstract int32 type TTime* = distinct int32
elif defined(ECMAScript): elif defined(ECMAScript):
type type
TTime* {.final.} = object TTime* {.final.} = object

0
lib/pure/unicode.nim Normal file → Executable file
View file

0
lib/pure/xmlgen.nim Normal file → Executable file
View file

93
lib/system.nim Normal file → Executable file
View file

@ -42,8 +42,12 @@ type
type type
`nil` {.magic: "Nil".} `nil` {.magic: "Nil".}
expr* {.magic: Expr.} ## meta type to denote an expression (for templates)
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
typeDesc* {.magic: TypeDesc.} ## meta type to denote
## a type description (for templates)
proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.} proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
## Special comile-time procedure that checks whether `x` is ## Special comile-time procedure that checks whether `x` is
## defined. `x` has to be an identifier or a qualified identifier. ## defined. `x` has to be an identifier or a qualified identifier.
## This can be used to check whether a library provides a certain ## This can be used to check whether a library provides a certain
@ -54,6 +58,12 @@ proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.}
## # provide our own toUpper proc here, because strutils is ## # provide our own toUpper proc here, because strutils is
## # missing it. ## # missing it.
proc definedInScope*[T](x: T, scope=0): bool {.
magic: "DefinedInScope", noSideEffect.}
## Special comile-time procedure that checks whether `x` is
## defined in the scope `scope`. `x` has to be an identifier.
## 0 means the current scope, 1 means the scope above the current scope, etc.
# these require compiler magic: # these require compiler magic:
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
## Boolean not; returns true iff ``x == false``. ## Boolean not; returns true iff ``x == false``.
@ -434,30 +444,6 @@ proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.}
## is -MININT for its type), an overflow exception is thrown (if overflow ## is -MININT for its type), an overflow exception is thrown (if overflow
## checking is turned on). ## checking is turned on).
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
## The minimum value of two integers.
proc min*[T](x: openarray[T]): T =
## The minimum value of an openarray.
result = x[0]
for i in 1..high(x): result = min(result, x[i])
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
## The maximum value of two integers.
proc max*[T](x: openarray[T]): T =
## The maximum value of an openarray.
result = x[0]
for i in 1..high(x): result = max(result, x[i])
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.} proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.} proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.} proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.}
@ -613,7 +599,7 @@ template `not_in` * (x, y: expr): expr = not contains(y, x)
proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
template `is_not` *(x, y: expr): expr = not (x is y) template `is_not` *(x, y: expr): expr = not (x is y)
proc cmp*[T](x, y: T): int = proc cmp*[T, S: typeDesc](x: T, y: S): int =
## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y ## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y
## and 0 iff x == y. This is useful for writing generic algorithms without ## and 0 iff x == y. This is useful for writing generic algorithms without
## performance loss. This generic implementation uses the `==` and `<` ## performance loss. This generic implementation uses the `==` and `<`
@ -999,6 +985,32 @@ iterator countup*[T](a, b: T, step = 1): T {.inline.} =
# we cannot use ``for x in a..b: `` here, because that is not # we cannot use ``for x in a..b: `` here, because that is not
# known in the System module # known in the System module
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
## The minimum value of two integers.
proc min*[T](x: openarray[T]): T =
## The minimum value of an openarray.
result = x[0]
for i in 1..high(x): result = min(result, x[i])
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
## The maximum value of two integers.
proc max*[T](x: openarray[T]): T =
## The maximum value of an openarray.
result = x[0]
for i in 1..high(x): result = max(result, x[i])
iterator items*[T](a: openarray[T]): T {.inline.} = iterator items*[T](a: openarray[T]): T {.inline.} =
## iterates over each item of `a`. ## iterates over each item of `a`.
var i = 0 var i = 0
@ -1009,9 +1021,11 @@ iterator items*[T](a: openarray[T]): T {.inline.} =
iterator items*[IX, T](a: array[IX, T]): T {.inline.} = iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
## iterates over each item of `a`. ## iterates over each item of `a`.
var i = low(IX) var i = low(IX)
while i <= high(IX): if i <= high(IX):
yield a[i] while true:
inc(i) yield a[i]
if i >= high(IX): break
inc(i)
iterator items*[T](a: seq[T]): T {.inline.} = iterator items*[T](a: seq[T]): T {.inline.} =
## iterates over each item of `a`. ## iterates over each item of `a`.
@ -1032,9 +1046,11 @@ iterator items*[T](a: set[T]): T {.inline.} =
## elements that are really in the set (and not over the ones the set is ## elements that are really in the set (and not over the ones the set is
## able to hold). ## able to hold).
var i = low(T) var i = low(T)
while i <= high(T): if i <= high(T):
if i in a: yield i while true:
inc(i) if i in a: yield i
if i >= high(T): break
inc(i)
iterator items*(a: cstring): char {.inline.} = iterator items*(a: cstring): char {.inline.} =
## iterates over each item of `a`. ## iterates over each item of `a`.
@ -1082,14 +1098,13 @@ proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
when not defined(NimrodVM): when not defined(NimrodVM):
when not defined(ECMAScript): when not defined(ECMAScript):
# XXX make this local procs proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} =
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
result = cast[pointer](x) result = cast[pointer](x)
else: else:
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} = proc seqToPtr[T](x: seq[T]): pointer {.pure, nosideeffect.} =
asm """return `x`""" asm """return `x`"""
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} = proc `==` *[T: typeDesc](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for ## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`. ## the element type `T`.
if seqToPtr(x) == seqToPtr(y): if seqToPtr(x) == seqToPtr(y):
@ -1101,10 +1116,9 @@ when not defined(NimrodVM):
if x[i] != y[i]: return false if x[i] != y[i]: return false
result = true result = true
proc find*[T, S](a: T, item: S): int {.inline.} = proc find*[T, S: typeDesc](a: T, item: S): int {.inline.}=
## Returns the first index of `item` in `a` or -1 if not found. This requires ## Returns the first index of `item` in `a` or -1 if not found. This requires
## appropriate `==` and `items` procs to work. ## appropriate `items` and `==` procs to work.
result = 0
for i in items(a): for i in items(a):
if i == item: return if i == item: return
inc(result) inc(result)
@ -1437,6 +1451,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
include "system/arithm" include "system/arithm"
{.pop.} # stack trace {.pop.} # stack trace
include "system/dyncalls" include "system/dyncalls"
include "system/sets"
const const
GenericSeqSize = (2 * sizeof(int)) GenericSeqSize = (2 * sizeof(int))

0
lib/system/alloc.nim Normal file → Executable file
View file

0
lib/system/ansi_c.nim Normal file → Executable file
View file

0
lib/system/arithm.nim Normal file → Executable file
View file

2
lib/system/assign.nim Normal file → Executable file
View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2009 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.

0
lib/system/cellsets.nim Normal file → Executable file
View file

10
lib/system/cntbits.nim Normal file → Executable file
View file

@ -8,13 +8,5 @@
# #
proc population16(a: int): int {.inline.} =
var x = a
x = ((x and 0xAAAA) shr 1) + (x and 0x5555)
x = ((x and 0xCCCC) shr 2) + (x and 0x3333)
x = ((x and 0xF0F0) shr 4) + (x and 0x0F0F)
x = ((x and 0xFF00) shr 8) + (x and 0x00FF)
return x
proc countBits(n: int32): int =
result = population16(n and 0xffff'i32) + population16(n shr 16'i32)

6
lib/system/debugger.nim Normal file → Executable file
View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2009 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -11,9 +11,9 @@
# with the application. We should not use dynamic memory here as that # with the application. We should not use dynamic memory here as that
# would interfere with the GC and trigger ON/OFF errors if the # would interfere with the GC and trigger ON/OFF errors if the
# user program corrupts memory. Unfortunately, for dispaying # user program corrupts memory. Unfortunately, for dispaying
# variables we use the system.repr() proc which uses Nimrod # variables we use the ``system.repr()`` proc which uses Nimrod
# strings and thus allocates memory from the heap. Pity, but # strings and thus allocates memory from the heap. Pity, but
# I do not want to implement repr() twice. We also cannot deactivate # I do not want to implement ``repr()`` twice. We also cannot deactivate
# the GC here as that might run out of memory too quickly... # the GC here as that might run out of memory too quickly...
type type

Some files were not shown because too many files have changed in this diff Show more