added tools and web dirs
This commit is contained in:
parent
300430fbba
commit
66a7e3d37c
489 changed files with 4593 additions and 9878 deletions
0
.bzrignore
Normal file → Executable file
0
.bzrignore
Normal file → Executable file
0
Nimrod.geany
Normal file → Executable file
0
Nimrod.geany
Normal file → Executable file
4
boot.nim
Normal file → Executable file
4
boot.nim
Normal file → Executable file
|
|
@ -27,9 +27,9 @@ proc exec(cmd: string) =
|
|||
|
||||
proc writePlatdefC =
|
||||
var f: TFile
|
||||
if openFile(f, "build/platdef.c", fmWrite):
|
||||
if open(f, "build/platdef.c", fmWrite):
|
||||
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
quit("Cannot write 'build/platdef.c'\n")
|
||||
|
||||
|
|
|
|||
0
cogapp.py
Normal file → Executable file
0
cogapp.py
Normal file → Executable file
0
config/my_nimrod.cfg
Normal file → Executable file
0
config/my_nimrod.cfg
Normal file → Executable file
0
config/nimdoc.cfg
Normal file → Executable file
0
config/nimdoc.cfg
Normal file → Executable file
8
config/nimrod.cfg
Normal file → Executable file
8
config/nimrod.cfg
Normal file → Executable file
|
|
@ -24,21 +24,23 @@ path="$lib/windows"
|
|||
path="$lib/posix"
|
||||
path="$lib/ecmas"
|
||||
|
||||
@if release:
|
||||
@if release or quick:
|
||||
obj_checks:off
|
||||
field_checks:off
|
||||
range_checks:off
|
||||
bound_checks:off
|
||||
overflow_checks:off
|
||||
assertions:off
|
||||
|
||||
stacktrace:off
|
||||
debugger:off
|
||||
line_dir:off
|
||||
opt:speed
|
||||
dead_code_elim:on
|
||||
@end
|
||||
|
||||
@if release:
|
||||
opt:speed
|
||||
@end
|
||||
|
||||
# additional options always passed to the compiler:
|
||||
--verbosity: "1"
|
||||
|
||||
|
|
|
|||
0
configure
vendored
Normal file → Executable file
0
configure
vendored
Normal file → Executable file
0
copying.txt
Normal file → Executable file
0
copying.txt
Normal file → Executable file
1
data/advopt.txt
Normal file → Executable file
1
data/advopt.txt
Normal file → Executable file
|
|
@ -14,6 +14,7 @@ Advanced options:
|
|||
--lib:PATH set the system library path
|
||||
-c, --compile_only compile only; do not assemble or 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'
|
||||
subdirectory named 'compile_$project$scriptext')
|
||||
--os:SYMBOL set the target operating system (cross-compilation)
|
||||
|
|
|
|||
35
data/ast.yml
Normal file → Executable file
35
data/ast.yml
Normal file → Executable file
|
|
@ -57,11 +57,12 @@
|
|||
'TypeKind': [ # order is important!
|
||||
# Don't forget to change hti.nim if you make a change here
|
||||
'tyNone', 'tyBool', 'tyChar',
|
||||
'tyEmpty', 'tyArrayConstr', 'tyNil',
|
||||
'tyGeneric',
|
||||
'tyGenericInst', # instantiated generic type
|
||||
'tyGenericParam',
|
||||
'tyAbstract', # abstract type
|
||||
'tyEmpty', 'tyArrayConstr', 'tyNil', 'tyExpr', 'tyStmt', 'tyTypeDesc',
|
||||
'tyGenericInvokation', # ``T[a, b]`` for types to invoke
|
||||
'tyGenericBody', # ``T[a, b, body]`` last parameter is the body
|
||||
'tyGenericInst', # ``T[a, b, realInstance]`` instantiated generic type
|
||||
'tyGenericParam', # ``a`` in the example
|
||||
'tyDistinct',
|
||||
'tyEnum',
|
||||
'tyOrdinal',
|
||||
'tyArray',
|
||||
|
|
@ -123,8 +124,9 @@
|
|||
# for transforming ``s.len`` to ``len(s)``
|
||||
'nkCommand', # a call like ``p 2, 4`` without parenthesis
|
||||
'nkCall', # a call like p(x, y) or an operation like +(a, b)
|
||||
'nkGenericCall', # a call with given type parameters
|
||||
'nkExplicitTypeListCall', # a call with given explicit typelist
|
||||
'nkCallStrLit', # a call with a string literal
|
||||
# x"abc" has two sons: nkIdent, nkRStrLit
|
||||
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
|
||||
'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
|
||||
'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
|
||||
'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
|
||||
|
|
@ -174,7 +176,6 @@
|
|||
|
||||
'nkAsgn', # a = b
|
||||
'nkFastAsgn', # internal node for a fast ``a = b`` (no string copy)
|
||||
'nkDefaultTypeParam', # `ident = typeDesc` in generic parameters
|
||||
'nkGenericParams', # generic parameters
|
||||
'nkFormalParams', # formal parameters
|
||||
'nkOfInherit', # inherited from symbol
|
||||
|
|
@ -215,7 +216,6 @@
|
|||
'nkStmtList', # a list of statements
|
||||
'nkImportStmt', # an import statement
|
||||
'nkFromStmt', # a from * import statement
|
||||
'nkImportAs', # an `import xyx as abc` section
|
||||
'nkIncludeStmt', # an include statement
|
||||
'nkCommentStmt', # a comment statement
|
||||
'nkStmtListExpr', # a statement list followed by an expr; this is used
|
||||
|
|
@ -225,20 +225,18 @@
|
|||
# temporary scope
|
||||
'nkStmtListType', # a statement list 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:
|
||||
'nkTypeOfExpr',
|
||||
'nkObjectTy',
|
||||
'nkTupleTy',
|
||||
'nkRecList', # list of record/object parts
|
||||
'nkRecCase', # case section of record/object
|
||||
'nkRecWhen', # when section of record/object
|
||||
'nkRecList', # list of object parts
|
||||
'nkRecCase', # case section of object
|
||||
'nkRecWhen', # when section of object
|
||||
'nkRefTy',
|
||||
'nkPtrTy',
|
||||
'nkVarTy',
|
||||
'nkAbstractTy', # abstract type
|
||||
'nkDistinctTy', # distinct type
|
||||
'nkProcTy',
|
||||
'nkEnumTy',
|
||||
'nkEnumFieldDef', # `ident = expr` in an enumeration
|
||||
|
|
@ -248,12 +246,13 @@
|
|||
'SymKind': [
|
||||
# the different symbols (start with the prefix sk);
|
||||
# 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)
|
||||
'skDynLib', # symbol represents a dynamic library; this is used
|
||||
# internally; it does not exist in Nimrod code
|
||||
'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)
|
||||
'skType', # a type
|
||||
'skConst', # a constant
|
||||
|
|
|
|||
1
data/basicopt.txt
Normal file → Executable file
1
data/basicopt.txt
Normal file → Executable file
|
|
@ -5,6 +5,7 @@ Command::
|
|||
compile_to_c, cc compile project with C code generator
|
||||
doc generate the documentation for inputfile
|
||||
rst2html converts a reStructuredText file to HTML
|
||||
rst2tex converts a reStructuredText file to TeX
|
||||
Arguments:
|
||||
arguments are passed to the program being run (if --run option is selected)
|
||||
Options:
|
||||
|
|
|
|||
0
data/ccomps.txt
Normal file → Executable file
0
data/ccomps.txt
Normal file → Executable file
4
data/keywords.txt
Normal file → Executable file
4
data/keywords.txt
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
|||
abstract addr and as asm
|
||||
addr and as asm
|
||||
bind block break
|
||||
case cast const continue converter
|
||||
discard div
|
||||
discard distinct div
|
||||
elif else end enum except
|
||||
finally for from generic
|
||||
if implies import in include is isnot iterator
|
||||
|
|
|
|||
5
data/magic.yml
Normal file → Executable file
5
data/magic.yml
Normal file → Executable file
|
|
@ -3,6 +3,7 @@
|
|||
[
|
||||
'None',
|
||||
'Defined',
|
||||
'DefinedInScope',
|
||||
'Low',
|
||||
'High',
|
||||
'SizeOf',
|
||||
|
|
@ -17,7 +18,6 @@
|
|||
'New',
|
||||
'NewFinalize',
|
||||
'NewSeq',
|
||||
'RegisterFinalizer',
|
||||
'LengthOpenArray',
|
||||
'LengthStr',
|
||||
'LengthArray',
|
||||
|
|
@ -203,6 +203,9 @@
|
|||
'EmptySet',
|
||||
'IntSetBaseType',
|
||||
'Nil',
|
||||
'Expr',
|
||||
'Stmt',
|
||||
'TypeDesc',
|
||||
|
||||
# magic constants:
|
||||
'IsMainModule',
|
||||
|
|
|
|||
22
data/messages.yml
Normal file → Executable file
22
data/messages.yml
Normal file → Executable file
|
|
@ -31,15 +31,14 @@
|
|||
{'errOperatorExpected': "operator expected, but found '$1'"},
|
||||
{'errTokenExpected': "'$1' expected"},
|
||||
{'errStringAfterIncludeExpected': "string after 'include' expected"},
|
||||
{'errRecursiveInclude': "recursive include file: '$1'"},
|
||||
{'errRecursiveDependencyX': "recursive dependency: '$1'"},
|
||||
{'errOnOrOffExpected': "'on' or 'off' expected"},
|
||||
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
||||
{'errInvalidPragma': 'invalid pragma'},
|
||||
{'errUnknownPragma': "unknown pragma: '$1'"},
|
||||
{'errUnknownDirective': "unknown directive: '$1'"},
|
||||
{'errInvalidDirective': 'invalid directive'},
|
||||
{'errInvalidDirectiveX': "invalid directive: '$1'"},
|
||||
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
|
||||
{'errEmptyAsm': 'empty asm statement makes no sense'},
|
||||
{'errEmptyAsm': 'empty asm statement'},
|
||||
{'errInvalidIndentation': 'invalid indentation'},
|
||||
{'errExceptionExpected': 'exception expected'},
|
||||
{'errExceptionAlreadyHandled': 'exception already handled'},
|
||||
|
|
@ -93,9 +92,6 @@
|
|||
{'errCannotEvalXBecauseIncompletelyDefined':
|
||||
"cannot evalutate '$1' because type is not defined completely"},
|
||||
{'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"},
|
||||
{'errUndeclaredFieldX': "undeclared field: '$1'"},
|
||||
{'errNilAccess': 'attempt to access a nil address'},
|
||||
|
|
@ -155,7 +151,7 @@
|
|||
{'errButExpected': 'but expected one of: '},
|
||||
{'errButExpectedX': "but expected '$1'"},
|
||||
{'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'},
|
||||
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
|
||||
{'errPragmaOnlyInHeaderOfProc':
|
||||
|
|
@ -198,16 +194,14 @@
|
|||
{'errNamedExprNotAllowed': 'named expression not allowed here'},
|
||||
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
|
||||
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
|
||||
{'errInvalidVisibilityX': "invalid invisibility: '$1'"},
|
||||
{'errInvalidVisibilityX': "invalid visibility: '$1'"},
|
||||
{'errInitHereNotAllowed': 'initialization not allowed here'},
|
||||
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
|
||||
{'errIteratorNotAllowed':
|
||||
"iterators can only be defined at the module's top level"},
|
||||
{'errIteratorNeedsImplementation': 'iterator needs an implementation'},
|
||||
{'errIteratorNeedsReturnType': 'iterator needs a return type'},
|
||||
{'errXNeedsReturnType': '$1 needs a return type'},
|
||||
{'errInvalidCommandX': "invalid command: '$1'"},
|
||||
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
||||
{'errTypeXNeedsImplementation': "type '$1' needs an implementation"},
|
||||
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
|
||||
{'errInstantiationFrom': 'instantiation from here'},
|
||||
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
||||
|
|
@ -230,12 +224,12 @@
|
|||
{'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"},
|
||||
{'errAssertionFailed': "assertion failed"},
|
||||
{'errCannotGenerateCodeForX': "cannot generate code for '$1'"},
|
||||
{'errXNeedsReturnType': "converter needs return type"},
|
||||
{'errXRequiresOneArgument': "converter requires one parameter"},
|
||||
{'errXRequiresOneArgument': "$1 requires one parameter"},
|
||||
{'errUnhandledExceptionX': "unhandled exception: $1"},
|
||||
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
|
||||
{'errXisNoMacroOrTemplate': "'$1' is no macro or template"},
|
||||
{'errXhasSideEffects': "'$1' can have side effects"},
|
||||
{'errIteratorExpected': "iterator within for loop context expected"},
|
||||
|
||||
# user error message:
|
||||
{'errUser': '$1'},
|
||||
|
|
|
|||
0
data/pas_keyw.yml
Normal file → Executable file
0
data/pas_keyw.yml
Normal file → Executable file
0
data/readme.txt
Normal file → Executable file
0
data/readme.txt
Normal file → Executable file
0
diff/empty.txt
Normal file → Executable file
0
diff/empty.txt
Normal file → Executable file
8
doc/abstypes.txt
Normal file → Executable file
8
doc/abstypes.txt
Normal file → Executable file
|
|
@ -91,7 +91,7 @@ we define our own ``+`` for dollars:
|
|||
result = TDollar(int(x) + int(y))
|
||||
|
||||
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::
|
||||
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:
|
||||
|
||||
.. 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.}
|
||||
|
||||
|
|
@ -129,13 +129,13 @@ the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
|
|||
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: base, y: typ): typ {.borrow.}
|
||||
proc `div` *(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.}
|
||||
|
|
|
|||
0
doc/astspec.txt
Normal file → Executable file
0
doc/astspec.txt
Normal file → Executable file
0
doc/docs.txt
Normal file → Executable file
0
doc/docs.txt
Normal file → Executable file
0
doc/endb.txt
Normal file → Executable file
0
doc/endb.txt
Normal file → Executable file
0
doc/filelist.txt
Normal file → Executable file
0
doc/filelist.txt
Normal file → Executable file
4
doc/grammar.txt
Normal file → Executable file
4
doc/grammar.txt
Normal file → Executable file
|
|
@ -135,10 +135,10 @@ fromStmt ::= 'from' filename 'import' symbol (comma symbol)*
|
|||
|
||||
pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}')
|
||||
|
||||
param ::= symbol (comma symbol)* ':' typeDesc
|
||||
param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr)
|
||||
paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc]
|
||||
|
||||
genericParam ::= symbol [':' typeDesc]
|
||||
genericParam ::= symbol [':' typeDesc] ['=' expr]
|
||||
genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']'
|
||||
|
||||
procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma]
|
||||
|
|
|
|||
129
doc/intern.txt
Normal file → Executable file
129
doc/intern.txt
Normal file → Executable file
|
|
@ -17,7 +17,7 @@ The Nimrod project's directory structure is:
|
|||
============ ==============================================
|
||||
Path Purpose
|
||||
============ ==============================================
|
||||
``bin`` binary files go into here
|
||||
``bin`` generated binary files
|
||||
``build`` generated C code for the installation
|
||||
``nim`` Pascal sources of the Nimrod compiler; this
|
||||
should be modified, not the Nimrod version in
|
||||
|
|
@ -26,16 +26,16 @@ Path Purpose
|
|||
automatically generated from the Pascal
|
||||
version
|
||||
``data`` data files that are used for generating source
|
||||
code go into here
|
||||
code
|
||||
``doc`` the documentation lives here; it is a bunch of
|
||||
reStructuredText files
|
||||
``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
|
||||
on it!
|
||||
``web`` website of Nimrod; generated by ``koch.py``
|
||||
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]
|
||||
|
||||
|
||||
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
|
||||
==================
|
||||
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
|
||||
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.
|
||||
Look at the file ``lib/hti.nim`` for more information.
|
||||
Look at the file ``lib/system/hti.nim`` for more information.
|
||||
|
||||
|
||||
The Garbage Collector
|
||||
|
|
@ -243,11 +255,8 @@ Consider this example:
|
|||
# r is on the stack
|
||||
setRef(r.left) # here we should update the refcounts!
|
||||
|
||||
Though it would be possible to produce code updating the refcounts (if
|
||||
necessary) before and after the call to ``setRef``, it is a complex task to
|
||||
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:
|
||||
We have to decide at runtime whether the reference is on the stack or not.
|
||||
The generated code looks roughly like this:
|
||||
|
||||
.. code-block:: C
|
||||
void setref(TNode** ref) {
|
||||
|
|
@ -260,13 +269,7 @@ roughly like this:
|
|||
|
||||
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
|
||||
comparisons). Another advantage of this scheme is that the code produced is
|
||||
smaller.
|
||||
|
||||
|
||||
The algorithm in pseudo-code
|
||||
----------------------------
|
||||
To be written.
|
||||
comparisons).
|
||||
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
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
2
doc/lib.txt
Normal file → Executable file
|
|
@ -134,7 +134,7 @@ Impure libraries
|
|||
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.
|
||||
|
||||
* `posix <posix.html>`_
|
||||
|
|
|
|||
363
doc/manual.txt
Normal file → Executable file
363
doc/manual.txt
Normal file → Executable file
|
|
@ -8,6 +8,10 @@ Nimrod Manual
|
|||
.. 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
|
||||
===================
|
||||
|
||||
|
|
@ -171,10 +175,10 @@ preferred. Another advantage is that it frees the programmer from remembering
|
|||
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:\ :
|
||||
|
||||
================== ===================================================
|
||||
|
|
@ -202,12 +206,21 @@ contain the following `escape sequences`:idx:\ :
|
|||
|
||||
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
|
||||
interpret any escape sequences.
|
||||
For convenience, when the opening ``"""`` is immediately followed by a newline,
|
||||
the newline is not included in the string.
|
||||
|
||||
|
||||
Raw string literals
|
||||
-------------------
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -501,7 +529,7 @@ designed for this.
|
|||
Another reason is that Nimrod can support ``array[char, int]`` or
|
||||
``set[char]`` efficiently as many algorithms rely on this feature. The
|
||||
`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
|
||||
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
|
||||
type
|
||||
|
|
@ -764,7 +792,7 @@ basetype can only be an ordinal type. The reason is that sets are implemented
|
|||
as high performance bit vectors.
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
|
@ -903,9 +931,8 @@ each other:
|
|||
|
||||
`closure`:idx:
|
||||
indicates that the procedure expects a context, a closure that needs
|
||||
to be passed to the procedure. The implementation is the
|
||||
same as ``cdecl``, but with a hidden pointer parameter (the
|
||||
*closure*). The hidden parameter is always the last one.
|
||||
to be passed to the procedure. The calling convention ``nimcall`` is
|
||||
compatible to ``closure``.
|
||||
|
||||
`syscall`:idx:
|
||||
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
|
||||
use the C compiler's default calling convention. This is needed because
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
--------------
|
||||
|
||||
|
|
@ -956,7 +1080,7 @@ algorithm determines type equality:
|
|||
for i in 0..a.tupleLen-1:
|
||||
if not typeEqualsAux(a[i], b[i], s): return false
|
||||
result = true
|
||||
of object, enum, abstract:
|
||||
of object, enum, distinct:
|
||||
result = a == b
|
||||
of proc:
|
||||
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
|
||||
|
|
@ -973,7 +1097,7 @@ auxiliary set ``s`` to detect this case.
|
|||
|
||||
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``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
|
@ -987,27 +1111,70 @@ relation is extended to the types ``var``, ``ref``, ``ptr``:
|
|||
of var, ref, ptr:
|
||||
result = isSubtype(a.baseType, b.baseType)
|
||||
|
||||
XXX nil is a special value!
|
||||
.. XXX nil is a special value!
|
||||
|
||||
|
||||
Convertible relation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
A type ``a`` is convertible to type ``b`` iff the following algorithm returns
|
||||
true:
|
||||
A type ``a`` is **implicitely** convertible to type ``b`` iff the following
|
||||
algorithm returns true:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isConvertible(a, b: PType): bool =
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of proc:
|
||||
# XXX range types?
|
||||
proc isImplicitelyConvertible(a, b: PType): bool =
|
||||
case a.kind
|
||||
of proc:
|
||||
if b.kind == proc:
|
||||
var x = a.parameterTuple
|
||||
var y = b.parameterTuple
|
||||
if x.tupleLen == y.tupleLen:
|
||||
for i in 0.. x.tupleLen-1:
|
||||
if not isSubtype(x[i], y[i]): return false
|
||||
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
|
||||
|
|
@ -1095,7 +1262,7 @@ Type default value
|
|||
============================ ==============================================
|
||||
any integer type 0
|
||||
any float 0.0
|
||||
char '\0'
|
||||
char '\\0'
|
||||
bool false
|
||||
ref or pointer 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
|
||||
given, control just passes after the ``case`` statement.
|
||||
|
||||
To suppress the static error in the ordinal case the programmer needs
|
||||
to write an ``else`` part with a ``nil`` statement.
|
||||
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
|
||||
statement can be used.
|
||||
|
||||
|
||||
When statement
|
||||
|
|
@ -1271,7 +1438,7 @@ Example:
|
|||
# and tries to add them
|
||||
var
|
||||
f: TFile
|
||||
if openFile(f, "numbers.txt"):
|
||||
if open(f, "numbers.txt"):
|
||||
try:
|
||||
var a = readLine(f)
|
||||
var b = readLine(f)
|
||||
|
|
@ -1285,7 +1452,7 @@ Example:
|
|||
except:
|
||||
echo("Unknown exception!")
|
||||
finally:
|
||||
closeFile(f)
|
||||
close(f)
|
||||
|
||||
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
|
||||
|
|
@ -1417,7 +1584,7 @@ Example:
|
|||
|
||||
The `while`:idx: statement is executed until the ``expr`` evaluates to false.
|
||||
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
|
||||
|
|
@ -1562,8 +1729,9 @@ type `var`).
|
|||
return intToStr(x)
|
||||
|
||||
Operators with one parameter are prefix operators, operators with two
|
||||
parameters are infix operators. There is no way to declare postfix
|
||||
operators: All postfix operators are built-in and handled by the
|
||||
parameters are infix operators. (However, the parser distinguishes these from
|
||||
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.
|
||||
|
||||
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.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
|
||||
var (x, y) = divmod(8, 5) # tuple unpacking
|
||||
assert x == 1
|
||||
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
|
||||
|
|
@ -1655,7 +1818,7 @@ Syntax::
|
|||
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``
|
||||
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
|
||||
end of the loop body. The iteration variables' types are inferred by the
|
||||
return type of the iterator.
|
||||
|
|
@ -1737,8 +1900,6 @@ possible within a single ``type`` section.
|
|||
Generics
|
||||
~~~~~~~~
|
||||
|
||||
`Version 0.7.10: Generic types like in the example do not work.`:red:
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
|
@ -1778,11 +1939,9 @@ Example:
|
|||
# inorder traversal of a binary tree
|
||||
# recursive iterators are not yet implemented, so this does not work in
|
||||
# the current compiler!
|
||||
if root.le != nil:
|
||||
yield inorder(root.le)
|
||||
if root.le != nil: yield inorder(root.le)
|
||||
yield root.data
|
||||
if root.ri != nil:
|
||||
yield inorder(root.ri)
|
||||
if root.ri != nil: yield inorder(root.ri)
|
||||
|
||||
var
|
||||
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
|
||||
~~~~~~~~~
|
||||
|
||||
A `template`:idx: is a simple form of a macro. It operates on parse trees and is
|
||||
processed in the semantic pass of the compiler. So 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 to understand and maintain. So one ought
|
||||
to use them sparingly. The usage of ordinary procs, iterators or generics is
|
||||
preferred to the usage of templates.
|
||||
A `template`:idx: is a simple form of a macro: It is a simple substitution
|
||||
mechanism that operates on Nimrod's abstract syntax trees. It is processed in
|
||||
the semantic pass of the compiler.
|
||||
|
||||
The syntax to *invoke* a template is the same as calling a procedure.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -1815,20 +1973,86 @@ Example:
|
|||
|
||||
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`:idx: are the most powerful feature of Nimrod. They can be used
|
||||
to implement `domain specific languages`:idx:. But they may lead to code
|
||||
that is harder to understand and maintain. So one ought to use them sparingly.
|
||||
to implement `domain specific languages`:idx:.
|
||||
|
||||
While macros enable advanced compile-time code tranformations, they
|
||||
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||
Nimrod's syntax is flexible enough anyway.
|
||||
|
||||
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:
|
||||
(1) invoking a macro like a procedure call (`expression macros`)
|
||||
|
|
@ -1847,7 +2071,7 @@ variable number of arguments:
|
|||
import macros
|
||||
|
||||
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:
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
# iterate over any argument that is passed to this macro:
|
||||
|
|
@ -1948,6 +2172,7 @@ This is best illustrated by an example:
|
|||
main()
|
||||
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module B
|
||||
import A # A is not parsed here! Only the already known symbols
|
||||
# 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
|
||||
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.
|
||||
* In all descendent types of the object type.
|
||||
|
||||
|
|
@ -2000,9 +2225,11 @@ iterator in which case the overloading resolution takes place:
|
|||
# Module A
|
||||
var x*: string
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module B
|
||||
var x*: int
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module C
|
||||
import A, B
|
||||
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.
|
||||
|
||||
|
||||
define pragma
|
||||
-------------
|
||||
The `define`:idx: pragma defines a conditional symbol. This symbol may only be
|
||||
used in other pragmas and in the ``defined`` expression and not in ordinary
|
||||
Nimrod source code. The conditional symbols go into a special symbol table.
|
||||
The compiler defines the target processor and the target operating
|
||||
system as conditional symbols.
|
||||
|
||||
Warning: The ``define`` pragma is deprecated as it conflicts with separate
|
||||
compilation! One should use boolean constants as a replacement - this is
|
||||
cleaner anyway.
|
||||
noSideEffect pragma
|
||||
-------------------
|
||||
The `noSideEffect`:idx: pragma is used to mark a proc/iterator to have no side
|
||||
effects. This means that the proc/iterator only changes locations that are
|
||||
reachable from its parameters and the return value only depends on the
|
||||
arguments. If none of its parameters have the type ``var T``
|
||||
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
|
||||
verify this.
|
||||
|
||||
|
||||
undef pragma
|
||||
------------
|
||||
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a
|
||||
conditional symbol.
|
||||
|
||||
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
|
||||
compilation!
|
||||
compileTime pragma
|
||||
------------------
|
||||
The `compileTime`:idx: pragma is used to mark a proc to be used at compile
|
||||
time only. No code will be generated for it. Compile time procs are useful
|
||||
as helpers for macros.
|
||||
|
||||
|
||||
error pragma
|
||||
|
|
|
|||
0
doc/mytest.cfg
Normal file → Executable file
0
doc/mytest.cfg
Normal file → Executable file
0
doc/nimdoc.css
Normal file → Executable file
0
doc/nimdoc.css
Normal file → Executable file
65
doc/nimrodc.txt
Normal file → Executable file
65
doc/nimrodc.txt
Normal file → Executable 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.}
|
||||
|
||||
In general, importing a dynamic library does not require any special linker
|
||||
options or linking with import libraries. This also
|
||||
implies that no *devel* packages need to be installed.
|
||||
options or linking with import libraries. This also implies that no *devel*
|
||||
packages need to be installed.
|
||||
|
||||
|
||||
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
|
||||
5. do low-level optimizations
|
||||
|
||||
This section can only help you with the last item. Note that rewriting parts
|
||||
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.
|
||||
This section can only help you with the last item.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since
|
||||
it is the proper term.
|
||||
|
||||
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 just generates a long ``.js`` file.
|
||||
|
||||
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.)
|
||||
* file management (``openfile``, etc.)
|
||||
* most modules of the Standard library
|
||||
* 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
|
||||
for the ECMAScript platform.
|
||||
..
|
||||
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: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
|
||||
since it is the proper term.
|
||||
|
||||
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 just generates a long ``.js`` file.
|
||||
|
||||
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.)
|
||||
* file management
|
||||
* most modules of the Standard library
|
||||
* 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 for the ECMAScript platform.
|
||||
|
|
|
|||
0
doc/overview.txt
Normal file → Executable file
0
doc/overview.txt
Normal file → Executable file
0
doc/readme.txt
Normal file → Executable file
0
doc/readme.txt
Normal file → Executable file
0
doc/regexprs.txt
Normal file → Executable file
0
doc/regexprs.txt
Normal file → Executable file
0
doc/rst.txt
Normal file → Executable file
0
doc/rst.txt
Normal file → Executable 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
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
0
doc/tut1.txt
Normal file → Executable file
46
doc/tut2.txt
Normal file → Executable file
46
doc/tut2.txt
Normal file → Executable file
|
|
@ -311,11 +311,10 @@ class provides a constructor, etc.
|
|||
c.draw()
|
||||
|
||||
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
|
||||
slightly more inconvienent than in traditional OOP-languages, but has the
|
||||
advantage of being much more flexible (and somewhat faster). The above approach
|
||||
also allows some form *monkey patching* by modifying the ``fdraw`` field.
|
||||
|
||||
the dynamic dispatch happens with the help of the ``fdraw`` field. Even though
|
||||
this solution has its advantages compared to traditional OOP-languages, it is
|
||||
a **preliminary** solution. Multimethods are a planned language feature that
|
||||
provide a more flexible and efficient mechanism.
|
||||
|
||||
|
||||
Exceptions
|
||||
|
|
@ -323,15 +322,13 @@ Exceptions
|
|||
|
||||
In Nimrod `exceptions`:idx: are objects. By convention, exception types are
|
||||
prefixed with an 'E', not 'T'. The ``system`` module defines an exception
|
||||
hierarchy that you should stick to. Reusing an existing exception type is
|
||||
often better than defining a new exception type: It avoids a proliferation of
|
||||
types.
|
||||
hierarchy that you might want to stick to.
|
||||
|
||||
Exceptions should be allocated on the heap because their lifetime is unknown.
|
||||
|
||||
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
|
||||
since this is quite common (the file may have been deleted).
|
||||
For example, if a file cannot be opened, this should not raise an
|
||||
exception since this is quite common (the file may not exist).
|
||||
|
||||
|
||||
Raise statement
|
||||
|
|
@ -359,7 +356,7 @@ The `try`:idx: statement handles exceptions:
|
|||
# and tries to add them
|
||||
var
|
||||
f: TFile
|
||||
if openFile(f, "numbers.txt"):
|
||||
if open(f, "numbers.txt"):
|
||||
try:
|
||||
var a = readLine(f)
|
||||
var b = readLine(f)
|
||||
|
|
@ -375,7 +372,7 @@ The `try`:idx: statement handles exceptions:
|
|||
# reraise the unknown exception:
|
||||
raise
|
||||
finally:
|
||||
closeFile(f)
|
||||
close(f)
|
||||
|
||||
The statements after the ``try`` are executed unless an exception is
|
||||
raised. Then the appropriate ``except`` part is executed.
|
||||
|
|
@ -396,8 +393,6 @@ is not executed (if an exception occurs).
|
|||
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
|
||||
with `type parameters`:idx:. They are most useful for efficient type safe
|
||||
containers:
|
||||
|
|
@ -448,7 +443,7 @@ containers:
|
|||
while stack.len > 0:
|
||||
var n = stack.pop()
|
||||
while n != nil:
|
||||
yield n
|
||||
yield n.data
|
||||
add(stack, n.ri) # push right subtree onto the stack
|
||||
n = n.le # and follow the left pointer
|
||||
|
||||
|
|
@ -472,8 +467,7 @@ Templates
|
|||
Templates are a simple substitution mechanism that operates on Nimrod's
|
||||
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
|
||||
of C's preprocessor macros flaws. However, they may lead to code that is harder
|
||||
to understand and maintain. So one should use them sparingly.
|
||||
of C's preprocessor macros flaws.
|
||||
|
||||
To *invoke* a template, call it like a procedure.
|
||||
|
||||
|
|
@ -488,7 +482,8 @@ Example:
|
|||
|
||||
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
|
||||
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 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
|
||||
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
|
||||
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*),
|
||||
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
||||
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
|
||||
use a ``block`` statement:
|
||||
|
|
@ -557,7 +552,8 @@ via a special ``:`` syntax:
|
|||
|
||||
.. code-block:: nimrod
|
||||
|
||||
template withFile(f, filename, mode: expr, actions: stmt): stmt =
|
||||
template withFile(f: expr, filename: string, mode: TFileMode,
|
||||
actions: stmt): stmt =
|
||||
block:
|
||||
var fn = filename
|
||||
var f: TFile
|
||||
|
|
@ -583,11 +579,6 @@ once.
|
|||
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
|
||||
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||
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:
|
||||
(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
|
||||
|
|
|
|||
0
dos2unix.py
Normal file → Executable file
0
dos2unix.py
Normal file → Executable file
0
examples/hallo.nim
Normal file → Executable file
0
examples/hallo.nim
Normal file → Executable file
0
examples/htmlrefs.nim
Normal file → Executable file
0
examples/htmlrefs.nim
Normal file → Executable file
0
examples/htmltitle.nim
Normal file → Executable file
0
examples/htmltitle.nim
Normal file → Executable file
0
examples/keyval.nim
Normal file → Executable file
0
examples/keyval.nim
Normal file → Executable file
0
examples/luaex.nim
Normal file → Executable file
0
examples/luaex.nim
Normal file → Executable file
2
examples/maximum.nim
Normal file → Executable file
2
examples/maximum.nim
Normal file → Executable file
|
|
@ -3,4 +3,4 @@
|
|||
import strutils
|
||||
|
||||
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
0
examples/myfile.txt
Normal file → Executable file
0
examples/pythonex.nim
Normal file → Executable file
0
examples/pythonex.nim
Normal file → Executable file
0
examples/readme.txt
Normal file → Executable file
0
examples/readme.txt
Normal file → Executable file
0
examples/statcsv.nim
Normal file → Executable file
0
examples/statcsv.nim
Normal file → Executable file
0
examples/tclex.nim
Normal file → Executable file
0
examples/tclex.nim
Normal file → Executable file
0
gcccpuopt.sh
Normal file → Executable file
0
gcccpuopt.sh
Normal file → Executable file
0
gpl.html
Normal file → Executable file
0
gpl.html
Normal file → Executable file
0
ide/config.nim
Normal file → Executable file
0
ide/config.nim
Normal file → Executable file
0
ide/main.nim
Normal file → Executable file
0
ide/main.nim
Normal file → Executable file
0
ide/nimide.glade
Normal file → Executable file
0
ide/nimide.glade
Normal file → Executable file
0
ide/nimide.gladep
Normal file → Executable file
0
ide/nimide.gladep
Normal file → Executable file
0
ide/nimide.nim
Normal file → Executable file
0
ide/nimide.nim
Normal file → Executable file
7
install.txt
Normal file → Executable file
7
install.txt
Normal file → Executable file
|
|
@ -5,9 +5,6 @@ Installation
|
|||
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
|
||||
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
|
||||
|
|
@ -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
|
||||
|
||||
From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are
|
||||
provided for distributing the files over the UNIX hierarchy. However, this
|
||||
makes updating your Nimrod installation more cumbersome.
|
||||
provided for distributing the files over the UNIX hierarchy. However,
|
||||
updating your Nimrod installation is more cumbersome then.
|
||||
|
||||
|
||||
Installation on the Macintosh
|
||||
|
|
|
|||
33
koch.py
Normal file → Executable file
33
koch.py
Normal file → Executable file
|
|
@ -12,16 +12,17 @@ from pycompab import *
|
|||
|
||||
# --------------------- constants ----------------------------------------
|
||||
|
||||
NIMROD_VERSION = '0.7.10'
|
||||
NIMROD_VERSION = '0.8.1'
|
||||
# This string contains Nimrod's version. It is the only place
|
||||
# where the version needs to be updated. The rest is done by
|
||||
# the build process automatically. It is replaced **everywhere**!
|
||||
# Format is: Major.Minor.Patch
|
||||
# Major part: plan is to use number 1 for the first version that is stable;
|
||||
# higher versions may be incompatible with previous versions
|
||||
# Minor part: incremented if new features are added (but is completely
|
||||
# backwards-compatible)
|
||||
# Patch level: is increased for every patch
|
||||
# Minor part: incremented if new features are added; unfortunately often
|
||||
# not backwards-compatible
|
||||
# Patch level: is increased for every patch; should be completely
|
||||
# backwards-compatible
|
||||
|
||||
EXPLAIN = true
|
||||
force = false
|
||||
|
|
@ -209,14 +210,15 @@ def Glob(pattern): # needed because glob.glob() is buggy on Windows 95:
|
|||
global _baseDir
|
||||
(head, tail) = os.path.split(Path(pattern))
|
||||
result = []
|
||||
try:
|
||||
os.chdir(os.path.join(_baseDir, head))
|
||||
if os.path.exists(head):
|
||||
try:
|
||||
for f in glob.glob(tail): result.append(os.path.join(head, f))
|
||||
except OSError:
|
||||
result = []
|
||||
finally:
|
||||
os.chdir(_baseDir)
|
||||
os.chdir(os.path.join(_baseDir, head))
|
||||
try:
|
||||
for f in glob.glob(tail): result.append(os.path.join(head, f))
|
||||
except OSError:
|
||||
result = []
|
||||
finally:
|
||||
os.chdir(_baseDir)
|
||||
return result
|
||||
|
||||
def FilenameNoExt(f):
|
||||
|
|
@ -384,10 +386,10 @@ Possible Commands:
|
|||
boot [options] bootstraps with given command line options
|
||||
rodsrc generates Nimrod version from Pascal version
|
||||
web generates the website
|
||||
profile profile the Nimrod compiler
|
||||
csource [options] build the C sources for installation
|
||||
zip build the installation ZIP package
|
||||
inno build the Inno Setup installer
|
||||
profile profiles the Nimrod compiler
|
||||
csource [options] builds the C sources for installation
|
||||
zip builds the installation ZIP package
|
||||
inno builds the Inno Setup installer
|
||||
""", NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
|
||||
|
||||
def main(args):
|
||||
|
|
@ -634,7 +636,6 @@ def getOSandProcessor():
|
|||
return (host, processor)
|
||||
|
||||
def writePlatdefC(nimrodpath):
|
||||
import os
|
||||
host, processor = getOSandProcessor()
|
||||
f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+")
|
||||
f.write(Subs('/* Generated by koch.py */\n'
|
||||
|
|
|
|||
0
lib/copying.txt
Normal file → Executable file
0
lib/copying.txt
Normal file → Executable file
0
lib/cycle.h
Normal file → Executable file
0
lib/cycle.h
Normal file → Executable file
0
lib/ecmas/dom.nim
Normal file → Executable file
0
lib/ecmas/dom.nim
Normal file → Executable file
0
lib/impure/dialogs.nim
Normal file → Executable file
0
lib/impure/dialogs.nim
Normal file → Executable file
0
lib/impure/web.nim
Normal file → Executable file
0
lib/impure/web.nim
Normal file → Executable file
0
lib/impure/zipfiles.nim
Normal file → Executable file
0
lib/impure/zipfiles.nim
Normal file → Executable file
0
lib/lgpl.txt
Normal file → Executable file
0
lib/lgpl.txt
Normal file → Executable file
0
lib/nimbase.h
Normal file → Executable file
0
lib/nimbase.h
Normal file → Executable file
0
lib/posix/posix.nim
Normal file → Executable file
0
lib/posix/posix.nim
Normal file → Executable file
0
lib/pure/cgi.nim
Normal file → Executable file
0
lib/pure/cgi.nim
Normal file → Executable file
0
lib/pure/complex.nim
Normal file → Executable file
0
lib/pure/complex.nim
Normal file → Executable file
0
lib/pure/dynlib.nim
Normal file → Executable file
0
lib/pure/dynlib.nim
Normal file → Executable file
0
lib/pure/hashes.nim
Normal file → Executable file
0
lib/pure/hashes.nim
Normal file → Executable file
0
lib/pure/lexbase.nim
Normal file → Executable file
0
lib/pure/lexbase.nim
Normal file → Executable file
104
lib/pure/macros.nim
Normal file → Executable file
104
lib/pure/macros.nim
Normal file → Executable 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.
|
||||
|
||||
## .. include:: ../doc/astspec.txt
|
||||
|
||||
## .. include:: ../doc/astspec.txt
|
||||
|
||||
#[[[cog
|
||||
#def toEnum(name, elems):
|
||||
|
|
@ -39,38 +39,38 @@ type
|
|||
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
|
||||
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
|
||||
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
|
||||
nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall,
|
||||
nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple,
|
||||
nnkInfix, nnkPrefix, nnkPostfix, nnkPar,
|
||||
nnkCurly, nnkBracket, nnkBracketExpr, nnkPragmaExpr,
|
||||
nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr,
|
||||
nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda,
|
||||
nnkAccQuoted, nnkTableConstr, nnkQualified, nnkBind,
|
||||
nnkSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv,
|
||||
nnkConv, nnkCast, nnkAddr, nnkHiddenAddr,
|
||||
nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF,
|
||||
nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString,
|
||||
nnkPassAsOpenArray, nnkAsgn, nnkFastAsgn, nnkDefaultTypeParam,
|
||||
nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkModule,
|
||||
nnkProcDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef,
|
||||
nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch,
|
||||
nnkElse, nnkMacroStmt, nnkAsmStmt, nnkPragma,
|
||||
nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkWhileStmt,
|
||||
nnkCaseStmt, nnkVarSection, nnkConstSection, nnkConstDef,
|
||||
nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkTryStmt,
|
||||
nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt,
|
||||
nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkStmtList,
|
||||
nnkImportStmt, nnkFromStmt, nnkImportAs, nnkIncludeStmt,
|
||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType,
|
||||
nnkBlockType, nnkVm, nnkTypeOfExpr, nnkObjectTy,
|
||||
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
|
||||
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
|
||||
nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
|
||||
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
||||
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
|
||||
nnkTableConstr, nnkQualified, nnkBind, nnkSymChoice,
|
||||
nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv,
|
||||
nnkCast, nnkAddr, nnkHiddenAddr, nnkHiddenDeref,
|
||||
nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64,
|
||||
nnkChckRange, nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray,
|
||||
nnkAsgn, nnkFastAsgn, nnkGenericParams, nnkFormalParams,
|
||||
nnkOfInherit, nnkModule, nnkProcDef, nnkConverterDef,
|
||||
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
||||
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
|
||||
nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt,
|
||||
nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection,
|
||||
nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef,
|
||||
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
|
||||
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
|
||||
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
|
||||
nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
||||
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
|
||||
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
||||
nnkRefTy, nnkPtrTy, nnkVarTy, nnkAbstractTy,
|
||||
nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy,
|
||||
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
||||
TNimNodeKinds* = set[TNimrodNodeKind]
|
||||
TNimrodTypeKind* = enum
|
||||
ntyNone, ntyBool, ntyChar, ntyEmpty,
|
||||
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
|
||||
ntyGenericParam, ntyAbstract, ntyEnum, ntyOrdinal,
|
||||
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
|
||||
ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
|
||||
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
|
||||
ntyArray, ntyObject, ntyTuple, ntySet,
|
||||
ntyRange, ntyPtr, ntyRef, ntyVar,
|
||||
ntySequence, ntyProc, ntyPointer, ntyOpenArray,
|
||||
|
|
@ -79,8 +79,8 @@ type
|
|||
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
|
||||
TNimTypeKinds* = set[TNimrodTypeKind]
|
||||
TNimrodSymKind* = enum
|
||||
nskUnknownSym, nskConditional, nskDynLib, nskParam,
|
||||
nskTypeParam, nskTemp, nskType, nskConst,
|
||||
nskUnknown, nskConditional, nskDynLib, nskParam,
|
||||
nskGenericParam, nskTemp, nskType, nskConst,
|
||||
nskVar, nskProc, nskIterator, nskConverter,
|
||||
nskMacro, nskTemplate, nskField, nskEnumField,
|
||||
nskForVar, nskModule, nskLabel, nskStub
|
||||
|
|
@ -91,7 +91,6 @@ type
|
|||
TNimrodIdent = object of TObject
|
||||
## represents a Nimrod identifier in the AST
|
||||
|
||||
TNimrodNode {.final.} = object # hidden
|
||||
TNimrodSymbol {.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
|
||||
## *ident*.
|
||||
|
||||
PNimrodNode* {.compilerproc.} = ref TNimrodNode
|
||||
PNimrodNode* = expr
|
||||
## 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!
|
||||
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
|
||||
# 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".}
|
||||
## 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`
|
||||
|
||||
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 newNimNode*(kind: TNimrodNodeKind,
|
||||
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
||||
|
||||
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
||||
|
||||
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
|
||||
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
|
||||
|
||||
|
|
@ -192,11 +188,11 @@ proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
|
|||
## creates an identifier node from `i`
|
||||
result = newNimNode(nnkIdent)
|
||||
result.ident = i
|
||||
|
||||
|
||||
proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
|
||||
## creates an identifier node from `i`
|
||||
result = newNimNode(nnkIdent)
|
||||
result.ident = !i
|
||||
result.ident = !i
|
||||
|
||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## converts the AST `n` to the concrete Nimrod code and wraps that
|
||||
|
|
@ -227,7 +223,7 @@ proc newCall*(theProc: TNimrodIdent,
|
|||
## the arguments ``args[0..]``.
|
||||
result = newNimNode(nnkCall)
|
||||
result.add(newIdentNode(theProc))
|
||||
result.add(args)
|
||||
result.add(args)
|
||||
|
||||
proc newCall*(theProc: string,
|
||||
args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
|
||||
|
|
@ -236,14 +232,14 @@ proc newCall*(theProc: string,
|
|||
result = newNimNode(nnkCall)
|
||||
result.add(newIdentNode(theProc))
|
||||
result.add(args)
|
||||
|
||||
proc nestList*(theProc: TNimrodIdent,
|
||||
x: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## nests the list `x` into a tree of call expressions:
|
||||
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
|
||||
var L = x.len
|
||||
result = newCall(theProc, x[L-2], x[L-1])
|
||||
var a = result
|
||||
for i in countdown(L-3, 0):
|
||||
a = newCall(theProc, x[i], copyNimTree(a))
|
||||
|
||||
|
||||
proc nestList*(theProc: TNimrodIdent,
|
||||
x: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## nests the list `x` into a tree of call expressions:
|
||||
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
|
||||
var L = x.len
|
||||
result = newCall(theProc, x[L-2], x[L-1])
|
||||
var a = result
|
||||
for i in countdown(L-3, 0):
|
||||
a = newCall(theProc, x[i], copyNimTree(a))
|
||||
|
||||
|
|
|
|||
10
lib/pure/math.nim
Normal file → Executable file
10
lib/pure/math.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -83,10 +83,12 @@ proc nextPowerOfTwo*(x: int): int =
|
|||
result = result or (result shr 1)
|
||||
Inc(result)
|
||||
|
||||
proc countBits*(n: int32): int {.noSideEffect.}
|
||||
proc countBits32*(n: int32): int {.noSideEffect.} =
|
||||
## counts the set bits in `n`.
|
||||
|
||||
include "system/cntbits"
|
||||
var v = n
|
||||
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.} =
|
||||
## computes the sum of the elements in `x`.
|
||||
|
|
|
|||
0
lib/pure/md5.nim
Normal file → Executable file
0
lib/pure/md5.nim
Normal file → Executable file
16
lib/pure/os.nim
Normal file → Executable file
16
lib/pure/os.nim
Normal file → Executable file
|
|
@ -58,10 +58,6 @@ when defined(Nimdoc): # only for proper documentation:
|
|||
## The character used by the operating system to separate pathname
|
||||
## components, for example, '/' for POSIX or ':' for the classic
|
||||
## 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* = '/'
|
||||
## An alternative character used by the operating system to separate
|
||||
|
|
@ -80,10 +76,10 @@ when defined(Nimdoc): # only for proper documentation:
|
|||
|
||||
ExeExt* = ""
|
||||
## The file extension of native executables. For example:
|
||||
## "" on UNIX, "exe" on Windows.
|
||||
## "" for POSIX, "exe" on Windows.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
# volume.
|
||||
# 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.
|
||||
# Two colons "::" are the relative path to the parent. Three is to the
|
||||
# grandparent etc.
|
||||
|
|
@ -551,7 +547,7 @@ proc sameFile*(path1, path2: string): bool =
|
|||
|
||||
proc sameFileContent*(path1, path2: string): bool =
|
||||
## Returns True if both pathname arguments refer to files with identical
|
||||
## content. Content is compared byte for byte.
|
||||
## binary content.
|
||||
const
|
||||
bufSize = 8192 # 8K buffer
|
||||
var
|
||||
|
|
@ -712,7 +708,7 @@ proc putEnv*(key, val: string) =
|
|||
OSError()
|
||||
|
||||
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.
|
||||
getEnvVarsC()
|
||||
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
|
||||
## `dir`. The component type and full path for each item is returned.
|
||||
## Walking is not recursive.
|
||||
## Example: Assuming this directory structure::
|
||||
## Example: This directory structure::
|
||||
## dirA / dirB / fileB1.txt
|
||||
## / dirC
|
||||
## / fileA1.txt
|
||||
|
|
|
|||
0
lib/pure/osproc.nim
Normal file → Executable file
0
lib/pure/osproc.nim
Normal file → Executable file
0
lib/pure/parsecfg.nim
Normal file → Executable file
0
lib/pure/parsecfg.nim
Normal file → Executable file
0
lib/pure/parsecsv.nim
Normal file → Executable file
0
lib/pure/parsecsv.nim
Normal file → Executable file
0
lib/pure/parseopt.nim
Normal file → Executable file
0
lib/pure/parseopt.nim
Normal file → Executable file
1
lib/pure/parsesql.nim
Normal file → Executable file
1
lib/pure/parsesql.nim
Normal file → Executable file
|
|
@ -571,6 +571,7 @@ proc getTok(p: var TSqlParser) =
|
|||
|
||||
proc sqlError(p: TSqlParser, msg: string) =
|
||||
var e: ref EInvalidSql
|
||||
new(e)
|
||||
e.msg = errorStr(p, msg)
|
||||
raise e
|
||||
|
||||
|
|
|
|||
0
lib/pure/parsexml.nim
Normal file → Executable file
0
lib/pure/parsexml.nim
Normal file → Executable file
2
lib/pure/regexprs.nim
Normal file → Executable file
2
lib/pure/regexprs.nim
Normal file → Executable file
|
|
@ -54,10 +54,10 @@ proc find*(s, pattern: string, matches: var openarray[string],
|
|||
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
|
||||
## substrings in the array ``matches``. If it does not match, nothing
|
||||
## is written into ``matches``.
|
||||
|
||||
proc find*(s, pattern: string, start: int = 0): bool
|
||||
## returns ``true`` if ``pattern`` occurs in ``s``.
|
||||
|
||||
|
||||
proc rawCompile(pattern: string, flags: cint): PPcre =
|
||||
var
|
||||
msg: CString
|
||||
|
|
|
|||
4
lib/pure/streams.nim
Normal file → Executable file
4
lib/pure/streams.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -42,7 +42,7 @@ proc write*(s: PStream, x: string) =
|
|||
s.writeData(s, cstring(x), x.len)
|
||||
|
||||
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):
|
||||
raise newEIO("cannot read from stream")
|
||||
|
||||
|
|
|
|||
0
lib/pure/strtabs.nim
Normal file → Executable file
0
lib/pure/strtabs.nim
Normal file → Executable file
73
lib/pure/strutils.nim
Normal file → Executable file
73
lib/pure/strutils.nim
Normal file → Executable file
|
|
@ -27,7 +27,7 @@ template newException(exceptn, message: expr): expr =
|
|||
|
||||
|
||||
type
|
||||
TCharSet* = set[char] # for compability for Nim
|
||||
TCharSet* = set[char] # for compability with Nim
|
||||
|
||||
const
|
||||
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
||||
|
|
@ -45,9 +45,9 @@ const
|
|||
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
|
||||
## the set of characters an identifier can start with
|
||||
|
||||
strStart* = 0 # this is only for bootstraping
|
||||
# XXX: remove this someday
|
||||
nl* = "\n" # this is only for bootstraping XXX: remove this somehow
|
||||
strStart* = 0 ## this is only for bootstraping
|
||||
## XXX: remove this someday
|
||||
nl* = "\n" ## this is only for bootstraping XXX: remove this somehow
|
||||
|
||||
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
||||
## The `substitution`:idx: operator performs string substitutions in
|
||||
|
|
@ -64,8 +64,13 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
|||
## .. code-block:: nimrod
|
||||
## "The cat eats fish."
|
||||
##
|
||||
## The substitution variables (the thing after the ``$``)
|
||||
## are enumerated from 1 to 9.
|
||||
## The substitution variables (the thing after the ``$``) are enumerated
|
||||
## 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
|
||||
## ``[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.
|
||||
|
|
@ -267,19 +272,43 @@ iterator splitLines*(s: string): string =
|
|||
else: break # was '\0'
|
||||
first = last
|
||||
|
||||
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect.} =
|
||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||
template iterToProc(iter: expr): stmt =
|
||||
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] {.
|
||||
noSideEffect.}
|
||||
noSideEffect, deprecated.} =
|
||||
## 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.
|
||||
result = @[]
|
||||
for sub in split(s, sep): add(result, sub)
|
||||
## **Deprecated since version 0.8.0**: Use `split` instead.
|
||||
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.}
|
||||
## 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.}
|
||||
## Converts `x` to its hexadecimal representation. The resulting string
|
||||
## 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
|
||||
## 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 =
|
||||
## returns true iff each character of `s` is in the set `theSet`.
|
||||
for c in items(s):
|
||||
if not (c in theSet): return false
|
||||
if c notin theSet: return false
|
||||
return true
|
||||
|
||||
proc quoteIfContainsWhite*(s: string): string =
|
||||
|
|
@ -397,12 +426,12 @@ proc endsWith(s, suffix: string): bool =
|
|||
when false:
|
||||
proc abbrev(s: string, possibilities: openarray[string]): int =
|
||||
## 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.
|
||||
result = -1 # none found
|
||||
for i in 0..possibilities.len-1:
|
||||
if possibilities[i].startsWith(s):
|
||||
if result >= 0: return -2 # ambigious
|
||||
if result >= 0: return -2 # ambiguous
|
||||
result = i
|
||||
|
||||
proc repeatChar(count: int, c: Char = ' '): string =
|
||||
|
|
@ -509,12 +538,6 @@ proc cmpIgnoreStyle(a, b: string): int =
|
|||
|
||||
{.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 =
|
||||
|
|
@ -732,7 +755,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
|
|||
# one more valid negative than prositive integer. Thus we perform the
|
||||
# computation as a negative number and then change the sign at the end.
|
||||
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
|
||||
if s[i] == '+':
|
||||
inc(i)
|
||||
|
|
@ -758,7 +781,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
|
|||
|
||||
proc parseInt(s: string): int =
|
||||
var
|
||||
index: int = 0
|
||||
index = 0
|
||||
res = rawParseInt(s, index)
|
||||
if index == -1:
|
||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
|
|
|
|||
0
lib/pure/terminal.nim
Normal file → Executable file
0
lib/pure/terminal.nim
Normal file → Executable file
6
lib/pure/times.nim
Normal file → Executable file
6
lib/pure/times.nim
Normal file → Executable file
|
|
@ -25,13 +25,13 @@ type
|
|||
|
||||
when defined(posix):
|
||||
type
|
||||
TTime* = abstract int ## abstract type that represents a time
|
||||
TTime* = distinct int ## distinct type that represents a time
|
||||
elif defined(windows):
|
||||
when defined(vcc):
|
||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
||||
type TTime* = abstract int64
|
||||
type TTime* = distinct int64
|
||||
else:
|
||||
type TTime* = abstract int32
|
||||
type TTime* = distinct int32
|
||||
elif defined(ECMAScript):
|
||||
type
|
||||
TTime* {.final.} = object
|
||||
|
|
|
|||
0
lib/pure/unicode.nim
Normal file → Executable file
0
lib/pure/unicode.nim
Normal file → Executable file
0
lib/pure/xmlgen.nim
Normal file → Executable file
0
lib/pure/xmlgen.nim
Normal file → Executable file
93
lib/system.nim
Normal file → Executable file
93
lib/system.nim
Normal file → Executable file
|
|
@ -42,8 +42,12 @@ type
|
|||
|
||||
type
|
||||
`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
|
||||
## defined. `x` has to be an identifier or a qualified identifier.
|
||||
## 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
|
||||
## # 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:
|
||||
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
|
||||
## 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
|
||||
## 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: int8): int8 {.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.}
|
||||
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
|
||||
## and 0 iff x == y. This is useful for writing generic algorithms without
|
||||
## 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
|
||||
# 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.} =
|
||||
## iterates over each item of `a`.
|
||||
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.} =
|
||||
## iterates over each item of `a`.
|
||||
var i = low(IX)
|
||||
while i <= high(IX):
|
||||
yield a[i]
|
||||
inc(i)
|
||||
if i <= high(IX):
|
||||
while true:
|
||||
yield a[i]
|
||||
if i >= high(IX): break
|
||||
inc(i)
|
||||
|
||||
iterator items*[T](a: seq[T]): T {.inline.} =
|
||||
## 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
|
||||
## able to hold).
|
||||
var i = low(T)
|
||||
while i <= high(T):
|
||||
if i in a: yield i
|
||||
inc(i)
|
||||
if i <= high(T):
|
||||
while true:
|
||||
if i in a: yield i
|
||||
if i >= high(T): break
|
||||
inc(i)
|
||||
|
||||
iterator items*(a: cstring): char {.inline.} =
|
||||
## 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(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)
|
||||
else:
|
||||
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
|
||||
proc seqToPtr[T](x: seq[T]): pointer {.pure, nosideeffect.} =
|
||||
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
|
||||
## the element type `T`.
|
||||
if seqToPtr(x) == seqToPtr(y):
|
||||
|
|
@ -1101,10 +1116,9 @@ when not defined(NimrodVM):
|
|||
if x[i] != y[i]: return false
|
||||
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
|
||||
## appropriate `==` and `items` procs to work.
|
||||
result = 0
|
||||
## appropriate `items` and `==` procs to work.
|
||||
for i in items(a):
|
||||
if i == item: return
|
||||
inc(result)
|
||||
|
|
@ -1437,6 +1451,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
|||
include "system/arithm"
|
||||
{.pop.} # stack trace
|
||||
include "system/dyncalls"
|
||||
include "system/sets"
|
||||
|
||||
const
|
||||
GenericSeqSize = (2 * sizeof(int))
|
||||
|
|
|
|||
0
lib/system/alloc.nim
Normal file → Executable file
0
lib/system/alloc.nim
Normal file → Executable file
0
lib/system/ansi_c.nim
Normal file → Executable file
0
lib/system/ansi_c.nim
Normal file → Executable file
0
lib/system/arithm.nim
Normal file → Executable file
0
lib/system/arithm.nim
Normal file → Executable file
2
lib/system/assign.nim
Normal file → Executable file
2
lib/system/assign.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
|
|||
0
lib/system/cellsets.nim
Normal file → Executable file
0
lib/system/cellsets.nim
Normal file → Executable file
10
lib/system/cntbits.nim
Normal file → Executable file
10
lib/system/cntbits.nim
Normal file → Executable 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
6
lib/system/debugger.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -11,9 +11,9 @@
|
|||
# with the application. We should not use dynamic memory here as that
|
||||
# would interfere with the GC and trigger ON/OFF errors if the
|
||||
# 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
|
||||
# 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...
|
||||
|
||||
type
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue