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 =
|
proc writePlatdefC =
|
||||||
var f: TFile
|
var f: TFile
|
||||||
if openFile(f, "build/platdef.c", fmWrite):
|
if open(f, "build/platdef.c", fmWrite):
|
||||||
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
|
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
|
||||||
closeFile(f)
|
close(f)
|
||||||
else:
|
else:
|
||||||
quit("Cannot write 'build/platdef.c'\n")
|
quit("Cannot write 'build/platdef.c'\n")
|
||||||
|
|
||||||
|
|
|
||||||
0
cogapp.py
Normal file → Executable file
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/posix"
|
||||||
path="$lib/ecmas"
|
path="$lib/ecmas"
|
||||||
|
|
||||||
@if release:
|
@if release or quick:
|
||||||
obj_checks:off
|
obj_checks:off
|
||||||
field_checks:off
|
field_checks:off
|
||||||
range_checks:off
|
range_checks:off
|
||||||
bound_checks:off
|
bound_checks:off
|
||||||
overflow_checks:off
|
overflow_checks:off
|
||||||
assertions:off
|
assertions:off
|
||||||
|
|
||||||
stacktrace:off
|
stacktrace:off
|
||||||
debugger:off
|
debugger:off
|
||||||
line_dir:off
|
line_dir:off
|
||||||
opt:speed
|
|
||||||
dead_code_elim:on
|
dead_code_elim:on
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@if release:
|
||||||
|
opt:speed
|
||||||
|
@end
|
||||||
|
|
||||||
# additional options always passed to the compiler:
|
# additional options always passed to the compiler:
|
||||||
--verbosity: "1"
|
--verbosity: "1"
|
||||||
|
|
||||||
|
|
|
||||||
0
configure
vendored
Normal file → Executable file
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
|
--lib:PATH set the system library path
|
||||||
-c, --compile_only compile only; do not assemble or link
|
-c, --compile_only compile only; do not assemble or link
|
||||||
--no_linking compile but do not link
|
--no_linking compile but do not link
|
||||||
|
--no_main do not generate a main procedure
|
||||||
--gen_script generate a compile script (in the 'nimcache'
|
--gen_script generate a compile script (in the 'nimcache'
|
||||||
subdirectory named 'compile_$project$scriptext')
|
subdirectory named 'compile_$project$scriptext')
|
||||||
--os:SYMBOL set the target operating system (cross-compilation)
|
--os:SYMBOL set the target operating system (cross-compilation)
|
||||||
|
|
|
||||||
35
data/ast.yml
Normal file → Executable file
35
data/ast.yml
Normal file → Executable file
|
|
@ -57,11 +57,12 @@
|
||||||
'TypeKind': [ # order is important!
|
'TypeKind': [ # order is important!
|
||||||
# Don't forget to change hti.nim if you make a change here
|
# Don't forget to change hti.nim if you make a change here
|
||||||
'tyNone', 'tyBool', 'tyChar',
|
'tyNone', 'tyBool', 'tyChar',
|
||||||
'tyEmpty', 'tyArrayConstr', 'tyNil',
|
'tyEmpty', 'tyArrayConstr', 'tyNil', 'tyExpr', 'tyStmt', 'tyTypeDesc',
|
||||||
'tyGeneric',
|
'tyGenericInvokation', # ``T[a, b]`` for types to invoke
|
||||||
'tyGenericInst', # instantiated generic type
|
'tyGenericBody', # ``T[a, b, body]`` last parameter is the body
|
||||||
'tyGenericParam',
|
'tyGenericInst', # ``T[a, b, realInstance]`` instantiated generic type
|
||||||
'tyAbstract', # abstract type
|
'tyGenericParam', # ``a`` in the example
|
||||||
|
'tyDistinct',
|
||||||
'tyEnum',
|
'tyEnum',
|
||||||
'tyOrdinal',
|
'tyOrdinal',
|
||||||
'tyArray',
|
'tyArray',
|
||||||
|
|
@ -123,8 +124,9 @@
|
||||||
# for transforming ``s.len`` to ``len(s)``
|
# for transforming ``s.len`` to ``len(s)``
|
||||||
'nkCommand', # a call like ``p 2, 4`` without parenthesis
|
'nkCommand', # a call like ``p 2, 4`` without parenthesis
|
||||||
'nkCall', # a call like p(x, y) or an operation like +(a, b)
|
'nkCall', # a call like p(x, y) or an operation like +(a, b)
|
||||||
'nkGenericCall', # a call with given type parameters
|
'nkCallStrLit', # a call with a string literal
|
||||||
'nkExplicitTypeListCall', # a call with given explicit typelist
|
# x"abc" has two sons: nkIdent, nkRStrLit
|
||||||
|
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
|
||||||
'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
|
'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
|
||||||
'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
|
'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
|
||||||
'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
|
'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
|
||||||
|
|
@ -174,7 +176,6 @@
|
||||||
|
|
||||||
'nkAsgn', # a = b
|
'nkAsgn', # a = b
|
||||||
'nkFastAsgn', # internal node for a fast ``a = b`` (no string copy)
|
'nkFastAsgn', # internal node for a fast ``a = b`` (no string copy)
|
||||||
'nkDefaultTypeParam', # `ident = typeDesc` in generic parameters
|
|
||||||
'nkGenericParams', # generic parameters
|
'nkGenericParams', # generic parameters
|
||||||
'nkFormalParams', # formal parameters
|
'nkFormalParams', # formal parameters
|
||||||
'nkOfInherit', # inherited from symbol
|
'nkOfInherit', # inherited from symbol
|
||||||
|
|
@ -215,7 +216,6 @@
|
||||||
'nkStmtList', # a list of statements
|
'nkStmtList', # a list of statements
|
||||||
'nkImportStmt', # an import statement
|
'nkImportStmt', # an import statement
|
||||||
'nkFromStmt', # a from * import statement
|
'nkFromStmt', # a from * import statement
|
||||||
'nkImportAs', # an `import xyx as abc` section
|
|
||||||
'nkIncludeStmt', # an include statement
|
'nkIncludeStmt', # an include statement
|
||||||
'nkCommentStmt', # a comment statement
|
'nkCommentStmt', # a comment statement
|
||||||
'nkStmtListExpr', # a statement list followed by an expr; this is used
|
'nkStmtListExpr', # a statement list followed by an expr; this is used
|
||||||
|
|
@ -225,20 +225,18 @@
|
||||||
# temporary scope
|
# temporary scope
|
||||||
'nkStmtListType', # a statement list ending in a type; for macros
|
'nkStmtListType', # a statement list ending in a type; for macros
|
||||||
'nkBlockType', # a statement block ending in a type; for macros
|
'nkBlockType', # a statement block ending in a type; for macros
|
||||||
'nkVm', # indicates a virtual instruction; integer field is
|
|
||||||
# used for the concrete opcode
|
|
||||||
|
|
||||||
# types as syntactic trees:
|
# types as syntactic trees:
|
||||||
'nkTypeOfExpr',
|
'nkTypeOfExpr',
|
||||||
'nkObjectTy',
|
'nkObjectTy',
|
||||||
'nkTupleTy',
|
'nkTupleTy',
|
||||||
'nkRecList', # list of record/object parts
|
'nkRecList', # list of object parts
|
||||||
'nkRecCase', # case section of record/object
|
'nkRecCase', # case section of object
|
||||||
'nkRecWhen', # when section of record/object
|
'nkRecWhen', # when section of object
|
||||||
'nkRefTy',
|
'nkRefTy',
|
||||||
'nkPtrTy',
|
'nkPtrTy',
|
||||||
'nkVarTy',
|
'nkVarTy',
|
||||||
'nkAbstractTy', # abstract type
|
'nkDistinctTy', # distinct type
|
||||||
'nkProcTy',
|
'nkProcTy',
|
||||||
'nkEnumTy',
|
'nkEnumTy',
|
||||||
'nkEnumFieldDef', # `ident = expr` in an enumeration
|
'nkEnumFieldDef', # `ident = expr` in an enumeration
|
||||||
|
|
@ -248,12 +246,13 @@
|
||||||
'SymKind': [
|
'SymKind': [
|
||||||
# the different symbols (start with the prefix sk);
|
# the different symbols (start with the prefix sk);
|
||||||
# order is important for the documentation generator!
|
# order is important for the documentation generator!
|
||||||
'skUnknownSym', # unknown symbol: used for parsing assembler blocks
|
'skUnknown', # unknown symbol: used for parsing assembler blocks
|
||||||
|
# and first phase symbol lookup in generics
|
||||||
'skConditional', # symbol for the preprocessor (may become obsolete)
|
'skConditional', # symbol for the preprocessor (may become obsolete)
|
||||||
'skDynLib', # symbol represents a dynamic library; this is used
|
'skDynLib', # symbol represents a dynamic library; this is used
|
||||||
# internally; it does not exist in Nimrod code
|
# internally; it does not exist in Nimrod code
|
||||||
'skParam', # a parameter
|
'skParam', # a parameter
|
||||||
'skTypeParam', # a type parameter; example: proc x[T]() <- `T`
|
'skGenericParam', # a generic parameter; eq in ``proc x[eq=`==`]()``
|
||||||
'skTemp', # a temporary variable (introduced by compiler)
|
'skTemp', # a temporary variable (introduced by compiler)
|
||||||
'skType', # a type
|
'skType', # a type
|
||||||
'skConst', # a constant
|
'skConst', # a constant
|
||||||
|
|
|
||||||
1
data/basicopt.txt
Normal file → Executable file
1
data/basicopt.txt
Normal file → Executable file
|
|
@ -5,6 +5,7 @@ Command::
|
||||||
compile_to_c, cc compile project with C code generator
|
compile_to_c, cc compile project with C code generator
|
||||||
doc generate the documentation for inputfile
|
doc generate the documentation for inputfile
|
||||||
rst2html converts a reStructuredText file to HTML
|
rst2html converts a reStructuredText file to HTML
|
||||||
|
rst2tex converts a reStructuredText file to TeX
|
||||||
Arguments:
|
Arguments:
|
||||||
arguments are passed to the program being run (if --run option is selected)
|
arguments are passed to the program being run (if --run option is selected)
|
||||||
Options:
|
Options:
|
||||||
|
|
|
||||||
0
data/ccomps.txt
Normal file → Executable file
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
|
bind block break
|
||||||
case cast const continue converter
|
case cast const continue converter
|
||||||
discard div
|
discard distinct div
|
||||||
elif else end enum except
|
elif else end enum except
|
||||||
finally for from generic
|
finally for from generic
|
||||||
if implies import in include is isnot iterator
|
if implies import in include is isnot iterator
|
||||||
|
|
|
||||||
5
data/magic.yml
Normal file → Executable file
5
data/magic.yml
Normal file → Executable file
|
|
@ -3,6 +3,7 @@
|
||||||
[
|
[
|
||||||
'None',
|
'None',
|
||||||
'Defined',
|
'Defined',
|
||||||
|
'DefinedInScope',
|
||||||
'Low',
|
'Low',
|
||||||
'High',
|
'High',
|
||||||
'SizeOf',
|
'SizeOf',
|
||||||
|
|
@ -17,7 +18,6 @@
|
||||||
'New',
|
'New',
|
||||||
'NewFinalize',
|
'NewFinalize',
|
||||||
'NewSeq',
|
'NewSeq',
|
||||||
'RegisterFinalizer',
|
|
||||||
'LengthOpenArray',
|
'LengthOpenArray',
|
||||||
'LengthStr',
|
'LengthStr',
|
||||||
'LengthArray',
|
'LengthArray',
|
||||||
|
|
@ -203,6 +203,9 @@
|
||||||
'EmptySet',
|
'EmptySet',
|
||||||
'IntSetBaseType',
|
'IntSetBaseType',
|
||||||
'Nil',
|
'Nil',
|
||||||
|
'Expr',
|
||||||
|
'Stmt',
|
||||||
|
'TypeDesc',
|
||||||
|
|
||||||
# magic constants:
|
# magic constants:
|
||||||
'IsMainModule',
|
'IsMainModule',
|
||||||
|
|
|
||||||
22
data/messages.yml
Normal file → Executable file
22
data/messages.yml
Normal file → Executable file
|
|
@ -31,15 +31,14 @@
|
||||||
{'errOperatorExpected': "operator expected, but found '$1'"},
|
{'errOperatorExpected': "operator expected, but found '$1'"},
|
||||||
{'errTokenExpected': "'$1' expected"},
|
{'errTokenExpected': "'$1' expected"},
|
||||||
{'errStringAfterIncludeExpected': "string after 'include' expected"},
|
{'errStringAfterIncludeExpected': "string after 'include' expected"},
|
||||||
{'errRecursiveInclude': "recursive include file: '$1'"},
|
{'errRecursiveDependencyX': "recursive dependency: '$1'"},
|
||||||
{'errOnOrOffExpected': "'on' or 'off' expected"},
|
{'errOnOrOffExpected': "'on' or 'off' expected"},
|
||||||
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
||||||
{'errInvalidPragma': 'invalid pragma'},
|
{'errInvalidPragma': 'invalid pragma'},
|
||||||
{'errUnknownPragma': "unknown pragma: '$1'"},
|
{'errUnknownPragma': "unknown pragma: '$1'"},
|
||||||
{'errUnknownDirective': "unknown directive: '$1'"},
|
{'errInvalidDirectiveX': "invalid directive: '$1'"},
|
||||||
{'errInvalidDirective': 'invalid directive'},
|
|
||||||
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
|
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
|
||||||
{'errEmptyAsm': 'empty asm statement makes no sense'},
|
{'errEmptyAsm': 'empty asm statement'},
|
||||||
{'errInvalidIndentation': 'invalid indentation'},
|
{'errInvalidIndentation': 'invalid indentation'},
|
||||||
{'errExceptionExpected': 'exception expected'},
|
{'errExceptionExpected': 'exception expected'},
|
||||||
{'errExceptionAlreadyHandled': 'exception already handled'},
|
{'errExceptionAlreadyHandled': 'exception already handled'},
|
||||||
|
|
@ -93,9 +92,6 @@
|
||||||
{'errCannotEvalXBecauseIncompletelyDefined':
|
{'errCannotEvalXBecauseIncompletelyDefined':
|
||||||
"cannot evalutate '$1' because type is not defined completely"},
|
"cannot evalutate '$1' because type is not defined completely"},
|
||||||
{'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"},
|
{'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"},
|
||||||
{'errStaticAssertFailed': "'staticAssert' failed: condition is false"},
|
|
||||||
{'errStaticAssertCannotBeEval':
|
|
||||||
"argument to 'staticAssert' cannot be evaluated at compile time"},
|
|
||||||
{'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"},
|
{'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"},
|
||||||
{'errUndeclaredFieldX': "undeclared field: '$1'"},
|
{'errUndeclaredFieldX': "undeclared field: '$1'"},
|
||||||
{'errNilAccess': 'attempt to access a nil address'},
|
{'errNilAccess': 'attempt to access a nil address'},
|
||||||
|
|
@ -155,7 +151,7 @@
|
||||||
{'errButExpected': 'but expected one of: '},
|
{'errButExpected': 'but expected one of: '},
|
||||||
{'errButExpectedX': "but expected '$1'"},
|
{'errButExpectedX': "but expected '$1'"},
|
||||||
{'errAmbiguousCallXYZ': 'ambiguous call; both $1 and $2 match for: $3'},
|
{'errAmbiguousCallXYZ': 'ambiguous call; both $1 and $2 match for: $3'},
|
||||||
{'errWrongNumberOfTypeParams': 'wrong number of type parameters'},
|
{'errWrongNumberOfArguments': 'wrong number of arguments'},
|
||||||
{'errInlineProcHasNoAddress': 'an inline proc has no address'},
|
{'errInlineProcHasNoAddress': 'an inline proc has no address'},
|
||||||
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
|
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
|
||||||
{'errPragmaOnlyInHeaderOfProc':
|
{'errPragmaOnlyInHeaderOfProc':
|
||||||
|
|
@ -198,16 +194,14 @@
|
||||||
{'errNamedExprNotAllowed': 'named expression not allowed here'},
|
{'errNamedExprNotAllowed': 'named expression not allowed here'},
|
||||||
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
|
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
|
||||||
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
|
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
|
||||||
{'errInvalidVisibilityX': "invalid invisibility: '$1'"},
|
{'errInvalidVisibilityX': "invalid visibility: '$1'"},
|
||||||
{'errInitHereNotAllowed': 'initialization not allowed here'},
|
{'errInitHereNotAllowed': 'initialization not allowed here'},
|
||||||
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
|
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
|
||||||
{'errIteratorNotAllowed':
|
{'errIteratorNotAllowed':
|
||||||
"iterators can only be defined at the module's top level"},
|
"iterators can only be defined at the module's top level"},
|
||||||
{'errIteratorNeedsImplementation': 'iterator needs an implementation'},
|
{'errXNeedsReturnType': '$1 needs a return type'},
|
||||||
{'errIteratorNeedsReturnType': 'iterator needs a return type'},
|
|
||||||
{'errInvalidCommandX': "invalid command: '$1'"},
|
{'errInvalidCommandX': "invalid command: '$1'"},
|
||||||
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
||||||
{'errTypeXNeedsImplementation': "type '$1' needs an implementation"},
|
|
||||||
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
|
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
|
||||||
{'errInstantiationFrom': 'instantiation from here'},
|
{'errInstantiationFrom': 'instantiation from here'},
|
||||||
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
||||||
|
|
@ -230,12 +224,12 @@
|
||||||
{'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"},
|
{'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"},
|
||||||
{'errAssertionFailed': "assertion failed"},
|
{'errAssertionFailed': "assertion failed"},
|
||||||
{'errCannotGenerateCodeForX': "cannot generate code for '$1'"},
|
{'errCannotGenerateCodeForX': "cannot generate code for '$1'"},
|
||||||
{'errXNeedsReturnType': "converter needs return type"},
|
{'errXRequiresOneArgument': "$1 requires one parameter"},
|
||||||
{'errXRequiresOneArgument': "converter requires one parameter"},
|
|
||||||
{'errUnhandledExceptionX': "unhandled exception: $1"},
|
{'errUnhandledExceptionX': "unhandled exception: $1"},
|
||||||
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
|
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
|
||||||
{'errXisNoMacroOrTemplate': "'$1' is no macro or template"},
|
{'errXisNoMacroOrTemplate': "'$1' is no macro or template"},
|
||||||
{'errXhasSideEffects': "'$1' can have side effects"},
|
{'errXhasSideEffects': "'$1' can have side effects"},
|
||||||
|
{'errIteratorExpected': "iterator within for loop context expected"},
|
||||||
|
|
||||||
# user error message:
|
# user error message:
|
||||||
{'errUser': '$1'},
|
{'errUser': '$1'},
|
||||||
|
|
|
||||||
0
data/pas_keyw.yml
Normal file → Executable file
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))
|
result = TDollar(int(x) + int(y))
|
||||||
|
|
||||||
It does not make sense to multiply a dollar with a dollar, but with a
|
It does not make sense to multiply a dollar with a dollar, but with a
|
||||||
unit-less number; and the same holds for division:
|
number without unit; and the same holds for division:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
proc `*` (x: TDollar, y: int): TDollar =
|
proc `*` (x: TDollar, y: int): TDollar =
|
||||||
|
|
@ -121,7 +121,7 @@ But it seems we still have to repeat all this boilerplate code for
|
||||||
the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
|
the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
template Additive(typ: typeExpr): stmt =
|
template Additive(typ: typeDesc): stmt =
|
||||||
proc `+` *(x, y: typ): typ {.borrow.}
|
proc `+` *(x, y: typ): typ {.borrow.}
|
||||||
proc `-` *(x, y: typ): typ {.borrow.}
|
proc `-` *(x, y: typ): typ {.borrow.}
|
||||||
|
|
||||||
|
|
@ -129,13 +129,13 @@ the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
|
||||||
proc `+` *(x: typ): typ {.borrow.}
|
proc `+` *(x: typ): typ {.borrow.}
|
||||||
proc `-` *(x: typ): typ {.borrow.}
|
proc `-` *(x: typ): typ {.borrow.}
|
||||||
|
|
||||||
template Multiplicative(typ, base: typeExpr): stmt =
|
template Multiplicative(typ, base: typeDesc): stmt =
|
||||||
proc `*` *(x: typ, y: base): typ {.borrow.}
|
proc `*` *(x: typ, y: base): typ {.borrow.}
|
||||||
proc `*` *(x: base, y: typ): typ {.borrow.}
|
proc `*` *(x: base, y: typ): typ {.borrow.}
|
||||||
proc `div` *(x: typ, y: base): typ {.borrow.}
|
proc `div` *(x: typ, y: base): typ {.borrow.}
|
||||||
proc `mod` *(x: typ, y: base): typ {.borrow.}
|
proc `mod` *(x: typ, y: base): typ {.borrow.}
|
||||||
|
|
||||||
template Comparable(typ: typeExpr): stmt =
|
template Comparable(typ: typeDesc): stmt =
|
||||||
proc `<` * (x, y: typ): bool {.borrow.}
|
proc `<` * (x, y: typ): bool {.borrow.}
|
||||||
proc `<=` * (x, y: typ): bool {.borrow.}
|
proc `<=` * (x, y: typ): bool {.borrow.}
|
||||||
proc `==` * (x, y: typ): bool {.borrow.}
|
proc `==` * (x, y: typ): bool {.borrow.}
|
||||||
|
|
|
||||||
0
doc/astspec.txt
Normal file → Executable file
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] ('.}' | '}')
|
pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}')
|
||||||
|
|
||||||
param ::= symbol (comma symbol)* ':' typeDesc
|
param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr)
|
||||||
paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc]
|
paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc]
|
||||||
|
|
||||||
genericParam ::= symbol [':' typeDesc]
|
genericParam ::= symbol [':' typeDesc] ['=' expr]
|
||||||
genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']'
|
genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']'
|
||||||
|
|
||||||
procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma]
|
procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma]
|
||||||
|
|
|
||||||
129
doc/intern.txt
Normal file → Executable file
129
doc/intern.txt
Normal file → Executable file
|
|
@ -17,7 +17,7 @@ The Nimrod project's directory structure is:
|
||||||
============ ==============================================
|
============ ==============================================
|
||||||
Path Purpose
|
Path Purpose
|
||||||
============ ==============================================
|
============ ==============================================
|
||||||
``bin`` binary files go into here
|
``bin`` generated binary files
|
||||||
``build`` generated C code for the installation
|
``build`` generated C code for the installation
|
||||||
``nim`` Pascal sources of the Nimrod compiler; this
|
``nim`` Pascal sources of the Nimrod compiler; this
|
||||||
should be modified, not the Nimrod version in
|
should be modified, not the Nimrod version in
|
||||||
|
|
@ -26,16 +26,16 @@ Path Purpose
|
||||||
automatically generated from the Pascal
|
automatically generated from the Pascal
|
||||||
version
|
version
|
||||||
``data`` data files that are used for generating source
|
``data`` data files that are used for generating source
|
||||||
code go into here
|
code
|
||||||
``doc`` the documentation lives here; it is a bunch of
|
``doc`` the documentation lives here; it is a bunch of
|
||||||
reStructuredText files
|
reStructuredText files
|
||||||
``dist`` additional packages for the distribution
|
``dist`` additional packages for the distribution
|
||||||
``config`` configuration files for Nimrod go into here
|
``config`` configuration files for Nimrod
|
||||||
``lib`` the Nimrod library lives here; ``rod`` depends
|
``lib`` the Nimrod library lives here; ``rod`` depends
|
||||||
on it!
|
on it!
|
||||||
``web`` website of Nimrod; generated by ``koch.py``
|
``web`` website of Nimrod; generated by ``koch.py``
|
||||||
from the ``*.txt`` and ``*.tmpl`` files
|
from the ``*.txt`` and ``*.tmpl`` files
|
||||||
``obj`` generated ``*.obj`` files go into here
|
``obj`` generated ``*.obj`` files
|
||||||
============ ==============================================
|
============ ==============================================
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -72,6 +72,18 @@ the same::
|
||||||
./boot [-d:release]
|
./boot [-d:release]
|
||||||
|
|
||||||
|
|
||||||
|
Coding Guidelines
|
||||||
|
=================
|
||||||
|
|
||||||
|
* Use CamelCase, not underscored_identifiers.
|
||||||
|
* Indent with two spaces.
|
||||||
|
* Max line length is 80 characters.
|
||||||
|
* Provide spaces around binary operators if that enhances readability.
|
||||||
|
* Use a space after a colon, but not before it.
|
||||||
|
* Start types with a capital ``T``, unless they are pointers which start with
|
||||||
|
``P``.
|
||||||
|
|
||||||
|
|
||||||
Pascal annotations
|
Pascal annotations
|
||||||
==================
|
==================
|
||||||
There are some annotations that the Pascal sources use so that they can
|
There are some annotations that the Pascal sources use so that they can
|
||||||
|
|
@ -153,9 +165,9 @@ Complex assignments
|
||||||
for any type that needs one. However, this would make the code bigger and
|
for any type that needs one. However, this would make the code bigger and
|
||||||
the RTTI is likely already there for the GC.
|
the RTTI is likely already there for the GC.
|
||||||
|
|
||||||
We already knew the type information as a graph in the compiler.
|
We already know the type information as a graph in the compiler.
|
||||||
Thus we need to serialize this graph as RTTI for C code generation.
|
Thus we need to serialize this graph as RTTI for C code generation.
|
||||||
Look at the file ``lib/hti.nim`` for more information.
|
Look at the file ``lib/system/hti.nim`` for more information.
|
||||||
|
|
||||||
|
|
||||||
The Garbage Collector
|
The Garbage Collector
|
||||||
|
|
@ -243,11 +255,8 @@ Consider this example:
|
||||||
# r is on the stack
|
# r is on the stack
|
||||||
setRef(r.left) # here we should update the refcounts!
|
setRef(r.left) # here we should update the refcounts!
|
||||||
|
|
||||||
Though it would be possible to produce code updating the refcounts (if
|
We have to decide at runtime whether the reference is on the stack or not.
|
||||||
necessary) before and after the call to ``setRef``, it is a complex task to
|
The generated code looks roughly like this:
|
||||||
do so in the code generator. So we don't and instead decide at runtime
|
|
||||||
whether the reference is on the stack or not. The generated code looks
|
|
||||||
roughly like this:
|
|
||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
void setref(TNode** ref) {
|
void setref(TNode** ref) {
|
||||||
|
|
@ -260,13 +269,7 @@ roughly like this:
|
||||||
|
|
||||||
Note that for systems with a continous stack (which most systems have)
|
Note that for systems with a continous stack (which most systems have)
|
||||||
the check whether the ref is on the stack is very cheap (only two
|
the check whether the ref is on the stack is very cheap (only two
|
||||||
comparisons). Another advantage of this scheme is that the code produced is
|
comparisons).
|
||||||
smaller.
|
|
||||||
|
|
||||||
|
|
||||||
The algorithm in pseudo-code
|
|
||||||
----------------------------
|
|
||||||
To be written.
|
|
||||||
|
|
||||||
|
|
||||||
The compiler's architecture
|
The compiler's architecture
|
||||||
|
|
@ -332,3 +335,93 @@ underlying C compiler already does all the hard work for us. The problem is the
|
||||||
common runtime library, especially the memory manager. Note that Borland's
|
common runtime library, especially the memory manager. Note that Borland's
|
||||||
Delphi had exactly the same problem. The workaround is to not link the GC with
|
Delphi had exactly the same problem. The workaround is to not link the GC with
|
||||||
the Dll and provide an extra runtime dll that needs to be initialized.
|
the Dll and provide an extra runtime dll that needs to be initialized.
|
||||||
|
|
||||||
|
|
||||||
|
Code generation for closures
|
||||||
|
============================
|
||||||
|
|
||||||
|
Example code:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc add(x: int): proc (y: int): int {.closure.} =
|
||||||
|
return lambda (y: int): int =
|
||||||
|
return x + y
|
||||||
|
|
||||||
|
var add2 = add(2)
|
||||||
|
echo add2(5) #OUT 7
|
||||||
|
|
||||||
|
This should produce roughly this code:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
type
|
||||||
|
PClosure = ref object
|
||||||
|
fn: proc (x: int, c: PClosure): int
|
||||||
|
x: int # data
|
||||||
|
|
||||||
|
proc wasLambda(y: int, c: PClosure): int =
|
||||||
|
return y + c.x
|
||||||
|
|
||||||
|
proc add(x: int): PClosure =
|
||||||
|
var c: PClosure
|
||||||
|
new(c)
|
||||||
|
c.x = x
|
||||||
|
c.fn = wasLambda
|
||||||
|
|
||||||
|
var add2 = add(2)
|
||||||
|
echo add2.fn(5, add2)
|
||||||
|
|
||||||
|
|
||||||
|
Beware of nesting:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} =
|
||||||
|
return lamba (y: int): proc (z: int): int {.closure.} =
|
||||||
|
return lambda (z: int): int =
|
||||||
|
return x + y + z
|
||||||
|
|
||||||
|
var add24 = add(2)(4)
|
||||||
|
echo add24(5) #OUT 11
|
||||||
|
|
||||||
|
This should produce roughly this code:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
type
|
||||||
|
PClosure1 = ref object
|
||||||
|
fn: proc (x: int, c: PClosure1): int
|
||||||
|
x: int # data
|
||||||
|
|
||||||
|
PClosure2 = ref object
|
||||||
|
fn: proc (x: int, c: PClosure2): int
|
||||||
|
y: int
|
||||||
|
c1: PClosure1
|
||||||
|
|
||||||
|
|
||||||
|
proc innerLambda(z: int, c2: PClosure2): int =
|
||||||
|
return c2.c1.x + c2.y + z
|
||||||
|
|
||||||
|
proc outerLambda1(y: int, c1: PClosure1): PClosure2 =
|
||||||
|
new(result)
|
||||||
|
result.c1 = c1
|
||||||
|
result.y = y
|
||||||
|
result.fn = innerLambda
|
||||||
|
|
||||||
|
proc add(x: int): PClosure1 =
|
||||||
|
new(result)
|
||||||
|
result.x = x
|
||||||
|
result.fn = outerLambda
|
||||||
|
|
||||||
|
var tmp = add(2)
|
||||||
|
var tmp2 = tmp.fn(4, tmp)
|
||||||
|
var add24 = tmp2.fn(4, tmp2)
|
||||||
|
echo add24(5)
|
||||||
|
|
||||||
|
|
||||||
|
Accumulator
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc GetAccumulator(start: int): proc (): int {.closure} =
|
||||||
|
var i = start
|
||||||
|
return lambda: int =
|
||||||
|
inc i
|
||||||
|
return i
|
||||||
|
|
|
||||||
2
doc/lib.txt
Normal file → Executable file
2
doc/lib.txt
Normal file → Executable file
|
|
@ -134,7 +134,7 @@ Impure libraries
|
||||||
Wrappers
|
Wrappers
|
||||||
========
|
========
|
||||||
|
|
||||||
Note that the generated HTML for some of these wrappers is so huge, that it is
|
The generated HTML for some of these wrappers is so huge, that it is
|
||||||
not contained in the distribution. You can then find them on the website.
|
not contained in the distribution. You can then find them on the website.
|
||||||
|
|
||||||
* `posix <posix.html>`_
|
* `posix <posix.html>`_
|
||||||
|
|
|
||||||
363
doc/manual.txt
Normal file → Executable file
363
doc/manual.txt
Normal file → Executable file
|
|
@ -8,6 +8,10 @@ Nimrod Manual
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
|
"Complexity" seems to be a lot like "energy": you can transfer it from the end
|
||||||
|
user to one/some of the other players, but the total amount seems to remain
|
||||||
|
pretty much constant for a given task. -- Ran
|
||||||
|
|
||||||
About this document
|
About this document
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
|
@ -171,10 +175,10 @@ preferred. Another advantage is that it frees the programmer from remembering
|
||||||
the exact spelling of an identifier.
|
the exact spelling of an identifier.
|
||||||
|
|
||||||
|
|
||||||
Literal strings
|
String literals
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
`Literal strings`:idx: can be delimited by matching double quotes, and can
|
`String literals`:idx: can be delimited by matching double quotes, and can
|
||||||
contain the following `escape sequences`:idx:\ :
|
contain the following `escape sequences`:idx:\ :
|
||||||
|
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
|
|
@ -202,12 +206,21 @@ contain the following `escape sequences`:idx:\ :
|
||||||
|
|
||||||
Strings in Nimrod may contain any 8-bit value, except embedded zeros.
|
Strings in Nimrod may contain any 8-bit value, except embedded zeros.
|
||||||
|
|
||||||
Literal strings can also be delimited by three double squotes
|
|
||||||
|
Triple quoted string literals
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
String literals can also be delimited by three double quotes
|
||||||
``"""`` ... ``"""``.
|
``"""`` ... ``"""``.
|
||||||
Literals in this form may run for several lines, may contain ``"`` and do not
|
Literals in this form may run for several lines, may contain ``"`` and do not
|
||||||
interpret any escape sequences.
|
interpret any escape sequences.
|
||||||
For convenience, when the opening ``"""`` is immediately followed by a newline,
|
For convenience, when the opening ``"""`` is immediately followed by a newline,
|
||||||
the newline is not included in the string.
|
the newline is not included in the string.
|
||||||
|
|
||||||
|
|
||||||
|
Raw string literals
|
||||||
|
-------------------
|
||||||
|
|
||||||
There are also `raw string literals` that are preceded with the letter ``r``
|
There are also `raw string literals` that are preceded with the letter ``r``
|
||||||
(or ``R``) and are delimited by matching double quotes (just like ordinary
|
(or ``R``) and are delimited by matching double quotes (just like ordinary
|
||||||
string literals) and do not interpret the escape sequences. This is especially
|
string literals) and do not interpret the escape sequences. This is especially
|
||||||
|
|
@ -218,7 +231,22 @@ convenient for regular expressions or Windows paths:
|
||||||
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
|
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
|
||||||
|
|
||||||
|
|
||||||
Literal characters
|
Generalized raw string literals
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The construct ``identifier"string literal"`` (without whitespace between the
|
||||||
|
identifier and the opening quotation mark) is a
|
||||||
|
`generalized raw string literal`:idx:. It is a shortcut for the construct
|
||||||
|
``identifier(r"string literal")``, so it denotes a procedure call with a
|
||||||
|
raw string literal as its only argument. Generalized raw string literals
|
||||||
|
are especially convenient for embedding mini languages directly into Nimrod
|
||||||
|
(for example regular expressions).
|
||||||
|
|
||||||
|
The construct ``identifier"""string literal"""`` exists too. It is a shortcut
|
||||||
|
for ``identifier("""string literal""")``.
|
||||||
|
|
||||||
|
|
||||||
|
Character literals
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Character literals are enclosed in single quotes ``''`` and can contain the
|
Character literals are enclosed in single quotes ``''`` and can contain the
|
||||||
|
|
@ -501,7 +529,7 @@ designed for this.
|
||||||
Another reason is that Nimrod can support ``array[char, int]`` or
|
Another reason is that Nimrod can support ``array[char, int]`` or
|
||||||
``set[char]`` efficiently as many algorithms rely on this feature. The
|
``set[char]`` efficiently as many algorithms rely on this feature. The
|
||||||
`TRune` type is used for Unicode characters, it can represent any Unicode
|
`TRune` type is used for Unicode characters, it can represent any Unicode
|
||||||
character. ``TRune`` is declared the ``unicode`` module.
|
character. ``TRune`` is declared in the ``unicode`` module.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -548,7 +576,7 @@ Subrange types
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
A `subrange`:idx: type is a range of values from an ordinal type (the base
|
A `subrange`:idx: type is a range of values from an ordinal type (the base
|
||||||
type). To define a subrange type, one must specify it's limiting values: the
|
type). To define a subrange type, one must specify it's limiting values: the
|
||||||
highest and lowest value of the type:
|
lowest and highest value of the type:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type
|
type
|
||||||
|
|
@ -764,7 +792,7 @@ basetype can only be an ordinal type. The reason is that sets are implemented
|
||||||
as high performance bit vectors.
|
as high performance bit vectors.
|
||||||
|
|
||||||
Sets can be constructed via the set constructor: ``{}`` is the empty set. The
|
Sets can be constructed via the set constructor: ``{}`` is the empty set. The
|
||||||
empty set is type combatible with any special set type. The constructor
|
empty set is type compatible with any special set type. The constructor
|
||||||
can also be used to include elements (and ranges of elements) in the set:
|
can also be used to include elements (and ranges of elements) in the set:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -903,9 +931,8 @@ each other:
|
||||||
|
|
||||||
`closure`:idx:
|
`closure`:idx:
|
||||||
indicates that the procedure expects a context, a closure that needs
|
indicates that the procedure expects a context, a closure that needs
|
||||||
to be passed to the procedure. The implementation is the
|
to be passed to the procedure. The calling convention ``nimcall`` is
|
||||||
same as ``cdecl``, but with a hidden pointer parameter (the
|
compatible to ``closure``.
|
||||||
*closure*). The hidden parameter is always the last one.
|
|
||||||
|
|
||||||
`syscall`:idx:
|
`syscall`:idx:
|
||||||
The syscall convention is the same as ``__syscall`` in C. It is used for
|
The syscall convention is the same as ``__syscall`` in C. It is used for
|
||||||
|
|
@ -915,11 +942,108 @@ each other:
|
||||||
The generated C code will not have any explicit calling convention and thus
|
The generated C code will not have any explicit calling convention and thus
|
||||||
use the C compiler's default calling convention. This is needed because
|
use the C compiler's default calling convention. This is needed because
|
||||||
Nimrod's default calling convention for procedures is ``fastcall`` to
|
Nimrod's default calling convention for procedures is ``fastcall`` to
|
||||||
improve speed. This is unlikely to be needed by the user.
|
improve speed.
|
||||||
|
|
||||||
Most calling conventions exist only for the Windows 32-bit platform.
|
Most calling conventions exist only for the Windows 32-bit platform.
|
||||||
|
|
||||||
|
|
||||||
|
Distinct type
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A distinct type is new type derived from a `base type`:idx: that is
|
||||||
|
incompatible with its base type. In particular, it is an essential property
|
||||||
|
of a distinct type that it **does not** imply a subtype relation between it
|
||||||
|
and its base type. Explict type conversions from a distinct type to its
|
||||||
|
base type and vice versa are allowed.
|
||||||
|
|
||||||
|
A distinct type can be used to model different physical `units`:idx: with a
|
||||||
|
numerical base type, for example. The following example models currencies.
|
||||||
|
|
||||||
|
Different currencies should not be mixed in monetary calculations. Distinct
|
||||||
|
types are a perfect tool to model different currencies:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
type
|
||||||
|
TDollar = distinct int
|
||||||
|
TEuro = distinct int
|
||||||
|
|
||||||
|
var
|
||||||
|
d: TDollar
|
||||||
|
e: TEuro
|
||||||
|
|
||||||
|
echo d + 12
|
||||||
|
# Error: cannot add a number with no unit and a ``TDollar``
|
||||||
|
|
||||||
|
Unfortunetaly, ``d + 12.TDollar`` is not allowed either,
|
||||||
|
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
|
||||||
|
a ``+`` for dollars needs to be defined:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
proc `+` (x, y: TDollar): TDollar =
|
||||||
|
result = TDollar(int(x) + int(y))
|
||||||
|
|
||||||
|
It does not make sense to multiply a dollar with a dollar, but with a
|
||||||
|
number without unit; and the same holds for division:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
proc `*` (x: TDollar, y: int): TDollar =
|
||||||
|
result = TDollar(int(x) * y)
|
||||||
|
|
||||||
|
proc `*` (x: int, y: TDollar): TDollar =
|
||||||
|
result = TDollar(x * int(y))
|
||||||
|
|
||||||
|
proc `div` ...
|
||||||
|
|
||||||
|
This quickly gets tedious. The implementations are trivial and the compiler
|
||||||
|
should not generate all this code only to optimize it away later - after all
|
||||||
|
``+`` for dollars should produce the same binary code as ``+`` for ints.
|
||||||
|
The pragma ``borrow`` has been designed to solve this problem; in principle
|
||||||
|
it generates the above trivial implementations:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc `*` (x: TDollar, y: int): TDollar {.borrow.}
|
||||||
|
proc `*` (x: int, y: TDollar): TDollar {.borrow.}
|
||||||
|
proc `div` (x: TDollar, y: int): TDollar {.borrow.}
|
||||||
|
|
||||||
|
The ``borrow`` pragma makes the compiler use the same implementation as
|
||||||
|
the proc that deals with the distinct type's base type, so no code is
|
||||||
|
generated.
|
||||||
|
|
||||||
|
But it seems all this boilerplate code needs to be repeated for the ``TEuro``
|
||||||
|
currency. This can be solved with templates_.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template Additive(typ: typeDesc): stmt =
|
||||||
|
proc `+` *(x, y: typ): typ {.borrow.}
|
||||||
|
proc `-` *(x, y: typ): typ {.borrow.}
|
||||||
|
|
||||||
|
# unary operators:
|
||||||
|
proc `+` *(x: typ): typ {.borrow.}
|
||||||
|
proc `-` *(x: typ): typ {.borrow.}
|
||||||
|
|
||||||
|
template Multiplicative(typ, base: typeDesc): stmt =
|
||||||
|
proc `*` *(x: typ, y: base): typ {.borrow.}
|
||||||
|
proc `*` *(x: base, y: typ): typ {.borrow.}
|
||||||
|
proc `div` *(x: typ, y: base): typ {.borrow.}
|
||||||
|
proc `mod` *(x: typ, y: base): typ {.borrow.}
|
||||||
|
|
||||||
|
template Comparable(typ: typeDesc): stmt =
|
||||||
|
proc `<` * (x, y: typ): bool {.borrow.}
|
||||||
|
proc `<=` * (x, y: typ): bool {.borrow.}
|
||||||
|
proc `==` * (x, y: typ): bool {.borrow.}
|
||||||
|
|
||||||
|
template DefineCurrency(typ, base: expr): stmt =
|
||||||
|
type
|
||||||
|
typ* = distinct base
|
||||||
|
Additive(typ)
|
||||||
|
Multiplicative(typ, base)
|
||||||
|
Comparable(typ)
|
||||||
|
|
||||||
|
DefineCurrency(TDollar, int)
|
||||||
|
DefineCurrency(TEuro, int)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Type relations
|
Type relations
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
@ -956,7 +1080,7 @@ algorithm determines type equality:
|
||||||
for i in 0..a.tupleLen-1:
|
for i in 0..a.tupleLen-1:
|
||||||
if not typeEqualsAux(a[i], b[i], s): return false
|
if not typeEqualsAux(a[i], b[i], s): return false
|
||||||
result = true
|
result = true
|
||||||
of object, enum, abstract:
|
of object, enum, distinct:
|
||||||
result = a == b
|
result = a == b
|
||||||
of proc:
|
of proc:
|
||||||
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
|
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
|
||||||
|
|
@ -973,7 +1097,7 @@ auxiliary set ``s`` to detect this case.
|
||||||
|
|
||||||
Subtype relation
|
Subtype relation
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
If object ``b`` inherits from ``a``, ``b`` is a subtype of ``a``. This subtype
|
If object ``a`` inherits from ``b``, ``a`` is a subtype of ``b``. This subtype
|
||||||
relation is extended to the types ``var``, ``ref``, ``ptr``:
|
relation is extended to the types ``var``, ``ref``, ``ptr``:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -987,27 +1111,70 @@ relation is extended to the types ``var``, ``ref``, ``ptr``:
|
||||||
of var, ref, ptr:
|
of var, ref, ptr:
|
||||||
result = isSubtype(a.baseType, b.baseType)
|
result = isSubtype(a.baseType, b.baseType)
|
||||||
|
|
||||||
XXX nil is a special value!
|
.. XXX nil is a special value!
|
||||||
|
|
||||||
|
|
||||||
Convertible relation
|
Convertible relation
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
A type ``a`` is convertible to type ``b`` iff the following algorithm returns
|
A type ``a`` is **implicitely** convertible to type ``b`` iff the following
|
||||||
true:
|
algorithm returns true:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc isConvertible(a, b: PType): bool =
|
# XXX range types?
|
||||||
if a.kind == b.kind:
|
proc isImplicitelyConvertible(a, b: PType): bool =
|
||||||
case a.kind
|
case a.kind
|
||||||
of proc:
|
of proc:
|
||||||
|
if b.kind == proc:
|
||||||
var x = a.parameterTuple
|
var x = a.parameterTuple
|
||||||
var y = b.parameterTuple
|
var y = b.parameterTuple
|
||||||
if x.tupleLen == y.tupleLen:
|
if x.tupleLen == y.tupleLen:
|
||||||
for i in 0.. x.tupleLen-1:
|
for i in 0.. x.tupleLen-1:
|
||||||
if not isSubtype(x[i], y[i]): return false
|
if not isSubtype(x[i], y[i]): return false
|
||||||
result = isSubType(b.resultType, a.resultType)
|
result = isSubType(b.resultType, a.resultType)
|
||||||
|
of int8: result = b.kind in {int16, int32, int64, int}
|
||||||
|
of int16: result = b.kind in {int32, int64, int}
|
||||||
|
of int32: result = b.kind in {int64, int}
|
||||||
|
of float: result = b.kind in {float32, float64}
|
||||||
|
of float32: result = b.kind in {float64, float}
|
||||||
|
of float64: result = b.kind in {float32, float}
|
||||||
|
of seq:
|
||||||
|
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
|
||||||
|
of array:
|
||||||
|
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
|
||||||
|
if a.baseType == char and a.indexType.rangeA == 0:
|
||||||
|
result = b.kind = cstring
|
||||||
|
of cstring, ptr:
|
||||||
|
result = b.kind == pointer
|
||||||
|
of string:
|
||||||
|
result = b.kind == cstring
|
||||||
|
|
||||||
|
A type ``a`` is **explicitely** convertible to type ``b`` iff the following
|
||||||
|
algorithm returns true:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc isIntegralType(t: PType): bool =
|
||||||
|
result = isOrdinal(t) or t.kind in {float, float32, float64}
|
||||||
|
|
||||||
|
proc isExplicitelyConvertible(a, b: PType): bool =
|
||||||
|
if isImplicitelyConvertible(a, b): return true
|
||||||
|
if isIntegralType(a) and isIntegralType(b): return true
|
||||||
|
if isSubtype(a, b) or isSubtype(b, a): return true
|
||||||
|
if a.kind == distinct and typeEquals(a.baseType, b): return true
|
||||||
|
if b.kind == distinct and typeEquals(b.baseType, a): return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
Assignment compability
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an
|
||||||
|
`l-value` and ``isImplicitelyConvertible(b.typ, a.typ)`` holds.
|
||||||
|
|
||||||
|
|
||||||
|
Overloading resolution
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
To be written.
|
||||||
|
|
||||||
|
|
||||||
Statements and expressions
|
Statements and expressions
|
||||||
|
|
@ -1095,7 +1262,7 @@ Type default value
|
||||||
============================ ==============================================
|
============================ ==============================================
|
||||||
any integer type 0
|
any integer type 0
|
||||||
any float 0.0
|
any float 0.0
|
||||||
char '\0'
|
char '\\0'
|
||||||
bool false
|
bool false
|
||||||
ref or pointer type nil
|
ref or pointer type nil
|
||||||
procedural type nil
|
procedural type nil
|
||||||
|
|
@ -1192,8 +1359,8 @@ a static error is given. This holds only for expressions of ordinal types.
|
||||||
If the expression is not of an ordinal type, and no ``else`` part is
|
If the expression is not of an ordinal type, and no ``else`` part is
|
||||||
given, control just passes after the ``case`` statement.
|
given, control just passes after the ``case`` statement.
|
||||||
|
|
||||||
To suppress the static error in the ordinal case the programmer needs
|
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
|
||||||
to write an ``else`` part with a ``nil`` statement.
|
statement can be used.
|
||||||
|
|
||||||
|
|
||||||
When statement
|
When statement
|
||||||
|
|
@ -1271,7 +1438,7 @@ Example:
|
||||||
# and tries to add them
|
# and tries to add them
|
||||||
var
|
var
|
||||||
f: TFile
|
f: TFile
|
||||||
if openFile(f, "numbers.txt"):
|
if open(f, "numbers.txt"):
|
||||||
try:
|
try:
|
||||||
var a = readLine(f)
|
var a = readLine(f)
|
||||||
var b = readLine(f)
|
var b = readLine(f)
|
||||||
|
|
@ -1285,7 +1452,7 @@ Example:
|
||||||
except:
|
except:
|
||||||
echo("Unknown exception!")
|
echo("Unknown exception!")
|
||||||
finally:
|
finally:
|
||||||
closeFile(f)
|
close(f)
|
||||||
|
|
||||||
The statements after the `try`:idx: are executed in sequential order unless
|
The statements after the `try`:idx: are executed in sequential order unless
|
||||||
an exception ``e`` is raised. If the exception type of ``e`` matches any
|
an exception ``e`` is raised. If the exception type of ``e`` matches any
|
||||||
|
|
@ -1417,7 +1584,7 @@ Example:
|
||||||
|
|
||||||
The `while`:idx: statement is executed until the ``expr`` evaluates to false.
|
The `while`:idx: statement is executed until the ``expr`` evaluates to false.
|
||||||
Endless loops are no error. ``while`` statements open an `implicit block`,
|
Endless loops are no error. ``while`` statements open an `implicit block`,
|
||||||
so that they can be leaved with a ``break`` statement.
|
so that they can be left with a ``break`` statement.
|
||||||
|
|
||||||
|
|
||||||
Continue statement
|
Continue statement
|
||||||
|
|
@ -1562,8 +1729,9 @@ type `var`).
|
||||||
return intToStr(x)
|
return intToStr(x)
|
||||||
|
|
||||||
Operators with one parameter are prefix operators, operators with two
|
Operators with one parameter are prefix operators, operators with two
|
||||||
parameters are infix operators. There is no way to declare postfix
|
parameters are infix operators. (However, the parser distinguishes these from
|
||||||
operators: All postfix operators are built-in and handled by the
|
the operators position within an expression.) There is no way to declare
|
||||||
|
postfix operators: All postfix operators are built-in and handled by the
|
||||||
grammar explicitely.
|
grammar explicitely.
|
||||||
|
|
||||||
Any operator can be called like an ordinary proc with the '`opr`'
|
Any operator can be called like an ordinary proc with the '`opr`'
|
||||||
|
|
@ -1622,18 +1790,13 @@ return values. This can be done in a cleaner way by returning a tuple:
|
||||||
assert t.res == 1
|
assert t.res == 1
|
||||||
assert t.remainder = 3
|
assert t.remainder = 3
|
||||||
|
|
||||||
Even more elegant is to use `tuple unpacking` to access the tuple's fields:
|
Even more elegant is to use `tuple unpacking`:idx: to access the tuple's fields:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
var (x, y) = divmod(8, 5) # tuple unpacking
|
var (x, y) = divmod(8, 5) # tuple unpacking
|
||||||
assert x == 1
|
assert x == 1
|
||||||
assert y == 3
|
assert y == 3
|
||||||
|
|
||||||
Unfortunately, this form of tuple unpacking is not yet implemented.
|
|
||||||
|
|
||||||
..
|
|
||||||
XXX remove this as soon as tuple unpacking is implemented
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Iterators and the for statement
|
Iterators and the for statement
|
||||||
|
|
@ -1655,7 +1818,7 @@ Syntax::
|
||||||
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
||||||
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
||||||
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
||||||
can be leaved with a ``break`` statement. The ``for`` loop declares
|
can be left with a ``break`` statement. The ``for`` loop declares
|
||||||
iteration variables (``x`` in the example) - their scope reaches until the
|
iteration variables (``x`` in the example) - their scope reaches until the
|
||||||
end of the loop body. The iteration variables' types are inferred by the
|
end of the loop body. The iteration variables' types are inferred by the
|
||||||
return type of the iterator.
|
return type of the iterator.
|
||||||
|
|
@ -1737,8 +1900,6 @@ possible within a single ``type`` section.
|
||||||
Generics
|
Generics
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
`Version 0.7.10: Generic types like in the example do not work.`:red:
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -1778,11 +1939,9 @@ Example:
|
||||||
# inorder traversal of a binary tree
|
# inorder traversal of a binary tree
|
||||||
# recursive iterators are not yet implemented, so this does not work in
|
# recursive iterators are not yet implemented, so this does not work in
|
||||||
# the current compiler!
|
# the current compiler!
|
||||||
if root.le != nil:
|
if root.le != nil: yield inorder(root.le)
|
||||||
yield inorder(root.le)
|
|
||||||
yield root.data
|
yield root.data
|
||||||
if root.ri != nil:
|
if root.ri != nil: yield inorder(root.ri)
|
||||||
yield inorder(root.ri)
|
|
||||||
|
|
||||||
var
|
var
|
||||||
root: PBinaryTree[string] # instantiate a PBinaryTree with the type string
|
root: PBinaryTree[string] # instantiate a PBinaryTree with the type string
|
||||||
|
|
@ -1799,12 +1958,11 @@ introduce type parameters or to instantiate a generic proc, iterator or type.
|
||||||
Templates
|
Templates
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
A `template`:idx: is a simple form of a macro. It operates on parse trees and is
|
A `template`:idx: is a simple form of a macro: It is a simple substitution
|
||||||
processed in the semantic pass of the compiler. So they integrate well with the
|
mechanism that operates on Nimrod's abstract syntax trees. It is processed in
|
||||||
rest of the language and share none of C's preprocessor macros flaws. However,
|
the semantic pass of the compiler.
|
||||||
they may lead to code that is harder to understand and maintain. So one ought
|
|
||||||
to use them sparingly. The usage of ordinary procs, iterators or generics is
|
The syntax to *invoke* a template is the same as calling a procedure.
|
||||||
preferred to the usage of templates.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
@ -1815,20 +1973,86 @@ Example:
|
||||||
|
|
||||||
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
|
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
|
||||||
|
|
||||||
|
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
|
||||||
|
templates:
|
||||||
|
|
||||||
|
| ``a > b`` is transformed into ``b < a``.
|
||||||
|
| ``a in b`` is transformed into ``contains(b, a)``.
|
||||||
|
| ``notin`` and ``isnot`` have the obvious meanings.
|
||||||
|
|
||||||
|
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
||||||
|
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
||||||
|
description*). These are no real types, they just help the compiler parsing.
|
||||||
|
Real types can be used too; this implies that expressions are expected.
|
||||||
|
However, for parameter type checking the arguments are semantically checked
|
||||||
|
before being passed to the template. Other arguments are not semantically
|
||||||
|
checked before being passed to the template.
|
||||||
|
|
||||||
|
The template body does not open a new scope. To open a new scope a ``block``
|
||||||
|
statement can be used:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template declareInScope(x: expr, t: typeDesc): stmt =
|
||||||
|
var x: t
|
||||||
|
|
||||||
|
template declareInNewScope(x: expr, t: typeDesc): stmt =
|
||||||
|
# open a new scope:
|
||||||
|
block:
|
||||||
|
var x: t
|
||||||
|
|
||||||
|
declareInScope(a, int)
|
||||||
|
a = 42 # works, `a` is known here
|
||||||
|
|
||||||
|
declareInNewScope(b, int)
|
||||||
|
b = 42 # does not work, `b` is unknown
|
||||||
|
|
||||||
|
|
||||||
|
If there is a ``stmt`` parameter it should be the last in the template
|
||||||
|
declaration, because statements are passed to a template via a
|
||||||
|
special ``:`` syntax:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
|
||||||
|
template withFile(f, fn, mode: expr, actions: stmt): stmt =
|
||||||
|
block:
|
||||||
|
var f: TFile
|
||||||
|
if open(f, fn, mode):
|
||||||
|
try:
|
||||||
|
actions
|
||||||
|
finally:
|
||||||
|
close(f)
|
||||||
|
else:
|
||||||
|
quit("cannot open: " & fn)
|
||||||
|
|
||||||
|
withFile(txt, "ttempl3.txt", fmWrite):
|
||||||
|
txt.writeln("line 1")
|
||||||
|
txt.writeln("line 2")
|
||||||
|
|
||||||
|
In the example the two ``writeln`` statements are bound to the ``actions``
|
||||||
|
parameter.
|
||||||
|
|
||||||
|
|
||||||
|
**Style note**: For code readability, it is the best idea to use the least
|
||||||
|
powerful programming construct that still suffices. So the "check list" is:
|
||||||
|
|
||||||
|
(1) Use an ordinary proc/iterator, if possible.
|
||||||
|
(2) Else: Use a generic proc/iterator, if possible.
|
||||||
|
(3) Else: Use a template, if possible.
|
||||||
|
(4) Else: Use a macro.
|
||||||
|
|
||||||
|
|
||||||
Macros
|
Macros
|
||||||
------
|
------
|
||||||
|
|
||||||
`Macros`:idx: are the most powerful feature of Nimrod. They can be used
|
`Macros`:idx: are the most powerful feature of Nimrod. They can be used
|
||||||
to implement `domain specific languages`:idx:. But they may lead to code
|
to implement `domain specific languages`:idx:.
|
||||||
that is harder to understand and maintain. So one ought to use them sparingly.
|
|
||||||
|
|
||||||
While macros enable advanced compile-time code tranformations, they
|
While macros enable advanced compile-time code tranformations, they
|
||||||
cannot change Nimrod's syntax. However, this is no real restriction because
|
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||||
Nimrod's syntax is flexible enough anyway.
|
Nimrod's syntax is flexible enough anyway.
|
||||||
|
|
||||||
To write macros, one needs to know how the Nimrod concrete syntax is converted
|
To write macros, one needs to know how the Nimrod concrete syntax is converted
|
||||||
to an abstract syntax tree. (Unfortunately the AST is not yet documented.)
|
to an abstract syntax tree.
|
||||||
|
|
||||||
There are two ways to invoke a macro:
|
There are two ways to invoke a macro:
|
||||||
(1) invoking a macro like a procedure call (`expression macros`)
|
(1) invoking a macro like a procedure call (`expression macros`)
|
||||||
|
|
@ -1847,7 +2071,7 @@ variable number of arguments:
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro debug(n: expr): stmt =
|
macro debug(n: expr): stmt =
|
||||||
# `n` is a Nimrod AST that contains the whole macro expression
|
# `n` is a Nimrod AST that contains the whole macro invokation
|
||||||
# this macro returns a list of statements:
|
# this macro returns a list of statements:
|
||||||
result = newNimNode(nnkStmtList, n)
|
result = newNimNode(nnkStmtList, n)
|
||||||
# iterate over any argument that is passed to this macro:
|
# iterate over any argument that is passed to this macro:
|
||||||
|
|
@ -1948,6 +2172,7 @@ This is best illustrated by an example:
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module B
|
# Module B
|
||||||
import A # A is not parsed here! Only the already known symbols
|
import A # A is not parsed here! Only the already known symbols
|
||||||
# of A are imported.
|
# of A are imported.
|
||||||
|
|
@ -1981,7 +2206,7 @@ Tuple or object scope
|
||||||
The field identifiers inside a tuple or object definition are valid in the
|
The field identifiers inside a tuple or object definition are valid in the
|
||||||
following places:
|
following places:
|
||||||
|
|
||||||
* To the end of the tuple/object definition
|
* To the end of the tuple/object definition.
|
||||||
* Field designators of a variable of the given tuple/object type.
|
* Field designators of a variable of the given tuple/object type.
|
||||||
* In all descendent types of the object type.
|
* In all descendent types of the object type.
|
||||||
|
|
||||||
|
|
@ -2000,9 +2225,11 @@ iterator in which case the overloading resolution takes place:
|
||||||
# Module A
|
# Module A
|
||||||
var x*: string
|
var x*: string
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module B
|
# Module B
|
||||||
var x*: int
|
var x*: int
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
# Module C
|
# Module C
|
||||||
import A, B
|
import A, B
|
||||||
write(stdout, x) # error: x is ambiguous
|
write(stdout, x) # error: x is ambiguous
|
||||||
|
|
@ -2035,26 +2262,22 @@ processed on the fly during semantic checking. Pragmas are enclosed in the
|
||||||
special ``{.`` and ``.}`` curly brackets.
|
special ``{.`` and ``.}`` curly brackets.
|
||||||
|
|
||||||
|
|
||||||
define pragma
|
noSideEffect pragma
|
||||||
-------------
|
-------------------
|
||||||
The `define`:idx: pragma defines a conditional symbol. This symbol may only be
|
The `noSideEffect`:idx: pragma is used to mark a proc/iterator to have no side
|
||||||
used in other pragmas and in the ``defined`` expression and not in ordinary
|
effects. This means that the proc/iterator only changes locations that are
|
||||||
Nimrod source code. The conditional symbols go into a special symbol table.
|
reachable from its parameters and the return value only depends on the
|
||||||
The compiler defines the target processor and the target operating
|
arguments. If none of its parameters have the type ``var T``
|
||||||
system as conditional symbols.
|
or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static
|
||||||
|
error to mark a proc/iterator to have no side effect if the compiler cannot
|
||||||
Warning: The ``define`` pragma is deprecated as it conflicts with separate
|
verify this.
|
||||||
compilation! One should use boolean constants as a replacement - this is
|
|
||||||
cleaner anyway.
|
|
||||||
|
|
||||||
|
|
||||||
undef pragma
|
compileTime pragma
|
||||||
------------
|
------------------
|
||||||
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a
|
The `compileTime`:idx: pragma is used to mark a proc to be used at compile
|
||||||
conditional symbol.
|
time only. No code will be generated for it. Compile time procs are useful
|
||||||
|
as helpers for macros.
|
||||||
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
|
|
||||||
compilation!
|
|
||||||
|
|
||||||
|
|
||||||
error pragma
|
error pragma
|
||||||
|
|
|
||||||
0
doc/mytest.cfg
Normal file → Executable file
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.}
|
proc gtk_image_new(): PGtkWidget {.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
|
||||||
|
|
||||||
In general, importing a dynamic library does not require any special linker
|
In general, importing a dynamic library does not require any special linker
|
||||||
options or linking with import libraries. This also
|
options or linking with import libraries. This also implies that no *devel*
|
||||||
implies that no *devel* packages need to be installed.
|
packages need to be installed.
|
||||||
|
|
||||||
|
|
||||||
No_decl Pragma
|
No_decl Pragma
|
||||||
|
|
@ -279,9 +279,7 @@ However, sometimes one has to optimize. Do it in the following order:
|
||||||
4. try to find a better algorithm
|
4. try to find a better algorithm
|
||||||
5. do low-level optimizations
|
5. do low-level optimizations
|
||||||
|
|
||||||
This section can only help you with the last item. Note that rewriting parts
|
This section can only help you with the last item.
|
||||||
of your program in C is *never* necessary to speed up your program, because
|
|
||||||
everything that can be done in C can be done in Nimrod.
|
|
||||||
|
|
||||||
|
|
||||||
Optimizing string handling
|
Optimizing string handling
|
||||||
|
|
@ -308,31 +306,32 @@ if several different string constants are used. This is likely to be more
|
||||||
efficient than any hand-coded scheme.
|
efficient than any hand-coded scheme.
|
||||||
|
|
||||||
|
|
||||||
The ECMAScript code generator
|
..
|
||||||
=============================
|
The ECMAScript code generator
|
||||||
|
=============================
|
||||||
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
|
|
||||||
longer. Help if you are interested.
|
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
|
||||||
|
longer. Help if you are interested.
|
||||||
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since
|
|
||||||
it is the proper term.
|
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
|
||||||
|
since it is the proper term.
|
||||||
The ECMAScript code generator is experimental!
|
|
||||||
|
The ECMAScript code generator is experimental!
|
||||||
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
|
|
||||||
Since ECMAScript does not have a portable means to include another module,
|
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
|
||||||
Nimrod just generates a long ``.js`` file.
|
Since ECMAScript does not have a portable means to include another module,
|
||||||
|
Nimrod just generates a long ``.js`` file.
|
||||||
Features or modules that the ECMAScript platform does not support are not
|
|
||||||
available. This includes:
|
Features or modules that the ECMAScript platform does not support are not
|
||||||
|
available. This includes:
|
||||||
* manual memory management (``alloc``, etc.)
|
|
||||||
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
|
* manual memory management (``alloc``, etc.)
|
||||||
* file management (``openfile``, etc.)
|
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
|
||||||
* most modules of the Standard library
|
* file management
|
||||||
* proper 64 bit integer arithmetic
|
* most modules of the Standard library
|
||||||
* proper unsigned integer arithmetic
|
* proper 64 bit integer arithmetic
|
||||||
|
* proper unsigned integer arithmetic
|
||||||
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
|
|
||||||
available! To access the DOM, use the `dom`:idx: module that is only available
|
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
|
||||||
for the ECMAScript platform.
|
available! To access the DOM, use the `dom`:idx: module that is only
|
||||||
|
available for the ECMAScript platform.
|
||||||
|
|
|
||||||
0
doc/overview.txt
Normal file → Executable file
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()
|
c.draw()
|
||||||
|
|
||||||
The code uses a ``draw`` procedure that is bound statically, but inside it
|
The code uses a ``draw`` procedure that is bound statically, but inside it
|
||||||
the dynamic dispatch happens with the help of the ``fdraw`` field. This is
|
the dynamic dispatch happens with the help of the ``fdraw`` field. Even though
|
||||||
slightly more inconvienent than in traditional OOP-languages, but has the
|
this solution has its advantages compared to traditional OOP-languages, it is
|
||||||
advantage of being much more flexible (and somewhat faster). The above approach
|
a **preliminary** solution. Multimethods are a planned language feature that
|
||||||
also allows some form *monkey patching* by modifying the ``fdraw`` field.
|
provide a more flexible and efficient mechanism.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Exceptions
|
Exceptions
|
||||||
|
|
@ -323,15 +322,13 @@ Exceptions
|
||||||
|
|
||||||
In Nimrod `exceptions`:idx: are objects. By convention, exception types are
|
In Nimrod `exceptions`:idx: are objects. By convention, exception types are
|
||||||
prefixed with an 'E', not 'T'. The ``system`` module defines an exception
|
prefixed with an 'E', not 'T'. The ``system`` module defines an exception
|
||||||
hierarchy that you should stick to. Reusing an existing exception type is
|
hierarchy that you might want to stick to.
|
||||||
often better than defining a new exception type: It avoids a proliferation of
|
|
||||||
types.
|
|
||||||
|
|
||||||
Exceptions should be allocated on the heap because their lifetime is unknown.
|
Exceptions should be allocated on the heap because their lifetime is unknown.
|
||||||
|
|
||||||
A convention is that exceptions should be raised in *exceptional* cases:
|
A convention is that exceptions should be raised in *exceptional* cases:
|
||||||
For example, if a file cannot be opened, this should not raise an exception
|
For example, if a file cannot be opened, this should not raise an
|
||||||
since this is quite common (the file may have been deleted).
|
exception since this is quite common (the file may not exist).
|
||||||
|
|
||||||
|
|
||||||
Raise statement
|
Raise statement
|
||||||
|
|
@ -359,7 +356,7 @@ The `try`:idx: statement handles exceptions:
|
||||||
# and tries to add them
|
# and tries to add them
|
||||||
var
|
var
|
||||||
f: TFile
|
f: TFile
|
||||||
if openFile(f, "numbers.txt"):
|
if open(f, "numbers.txt"):
|
||||||
try:
|
try:
|
||||||
var a = readLine(f)
|
var a = readLine(f)
|
||||||
var b = readLine(f)
|
var b = readLine(f)
|
||||||
|
|
@ -375,7 +372,7 @@ The `try`:idx: statement handles exceptions:
|
||||||
# reraise the unknown exception:
|
# reraise the unknown exception:
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
closeFile(f)
|
close(f)
|
||||||
|
|
||||||
The statements after the ``try`` are executed unless an exception is
|
The statements after the ``try`` are executed unless an exception is
|
||||||
raised. Then the appropriate ``except`` part is executed.
|
raised. Then the appropriate ``except`` part is executed.
|
||||||
|
|
@ -396,8 +393,6 @@ is not executed (if an exception occurs).
|
||||||
Generics
|
Generics
|
||||||
========
|
========
|
||||||
|
|
||||||
`Version 0.7.10: Complex generic types like in the example do not work.`:red:
|
|
||||||
|
|
||||||
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types
|
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types
|
||||||
with `type parameters`:idx:. They are most useful for efficient type safe
|
with `type parameters`:idx:. They are most useful for efficient type safe
|
||||||
containers:
|
containers:
|
||||||
|
|
@ -448,7 +443,7 @@ containers:
|
||||||
while stack.len > 0:
|
while stack.len > 0:
|
||||||
var n = stack.pop()
|
var n = stack.pop()
|
||||||
while n != nil:
|
while n != nil:
|
||||||
yield n
|
yield n.data
|
||||||
add(stack, n.ri) # push right subtree onto the stack
|
add(stack, n.ri) # push right subtree onto the stack
|
||||||
n = n.le # and follow the left pointer
|
n = n.le # and follow the left pointer
|
||||||
|
|
||||||
|
|
@ -472,8 +467,7 @@ Templates
|
||||||
Templates are a simple substitution mechanism that operates on Nimrod's
|
Templates are a simple substitution mechanism that operates on Nimrod's
|
||||||
abstract syntax trees. Templates are processed in the semantic pass of the
|
abstract syntax trees. Templates are processed in the semantic pass of the
|
||||||
compiler. They integrate well with the rest of the language and share none
|
compiler. They integrate well with the rest of the language and share none
|
||||||
of C's preprocessor macros flaws. However, they may lead to code that is harder
|
of C's preprocessor macros flaws.
|
||||||
to understand and maintain. So one should use them sparingly.
|
|
||||||
|
|
||||||
To *invoke* a template, call it like a procedure.
|
To *invoke* a template, call it like a procedure.
|
||||||
|
|
||||||
|
|
@ -488,7 +482,8 @@ Example:
|
||||||
|
|
||||||
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
|
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
|
||||||
templates: This has the benefit that if you overload the ``==`` operator,
|
templates: This has the benefit that if you overload the ``==`` operator,
|
||||||
the ``!=`` operator is available automatically and does the right thing.
|
the ``!=`` operator is available automatically and does the right thing. (Except
|
||||||
|
for IEEE floating point numbers - NaN breaks basic boolean logic.)
|
||||||
|
|
||||||
``a > b`` is transformed into ``b < a``.
|
``a > b`` is transformed into ``b < a``.
|
||||||
``a in b`` is transformed into ``contains(b, a)``.
|
``a in b`` is transformed into ``contains(b, a)``.
|
||||||
|
|
@ -513,7 +508,7 @@ This code has a shortcoming: If ``debug`` is set to false someday, the quite
|
||||||
expensive ``$`` and ``&`` operations are still performed! (The argument
|
expensive ``$`` and ``&`` operations are still performed! (The argument
|
||||||
evaluation for procedures is said to be *eager*).
|
evaluation for procedures is said to be *eager*).
|
||||||
|
|
||||||
Turning the ``log`` proc into a template solves this problem in an elegant way:
|
Turning the ``log`` proc into a template solves this problem:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
const
|
const
|
||||||
|
|
@ -530,7 +525,7 @@ Turning the ``log`` proc into a template solves this problem in an elegant way:
|
||||||
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
||||||
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
||||||
description*). These are no real types, they just help the compiler parsing.
|
description*). These are no real types, they just help the compiler parsing.
|
||||||
In later versions, real types will be supported too.
|
However, real types are supported too.
|
||||||
|
|
||||||
The template body does not open a new scope. To open a new scope
|
The template body does not open a new scope. To open a new scope
|
||||||
use a ``block`` statement:
|
use a ``block`` statement:
|
||||||
|
|
@ -557,7 +552,8 @@ via a special ``:`` syntax:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
||||||
template withFile(f, filename, mode: expr, actions: stmt): stmt =
|
template withFile(f: expr, filename: string, mode: TFileMode,
|
||||||
|
actions: stmt): stmt =
|
||||||
block:
|
block:
|
||||||
var fn = filename
|
var fn = filename
|
||||||
var f: TFile
|
var f: TFile
|
||||||
|
|
@ -583,11 +579,6 @@ once.
|
||||||
Macros
|
Macros
|
||||||
======
|
======
|
||||||
|
|
||||||
If the template mechanism scares you, you will be pleased to hear that
|
|
||||||
templates are not really necessary: Macros can do anything that templates can
|
|
||||||
do and much more. Macros are harder to write than templates and even harder
|
|
||||||
to get right :-). Now that you have been warned, lets see what a macro *is*.
|
|
||||||
|
|
||||||
Macros enable advanced compile-time code tranformations, but they
|
Macros enable advanced compile-time code tranformations, but they
|
||||||
cannot change Nimrod's syntax. However, this is no real restriction because
|
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||||
Nimrod's syntax is flexible enough anyway.
|
Nimrod's syntax is flexible enough anyway.
|
||||||
|
|
@ -598,7 +589,8 @@ to an abstract syntax tree (AST). The AST is documented in the
|
||||||
|
|
||||||
There are two ways to invoke a macro:
|
There are two ways to invoke a macro:
|
||||||
(1) invoking a macro like a procedure call (`expression macros`:idx:)
|
(1) invoking a macro like a procedure call (`expression macros`:idx:)
|
||||||
(2) invoking a macro with the special ``macrostmt`` syntax (`statement macros`:idx:)
|
(2) invoking a macro with the special ``macrostmt``
|
||||||
|
syntax (`statement macros`:idx:)
|
||||||
|
|
||||||
|
|
||||||
Expression Macros
|
Expression Macros
|
||||||
|
|
|
||||||
0
dos2unix.py
Normal file → Executable file
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
|
import strutils
|
||||||
|
|
||||||
echo "Give a list of numbers (separated by spaces): "
|
echo "Give a list of numbers (separated by spaces): "
|
||||||
stdin.readLine.splitSeq.each(parseInt).max.`$`.echo(" is the maximum!")
|
stdin.readLine.split.each(parseInt).max.`$`.echo(" is the maximum!")
|
||||||
|
|
|
||||||
0
examples/myfile.txt
Normal file → Executable file
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
|
Installation on Linux/UNIX
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
Note:
|
|
||||||
A C compiler is required - knowledge of C is not!
|
|
||||||
|
|
||||||
The GNU C Compiler is fully supported, other compilers may work. The C compiler
|
The GNU C Compiler is fully supported, other compilers may work. The C compiler
|
||||||
should be in your ``$PATH`` (most likely the case). Note that some few Linux
|
should be in your ``$PATH`` (most likely the case). Note that some few Linux
|
||||||
distributions do not ship with a GCC compiler preinstalled - then you have to
|
distributions do not ship with a GCC compiler preinstalled - then you have to
|
||||||
|
|
@ -31,8 +28,8 @@ manually. An alternative is to create a symbolic link in ``/usr/bin``::
|
||||||
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
|
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
|
||||||
|
|
||||||
From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are
|
From version 0.7.10 onwards ``install.sh`` and ``deinstall.sh`` scripts are
|
||||||
provided for distributing the files over the UNIX hierarchy. However, this
|
provided for distributing the files over the UNIX hierarchy. However,
|
||||||
makes updating your Nimrod installation more cumbersome.
|
updating your Nimrod installation is more cumbersome then.
|
||||||
|
|
||||||
|
|
||||||
Installation on the Macintosh
|
Installation on the Macintosh
|
||||||
|
|
|
||||||
33
koch.py
Normal file → Executable file
33
koch.py
Normal file → Executable file
|
|
@ -12,16 +12,17 @@ from pycompab import *
|
||||||
|
|
||||||
# --------------------- constants ----------------------------------------
|
# --------------------- constants ----------------------------------------
|
||||||
|
|
||||||
NIMROD_VERSION = '0.7.10'
|
NIMROD_VERSION = '0.8.1'
|
||||||
# This string contains Nimrod's version. It is the only place
|
# This string contains Nimrod's version. It is the only place
|
||||||
# where the version needs to be updated. The rest is done by
|
# where the version needs to be updated. The rest is done by
|
||||||
# the build process automatically. It is replaced **everywhere**!
|
# the build process automatically. It is replaced **everywhere**!
|
||||||
# Format is: Major.Minor.Patch
|
# Format is: Major.Minor.Patch
|
||||||
# Major part: plan is to use number 1 for the first version that is stable;
|
# Major part: plan is to use number 1 for the first version that is stable;
|
||||||
# higher versions may be incompatible with previous versions
|
# higher versions may be incompatible with previous versions
|
||||||
# Minor part: incremented if new features are added (but is completely
|
# Minor part: incremented if new features are added; unfortunately often
|
||||||
# backwards-compatible)
|
# not backwards-compatible
|
||||||
# Patch level: is increased for every patch
|
# Patch level: is increased for every patch; should be completely
|
||||||
|
# backwards-compatible
|
||||||
|
|
||||||
EXPLAIN = true
|
EXPLAIN = true
|
||||||
force = false
|
force = false
|
||||||
|
|
@ -209,14 +210,15 @@ def Glob(pattern): # needed because glob.glob() is buggy on Windows 95:
|
||||||
global _baseDir
|
global _baseDir
|
||||||
(head, tail) = os.path.split(Path(pattern))
|
(head, tail) = os.path.split(Path(pattern))
|
||||||
result = []
|
result = []
|
||||||
try:
|
if os.path.exists(head):
|
||||||
os.chdir(os.path.join(_baseDir, head))
|
|
||||||
try:
|
try:
|
||||||
for f in glob.glob(tail): result.append(os.path.join(head, f))
|
os.chdir(os.path.join(_baseDir, head))
|
||||||
except OSError:
|
try:
|
||||||
result = []
|
for f in glob.glob(tail): result.append(os.path.join(head, f))
|
||||||
finally:
|
except OSError:
|
||||||
os.chdir(_baseDir)
|
result = []
|
||||||
|
finally:
|
||||||
|
os.chdir(_baseDir)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def FilenameNoExt(f):
|
def FilenameNoExt(f):
|
||||||
|
|
@ -384,10 +386,10 @@ Possible Commands:
|
||||||
boot [options] bootstraps with given command line options
|
boot [options] bootstraps with given command line options
|
||||||
rodsrc generates Nimrod version from Pascal version
|
rodsrc generates Nimrod version from Pascal version
|
||||||
web generates the website
|
web generates the website
|
||||||
profile profile the Nimrod compiler
|
profile profiles the Nimrod compiler
|
||||||
csource [options] build the C sources for installation
|
csource [options] builds the C sources for installation
|
||||||
zip build the installation ZIP package
|
zip builds the installation ZIP package
|
||||||
inno build the Inno Setup installer
|
inno builds the Inno Setup installer
|
||||||
""", NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
|
""", NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
|
|
@ -634,7 +636,6 @@ def getOSandProcessor():
|
||||||
return (host, processor)
|
return (host, processor)
|
||||||
|
|
||||||
def writePlatdefC(nimrodpath):
|
def writePlatdefC(nimrodpath):
|
||||||
import os
|
|
||||||
host, processor = getOSandProcessor()
|
host, processor = getOSandProcessor()
|
||||||
f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+")
|
f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+")
|
||||||
f.write(Subs('/* Generated by koch.py */\n'
|
f.write(Subs('/* Generated by koch.py */\n'
|
||||||
|
|
|
||||||
0
lib/copying.txt
Normal file → Executable file
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.
|
## tree (`AST`:idx:). Macros operate on this tree.
|
||||||
|
|
||||||
## .. include:: ../doc/astspec.txt
|
## .. include:: ../doc/astspec.txt
|
||||||
|
|
||||||
#[[[cog
|
#[[[cog
|
||||||
#def toEnum(name, elems):
|
#def toEnum(name, elems):
|
||||||
|
|
@ -39,38 +39,38 @@ type
|
||||||
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
|
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
|
||||||
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
|
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
|
||||||
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
|
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
|
||||||
nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall,
|
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
|
||||||
nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple,
|
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
|
||||||
nnkInfix, nnkPrefix, nnkPostfix, nnkPar,
|
nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
|
||||||
nnkCurly, nnkBracket, nnkBracketExpr, nnkPragmaExpr,
|
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
||||||
nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr,
|
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||||
nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda,
|
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
|
||||||
nnkAccQuoted, nnkTableConstr, nnkQualified, nnkBind,
|
nnkTableConstr, nnkQualified, nnkBind, nnkSymChoice,
|
||||||
nnkSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv,
|
nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv,
|
||||||
nnkConv, nnkCast, nnkAddr, nnkHiddenAddr,
|
nnkCast, nnkAddr, nnkHiddenAddr, nnkHiddenDeref,
|
||||||
nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF,
|
nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64,
|
||||||
nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString,
|
nnkChckRange, nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray,
|
||||||
nnkPassAsOpenArray, nnkAsgn, nnkFastAsgn, nnkDefaultTypeParam,
|
nnkAsgn, nnkFastAsgn, nnkGenericParams, nnkFormalParams,
|
||||||
nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkModule,
|
nnkOfInherit, nnkModule, nnkProcDef, nnkConverterDef,
|
||||||
nnkProcDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef,
|
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
||||||
nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch,
|
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
|
||||||
nnkElse, nnkMacroStmt, nnkAsmStmt, nnkPragma,
|
nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt,
|
||||||
nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkWhileStmt,
|
nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection,
|
||||||
nnkCaseStmt, nnkVarSection, nnkConstSection, nnkConstDef,
|
nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef,
|
||||||
nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkTryStmt,
|
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
|
||||||
nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt,
|
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
|
||||||
nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkStmtList,
|
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
|
||||||
nnkImportStmt, nnkFromStmt, nnkImportAs, nnkIncludeStmt,
|
nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
||||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType,
|
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
|
||||||
nnkBlockType, nnkVm, nnkTypeOfExpr, nnkObjectTy,
|
|
||||||
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
||||||
nnkRefTy, nnkPtrTy, nnkVarTy, nnkAbstractTy,
|
nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy,
|
||||||
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
||||||
TNimNodeKinds* = set[TNimrodNodeKind]
|
TNimNodeKinds* = set[TNimrodNodeKind]
|
||||||
TNimrodTypeKind* = enum
|
TNimrodTypeKind* = enum
|
||||||
ntyNone, ntyBool, ntyChar, ntyEmpty,
|
ntyNone, ntyBool, ntyChar, ntyEmpty,
|
||||||
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
|
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
|
||||||
ntyGenericParam, ntyAbstract, ntyEnum, ntyOrdinal,
|
ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
|
||||||
|
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
|
||||||
ntyArray, ntyObject, ntyTuple, ntySet,
|
ntyArray, ntyObject, ntyTuple, ntySet,
|
||||||
ntyRange, ntyPtr, ntyRef, ntyVar,
|
ntyRange, ntyPtr, ntyRef, ntyVar,
|
||||||
ntySequence, ntyProc, ntyPointer, ntyOpenArray,
|
ntySequence, ntyProc, ntyPointer, ntyOpenArray,
|
||||||
|
|
@ -79,8 +79,8 @@ type
|
||||||
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
|
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
|
||||||
TNimTypeKinds* = set[TNimrodTypeKind]
|
TNimTypeKinds* = set[TNimrodTypeKind]
|
||||||
TNimrodSymKind* = enum
|
TNimrodSymKind* = enum
|
||||||
nskUnknownSym, nskConditional, nskDynLib, nskParam,
|
nskUnknown, nskConditional, nskDynLib, nskParam,
|
||||||
nskTypeParam, nskTemp, nskType, nskConst,
|
nskGenericParam, nskTemp, nskType, nskConst,
|
||||||
nskVar, nskProc, nskIterator, nskConverter,
|
nskVar, nskProc, nskIterator, nskConverter,
|
||||||
nskMacro, nskTemplate, nskField, nskEnumField,
|
nskMacro, nskTemplate, nskField, nskEnumField,
|
||||||
nskForVar, nskModule, nskLabel, nskStub
|
nskForVar, nskModule, nskLabel, nskStub
|
||||||
|
|
@ -91,7 +91,6 @@ type
|
||||||
TNimrodIdent = object of TObject
|
TNimrodIdent = object of TObject
|
||||||
## represents a Nimrod identifier in the AST
|
## represents a Nimrod identifier in the AST
|
||||||
|
|
||||||
TNimrodNode {.final.} = object # hidden
|
|
||||||
TNimrodSymbol {.final.} = object # hidden
|
TNimrodSymbol {.final.} = object # hidden
|
||||||
TNimrodType {.final.} = object # hidden
|
TNimrodType {.final.} = object # hidden
|
||||||
|
|
||||||
|
|
@ -103,12 +102,9 @@ type
|
||||||
## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up
|
## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up
|
||||||
## *ident*.
|
## *ident*.
|
||||||
|
|
||||||
PNimrodNode* {.compilerproc.} = ref TNimrodNode
|
PNimrodNode* = expr
|
||||||
## represents a Nimrod AST node. Macros operate on this type.
|
## represents a Nimrod AST node. Macros operate on this type.
|
||||||
|
|
||||||
expr* = PNimrodNode
|
|
||||||
stmt* = PNimrodNode
|
|
||||||
|
|
||||||
# Nodes should be reference counted to make the `copy` operation very fast!
|
# Nodes should be reference counted to make the `copy` operation very fast!
|
||||||
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
|
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
|
||||||
# its father. How to do this without back references?
|
# its father. How to do this without back references?
|
||||||
|
|
@ -119,7 +115,7 @@ proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
|
||||||
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
||||||
## set `n`'s `i`'th child to `child`.
|
## set `n`'s `i`'th child to `child`.
|
||||||
|
|
||||||
proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
||||||
## constructs an identifier from the string `s`
|
## constructs an identifier from the string `s`
|
||||||
|
|
||||||
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
||||||
|
|
@ -159,8 +155,8 @@ proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".}
|
||||||
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
|
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
|
||||||
|
|
||||||
proc newNimNode*(kind: TNimrodNodeKind,
|
proc newNimNode*(kind: TNimrodNodeKind,
|
||||||
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
||||||
|
|
||||||
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
|
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
|
||||||
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
|
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
|
||||||
|
|
||||||
|
|
@ -192,11 +188,11 @@ proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
|
||||||
## creates an identifier node from `i`
|
## creates an identifier node from `i`
|
||||||
result = newNimNode(nnkIdent)
|
result = newNimNode(nnkIdent)
|
||||||
result.ident = i
|
result.ident = i
|
||||||
|
|
||||||
proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
|
proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
|
||||||
## creates an identifier node from `i`
|
## creates an identifier node from `i`
|
||||||
result = newNimNode(nnkIdent)
|
result = newNimNode(nnkIdent)
|
||||||
result.ident = !i
|
result.ident = !i
|
||||||
|
|
||||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## converts the AST `n` to the concrete Nimrod code and wraps that
|
## converts the AST `n` to the concrete Nimrod code and wraps that
|
||||||
|
|
@ -227,7 +223,7 @@ proc newCall*(theProc: TNimrodIdent,
|
||||||
## the arguments ``args[0..]``.
|
## the arguments ``args[0..]``.
|
||||||
result = newNimNode(nnkCall)
|
result = newNimNode(nnkCall)
|
||||||
result.add(newIdentNode(theProc))
|
result.add(newIdentNode(theProc))
|
||||||
result.add(args)
|
result.add(args)
|
||||||
|
|
||||||
proc newCall*(theProc: string,
|
proc newCall*(theProc: string,
|
||||||
args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
|
args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
|
||||||
|
|
@ -236,14 +232,14 @@ proc newCall*(theProc: string,
|
||||||
result = newNimNode(nnkCall)
|
result = newNimNode(nnkCall)
|
||||||
result.add(newIdentNode(theProc))
|
result.add(newIdentNode(theProc))
|
||||||
result.add(args)
|
result.add(args)
|
||||||
|
|
||||||
proc nestList*(theProc: TNimrodIdent,
|
proc nestList*(theProc: TNimrodIdent,
|
||||||
x: PNimrodNode): PNimrodNode {.compileTime.} =
|
x: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## nests the list `x` into a tree of call expressions:
|
## nests the list `x` into a tree of call expressions:
|
||||||
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
|
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
|
||||||
var L = x.len
|
var L = x.len
|
||||||
result = newCall(theProc, x[L-2], x[L-1])
|
result = newCall(theProc, x[L-2], x[L-1])
|
||||||
var a = result
|
var a = result
|
||||||
for i in countdown(L-3, 0):
|
for i in countdown(L-3, 0):
|
||||||
a = newCall(theProc, x[i], copyNimTree(a))
|
a = newCall(theProc, x[i], copyNimTree(a))
|
||||||
|
|
||||||
|
|
|
||||||
10
lib/pure/math.nim
Normal file → Executable file
10
lib/pure/math.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2009 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -83,10 +83,12 @@ proc nextPowerOfTwo*(x: int): int =
|
||||||
result = result or (result shr 1)
|
result = result or (result shr 1)
|
||||||
Inc(result)
|
Inc(result)
|
||||||
|
|
||||||
proc countBits*(n: int32): int {.noSideEffect.}
|
proc countBits32*(n: int32): int {.noSideEffect.} =
|
||||||
## counts the set bits in `n`.
|
## counts the set bits in `n`.
|
||||||
|
var v = n
|
||||||
include "system/cntbits"
|
v = v -% ((v shr 1'i32) and 0x55555555'i32)
|
||||||
|
v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32)
|
||||||
|
result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32
|
||||||
|
|
||||||
proc sum*[T](x: openarray[T]): T {.noSideEffect.} =
|
proc sum*[T](x: openarray[T]): T {.noSideEffect.} =
|
||||||
## computes the sum of the elements in `x`.
|
## computes the sum of the elements in `x`.
|
||||||
|
|
|
||||||
0
lib/pure/md5.nim
Normal file → Executable file
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
|
## The character used by the operating system to separate pathname
|
||||||
## components, for example, '/' for POSIX or ':' for the classic
|
## components, for example, '/' for POSIX or ':' for the classic
|
||||||
## Macintosh.
|
## Macintosh.
|
||||||
##
|
|
||||||
## Note that knowing this is not sufficient to be able to parse or
|
|
||||||
## concatenate pathnames -- use `splitPath` and `joinPath` instead --
|
|
||||||
## but it is occasionally useful.
|
|
||||||
|
|
||||||
AltSep* = '/'
|
AltSep* = '/'
|
||||||
## An alternative character used by the operating system to separate
|
## An alternative character used by the operating system to separate
|
||||||
|
|
@ -80,10 +76,10 @@ when defined(Nimdoc): # only for proper documentation:
|
||||||
|
|
||||||
ExeExt* = ""
|
ExeExt* = ""
|
||||||
## The file extension of native executables. For example:
|
## The file extension of native executables. For example:
|
||||||
## "" on UNIX, "exe" on Windows.
|
## "" for POSIX, "exe" on Windows.
|
||||||
|
|
||||||
ScriptExt* = ""
|
ScriptExt* = ""
|
||||||
## The file extension of a script file. For example: "" on UNIX,
|
## The file extension of a script file. For example: "" for POSIX,
|
||||||
## "bat" on Windows.
|
## "bat" on Windows.
|
||||||
|
|
||||||
elif defined(macos):
|
elif defined(macos):
|
||||||
|
|
@ -111,7 +107,7 @@ elif defined(macos):
|
||||||
# In full paths the first name (e g HD above) is the name of a mounted
|
# In full paths the first name (e g HD above) is the name of a mounted
|
||||||
# volume.
|
# volume.
|
||||||
# These names are not unique, because, for instance, two diskettes with the
|
# These names are not unique, because, for instance, two diskettes with the
|
||||||
# same names could be inserted. This means that paths on MacOS is not
|
# same names could be inserted. This means that paths on MacOS are not
|
||||||
# waterproof. In case of equal names the first volume found will do.
|
# waterproof. In case of equal names the first volume found will do.
|
||||||
# Two colons "::" are the relative path to the parent. Three is to the
|
# Two colons "::" are the relative path to the parent. Three is to the
|
||||||
# grandparent etc.
|
# grandparent etc.
|
||||||
|
|
@ -551,7 +547,7 @@ proc sameFile*(path1, path2: string): bool =
|
||||||
|
|
||||||
proc sameFileContent*(path1, path2: string): bool =
|
proc sameFileContent*(path1, path2: string): bool =
|
||||||
## Returns True if both pathname arguments refer to files with identical
|
## Returns True if both pathname arguments refer to files with identical
|
||||||
## content. Content is compared byte for byte.
|
## binary content.
|
||||||
const
|
const
|
||||||
bufSize = 8192 # 8K buffer
|
bufSize = 8192 # 8K buffer
|
||||||
var
|
var
|
||||||
|
|
@ -712,7 +708,7 @@ proc putEnv*(key, val: string) =
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
iterator iterOverEnvironment*(): tuple[key, value: string] =
|
iterator iterOverEnvironment*(): tuple[key, value: string] =
|
||||||
## Iterate over all environments varialbes. In the first component of the
|
## Iterate over all environments variables. In the first component of the
|
||||||
## tuple is the name of the current variable stored, in the second its value.
|
## tuple is the name of the current variable stored, in the second its value.
|
||||||
getEnvVarsC()
|
getEnvVarsC()
|
||||||
for i in 0..high(environment):
|
for i in 0..high(environment):
|
||||||
|
|
@ -760,7 +756,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
|
||||||
## walks over the directory `dir` and yields for each directory or file in
|
## walks over the directory `dir` and yields for each directory or file in
|
||||||
## `dir`. The component type and full path for each item is returned.
|
## `dir`. The component type and full path for each item is returned.
|
||||||
## Walking is not recursive.
|
## Walking is not recursive.
|
||||||
## Example: Assuming this directory structure::
|
## Example: This directory structure::
|
||||||
## dirA / dirB / fileB1.txt
|
## dirA / dirB / fileB1.txt
|
||||||
## / dirC
|
## / dirC
|
||||||
## / fileA1.txt
|
## / fileA1.txt
|
||||||
|
|
|
||||||
0
lib/pure/osproc.nim
Normal file → Executable file
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) =
|
proc sqlError(p: TSqlParser, msg: string) =
|
||||||
var e: ref EInvalidSql
|
var e: ref EInvalidSql
|
||||||
|
new(e)
|
||||||
e.msg = errorStr(p, msg)
|
e.msg = errorStr(p, msg)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
|
||||||
0
lib/pure/parsexml.nim
Normal file → Executable file
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
|
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
|
||||||
## substrings in the array ``matches``. If it does not match, nothing
|
## substrings in the array ``matches``. If it does not match, nothing
|
||||||
## is written into ``matches``.
|
## is written into ``matches``.
|
||||||
|
|
||||||
proc find*(s, pattern: string, start: int = 0): bool
|
proc find*(s, pattern: string, start: int = 0): bool
|
||||||
## returns ``true`` if ``pattern`` occurs in ``s``.
|
## returns ``true`` if ``pattern`` occurs in ``s``.
|
||||||
|
|
||||||
|
|
||||||
proc rawCompile(pattern: string, flags: cint): PPcre =
|
proc rawCompile(pattern: string, flags: cint): PPcre =
|
||||||
var
|
var
|
||||||
msg: CString
|
msg: CString
|
||||||
|
|
|
||||||
4
lib/pure/streams.nim
Normal file → Executable file
4
lib/pure/streams.nim
Normal file → Executable file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2009 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -42,7 +42,7 @@ proc write*(s: PStream, x: string) =
|
||||||
s.writeData(s, cstring(x), x.len)
|
s.writeData(s, cstring(x), x.len)
|
||||||
|
|
||||||
proc read[T](s: PStream, result: var T) =
|
proc read[T](s: PStream, result: var T) =
|
||||||
## generic write procedure. Reads `result` from the stream `s`.
|
## generic read procedure. Reads `result` from the stream `s`.
|
||||||
if s.readData(s, addr(result), sizeof(T)) != sizeof(T):
|
if s.readData(s, addr(result), sizeof(T)) != sizeof(T):
|
||||||
raise newEIO("cannot read from stream")
|
raise newEIO("cannot read from stream")
|
||||||
|
|
||||||
|
|
|
||||||
0
lib/pure/strtabs.nim
Normal file → Executable file
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
|
type
|
||||||
TCharSet* = set[char] # for compability for Nim
|
TCharSet* = set[char] # for compability with Nim
|
||||||
|
|
||||||
const
|
const
|
||||||
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
||||||
|
|
@ -45,9 +45,9 @@ const
|
||||||
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
|
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
|
||||||
## the set of characters an identifier can start with
|
## the set of characters an identifier can start with
|
||||||
|
|
||||||
strStart* = 0 # this is only for bootstraping
|
strStart* = 0 ## this is only for bootstraping
|
||||||
# XXX: remove this someday
|
## XXX: remove this someday
|
||||||
nl* = "\n" # this is only for bootstraping XXX: remove this somehow
|
nl* = "\n" ## this is only for bootstraping XXX: remove this somehow
|
||||||
|
|
||||||
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
||||||
## The `substitution`:idx: operator performs string substitutions in
|
## The `substitution`:idx: operator performs string substitutions in
|
||||||
|
|
@ -64,8 +64,13 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## "The cat eats fish."
|
## "The cat eats fish."
|
||||||
##
|
##
|
||||||
## The substitution variables (the thing after the ``$``)
|
## The substitution variables (the thing after the ``$``) are enumerated
|
||||||
## are enumerated from 1 to 9.
|
## from 1 to ``a.len``.
|
||||||
|
## The notation ``$#`` can be used to refer to the next substitution variable:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## "$# eats $#." % ["The cat", "fish"]
|
||||||
|
##
|
||||||
## Substitution variables can also be words (that is
|
## Substitution variables can also be words (that is
|
||||||
## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even
|
## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even
|
||||||
## indices are keys and with odd indices are the corresponding values.
|
## indices are keys and with odd indices are the corresponding values.
|
||||||
|
|
@ -267,19 +272,43 @@ iterator splitLines*(s: string): string =
|
||||||
else: break # was '\0'
|
else: break # was '\0'
|
||||||
first = last
|
first = last
|
||||||
|
|
||||||
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect.} =
|
template iterToProc(iter: expr): stmt =
|
||||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
|
||||||
result = @[]
|
result = @[]
|
||||||
for line in splitLines(s): add(result, line)
|
for x in iter: add(result, x)
|
||||||
|
|
||||||
|
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect, deprecated.} =
|
||||||
|
## The same as `splitLines`, but is a proc that returns a sequence
|
||||||
|
## of substrings.
|
||||||
|
## **Deprecated since version 0.8.0**: Use `splitLines` instead.
|
||||||
|
iterToProc(splitLines(s))
|
||||||
|
|
||||||
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
|
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
|
||||||
noSideEffect.}
|
noSideEffect, deprecated.} =
|
||||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||||
|
## **Deprecated since version 0.8.0**: Use `split` instead.
|
||||||
|
iterToProc(split(s, seps))
|
||||||
|
|
||||||
proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect.} =
|
proc splitSeq*(s: string, sep: char): seq[string] {.noSideEffect,
|
||||||
|
deprecated.} =
|
||||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||||
result = @[]
|
## **Deprecated since version 0.8.0**: Use `split` instead.
|
||||||
for sub in split(s, sep): add(result, sub)
|
iterToProc(split(s, sep))
|
||||||
|
|
||||||
|
proc splitLines*(s: string): seq[string] {.noSideEffect.} =
|
||||||
|
## The same as the `splitLines` iterator, but is a proc that returns a
|
||||||
|
## sequence of substrings.
|
||||||
|
iterToProc(splitLines(s))
|
||||||
|
|
||||||
|
proc split*(s: string, seps: set[char] = Whitespace): seq[string] {.
|
||||||
|
noSideEffect.} =
|
||||||
|
## The same as the `split` iterator, but is a proc that returns a
|
||||||
|
## sequence of substrings.
|
||||||
|
iterToProc(split(s, seps))
|
||||||
|
|
||||||
|
proc split*(s: string, sep: char): seq[string] {.noSideEffect.} =
|
||||||
|
## The same as the `split` iterator, but is a proc that returns a sequence
|
||||||
|
## of substrings.
|
||||||
|
iterToProc(split(s, sep))
|
||||||
|
|
||||||
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.}
|
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.}
|
||||||
## Compares two strings in a case insensitive manner. Returns:
|
## Compares two strings in a case insensitive manner. Returns:
|
||||||
|
|
@ -308,7 +337,7 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.}
|
||||||
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.}
|
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.}
|
||||||
## Converts `x` to its hexadecimal representation. The resulting string
|
## Converts `x` to its hexadecimal representation. The resulting string
|
||||||
## will be exactly `len` characters long. No prefix like ``0x``
|
## will be exactly `len` characters long. No prefix like ``0x``
|
||||||
## is generated. `x` is treated as unsigned value.
|
## is generated. `x` is treated as an unsigned value.
|
||||||
|
|
||||||
proc intToStr*(x: int, minchars: int = 1): string
|
proc intToStr*(x: int, minchars: int = 1): string
|
||||||
## Converts `x` to its decimal representation. The resulting string
|
## Converts `x` to its decimal representation. The resulting string
|
||||||
|
|
@ -367,7 +396,7 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
|
||||||
proc allCharsInSet*(s: string, theSet: TCharSet): bool =
|
proc allCharsInSet*(s: string, theSet: TCharSet): bool =
|
||||||
## returns true iff each character of `s` is in the set `theSet`.
|
## returns true iff each character of `s` is in the set `theSet`.
|
||||||
for c in items(s):
|
for c in items(s):
|
||||||
if not (c in theSet): return false
|
if c notin theSet: return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc quoteIfContainsWhite*(s: string): string =
|
proc quoteIfContainsWhite*(s: string): string =
|
||||||
|
|
@ -397,12 +426,12 @@ proc endsWith(s, suffix: string): bool =
|
||||||
when false:
|
when false:
|
||||||
proc abbrev(s: string, possibilities: openarray[string]): int =
|
proc abbrev(s: string, possibilities: openarray[string]): int =
|
||||||
## returns the index of the first item in `possibilities` if not
|
## returns the index of the first item in `possibilities` if not
|
||||||
## ambigious; -1 if no item has been found; -2 if multiple items
|
## ambiguous; -1 if no item has been found; -2 if multiple items
|
||||||
## match.
|
## match.
|
||||||
result = -1 # none found
|
result = -1 # none found
|
||||||
for i in 0..possibilities.len-1:
|
for i in 0..possibilities.len-1:
|
||||||
if possibilities[i].startsWith(s):
|
if possibilities[i].startsWith(s):
|
||||||
if result >= 0: return -2 # ambigious
|
if result >= 0: return -2 # ambiguous
|
||||||
result = i
|
result = i
|
||||||
|
|
||||||
proc repeatChar(count: int, c: Char = ' '): string =
|
proc repeatChar(count: int, c: Char = ' '): string =
|
||||||
|
|
@ -509,12 +538,6 @@ proc cmpIgnoreStyle(a, b: string): int =
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
# ---------- splitting -----------------------------------------------------
|
|
||||||
|
|
||||||
proc splitSeq(s: string, seps: set[char]): seq[string] =
|
|
||||||
result = @[]
|
|
||||||
for sub in split(s, seps): add result, sub
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
proc join*(a: openArray[string], sep: string): string =
|
proc join*(a: openArray[string], sep: string): string =
|
||||||
|
|
@ -732,7 +755,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
|
||||||
# one more valid negative than prositive integer. Thus we perform the
|
# one more valid negative than prositive integer. Thus we perform the
|
||||||
# computation as a negative number and then change the sign at the end.
|
# computation as a negative number and then change the sign at the end.
|
||||||
var
|
var
|
||||||
i: int = index # a local i is more efficient than accessing a var parameter
|
i = index # a local i is more efficient than accessing a var parameter
|
||||||
sign: BiggestInt = -1
|
sign: BiggestInt = -1
|
||||||
if s[i] == '+':
|
if s[i] == '+':
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
@ -758,7 +781,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
|
||||||
|
|
||||||
proc parseInt(s: string): int =
|
proc parseInt(s: string): int =
|
||||||
var
|
var
|
||||||
index: int = 0
|
index = 0
|
||||||
res = rawParseInt(s, index)
|
res = rawParseInt(s, index)
|
||||||
if index == -1:
|
if index == -1:
|
||||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||||
|
|
|
||||||
0
lib/pure/terminal.nim
Normal file → Executable file
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):
|
when defined(posix):
|
||||||
type
|
type
|
||||||
TTime* = abstract int ## abstract type that represents a time
|
TTime* = distinct int ## distinct type that represents a time
|
||||||
elif defined(windows):
|
elif defined(windows):
|
||||||
when defined(vcc):
|
when defined(vcc):
|
||||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
# newest version of Visual C++ defines time_t to be of 64 bits
|
||||||
type TTime* = abstract int64
|
type TTime* = distinct int64
|
||||||
else:
|
else:
|
||||||
type TTime* = abstract int32
|
type TTime* = distinct int32
|
||||||
elif defined(ECMAScript):
|
elif defined(ECMAScript):
|
||||||
type
|
type
|
||||||
TTime* {.final.} = object
|
TTime* {.final.} = object
|
||||||
|
|
|
||||||
0
lib/pure/unicode.nim
Normal file → Executable file
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
|
type
|
||||||
`nil` {.magic: "Nil".}
|
`nil` {.magic: "Nil".}
|
||||||
|
expr* {.magic: Expr.} ## meta type to denote an expression (for templates)
|
||||||
|
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
|
||||||
|
typeDesc* {.magic: TypeDesc.} ## meta type to denote
|
||||||
|
## a type description (for templates)
|
||||||
|
|
||||||
proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.}
|
proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
|
||||||
## Special comile-time procedure that checks whether `x` is
|
## Special comile-time procedure that checks whether `x` is
|
||||||
## defined. `x` has to be an identifier or a qualified identifier.
|
## defined. `x` has to be an identifier or a qualified identifier.
|
||||||
## This can be used to check whether a library provides a certain
|
## This can be used to check whether a library provides a certain
|
||||||
|
|
@ -54,6 +58,12 @@ proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.}
|
||||||
## # provide our own toUpper proc here, because strutils is
|
## # provide our own toUpper proc here, because strutils is
|
||||||
## # missing it.
|
## # missing it.
|
||||||
|
|
||||||
|
proc definedInScope*[T](x: T, scope=0): bool {.
|
||||||
|
magic: "DefinedInScope", noSideEffect.}
|
||||||
|
## Special comile-time procedure that checks whether `x` is
|
||||||
|
## defined in the scope `scope`. `x` has to be an identifier.
|
||||||
|
## 0 means the current scope, 1 means the scope above the current scope, etc.
|
||||||
|
|
||||||
# these require compiler magic:
|
# these require compiler magic:
|
||||||
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
|
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
|
||||||
## Boolean not; returns true iff ``x == false``.
|
## Boolean not; returns true iff ``x == false``.
|
||||||
|
|
@ -434,30 +444,6 @@ proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.}
|
||||||
## is -MININT for its type), an overflow exception is thrown (if overflow
|
## is -MININT for its type), an overflow exception is thrown (if overflow
|
||||||
## checking is turned on).
|
## checking is turned on).
|
||||||
|
|
||||||
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
|
|
||||||
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
|
|
||||||
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
|
|
||||||
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.}
|
|
||||||
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
|
|
||||||
## The minimum value of two integers.
|
|
||||||
|
|
||||||
proc min*[T](x: openarray[T]): T =
|
|
||||||
## The minimum value of an openarray.
|
|
||||||
result = x[0]
|
|
||||||
for i in 1..high(x): result = min(result, x[i])
|
|
||||||
|
|
||||||
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
|
|
||||||
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.}
|
|
||||||
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.}
|
|
||||||
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.}
|
|
||||||
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
|
|
||||||
## The maximum value of two integers.
|
|
||||||
|
|
||||||
proc max*[T](x: openarray[T]): T =
|
|
||||||
## The maximum value of an openarray.
|
|
||||||
result = x[0]
|
|
||||||
for i in 1..high(x): result = max(result, x[i])
|
|
||||||
|
|
||||||
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
|
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
|
||||||
proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.}
|
proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.}
|
||||||
proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.}
|
proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.}
|
||||||
|
|
@ -613,7 +599,7 @@ template `not_in` * (x, y: expr): expr = not contains(y, x)
|
||||||
proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
|
proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
|
||||||
template `is_not` *(x, y: expr): expr = not (x is y)
|
template `is_not` *(x, y: expr): expr = not (x is y)
|
||||||
|
|
||||||
proc cmp*[T](x, y: T): int =
|
proc cmp*[T, S: typeDesc](x: T, y: S): int =
|
||||||
## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y
|
## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y
|
||||||
## and 0 iff x == y. This is useful for writing generic algorithms without
|
## and 0 iff x == y. This is useful for writing generic algorithms without
|
||||||
## performance loss. This generic implementation uses the `==` and `<`
|
## performance loss. This generic implementation uses the `==` and `<`
|
||||||
|
|
@ -999,6 +985,32 @@ iterator countup*[T](a, b: T, step = 1): T {.inline.} =
|
||||||
# we cannot use ``for x in a..b: `` here, because that is not
|
# we cannot use ``for x in a..b: `` here, because that is not
|
||||||
# known in the System module
|
# known in the System module
|
||||||
|
|
||||||
|
|
||||||
|
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
|
||||||
|
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
|
||||||
|
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
|
||||||
|
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.}
|
||||||
|
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
|
||||||
|
## The minimum value of two integers.
|
||||||
|
|
||||||
|
proc min*[T](x: openarray[T]): T =
|
||||||
|
## The minimum value of an openarray.
|
||||||
|
result = x[0]
|
||||||
|
for i in 1..high(x): result = min(result, x[i])
|
||||||
|
|
||||||
|
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
|
||||||
|
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.}
|
||||||
|
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.}
|
||||||
|
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.}
|
||||||
|
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
|
||||||
|
## The maximum value of two integers.
|
||||||
|
|
||||||
|
proc max*[T](x: openarray[T]): T =
|
||||||
|
## The maximum value of an openarray.
|
||||||
|
result = x[0]
|
||||||
|
for i in 1..high(x): result = max(result, x[i])
|
||||||
|
|
||||||
|
|
||||||
iterator items*[T](a: openarray[T]): T {.inline.} =
|
iterator items*[T](a: openarray[T]): T {.inline.} =
|
||||||
## iterates over each item of `a`.
|
## iterates over each item of `a`.
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -1009,9 +1021,11 @@ iterator items*[T](a: openarray[T]): T {.inline.} =
|
||||||
iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
|
iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
|
||||||
## iterates over each item of `a`.
|
## iterates over each item of `a`.
|
||||||
var i = low(IX)
|
var i = low(IX)
|
||||||
while i <= high(IX):
|
if i <= high(IX):
|
||||||
yield a[i]
|
while true:
|
||||||
inc(i)
|
yield a[i]
|
||||||
|
if i >= high(IX): break
|
||||||
|
inc(i)
|
||||||
|
|
||||||
iterator items*[T](a: seq[T]): T {.inline.} =
|
iterator items*[T](a: seq[T]): T {.inline.} =
|
||||||
## iterates over each item of `a`.
|
## iterates over each item of `a`.
|
||||||
|
|
@ -1032,9 +1046,11 @@ iterator items*[T](a: set[T]): T {.inline.} =
|
||||||
## elements that are really in the set (and not over the ones the set is
|
## elements that are really in the set (and not over the ones the set is
|
||||||
## able to hold).
|
## able to hold).
|
||||||
var i = low(T)
|
var i = low(T)
|
||||||
while i <= high(T):
|
if i <= high(T):
|
||||||
if i in a: yield i
|
while true:
|
||||||
inc(i)
|
if i in a: yield i
|
||||||
|
if i >= high(T): break
|
||||||
|
inc(i)
|
||||||
|
|
||||||
iterator items*(a: cstring): char {.inline.} =
|
iterator items*(a: cstring): char {.inline.} =
|
||||||
## iterates over each item of `a`.
|
## iterates over each item of `a`.
|
||||||
|
|
@ -1082,14 +1098,13 @@ proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(NimrodVM):
|
||||||
when not defined(ECMAScript):
|
when not defined(ECMAScript):
|
||||||
# XXX make this local procs
|
proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} =
|
||||||
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
|
|
||||||
result = cast[pointer](x)
|
result = cast[pointer](x)
|
||||||
else:
|
else:
|
||||||
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
|
proc seqToPtr[T](x: seq[T]): pointer {.pure, nosideeffect.} =
|
||||||
asm """return `x`"""
|
asm """return `x`"""
|
||||||
|
|
||||||
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
|
proc `==` *[T: typeDesc](x, y: seq[T]): bool {.noSideEffect.} =
|
||||||
## Generic equals operator for sequences: relies on a equals operator for
|
## Generic equals operator for sequences: relies on a equals operator for
|
||||||
## the element type `T`.
|
## the element type `T`.
|
||||||
if seqToPtr(x) == seqToPtr(y):
|
if seqToPtr(x) == seqToPtr(y):
|
||||||
|
|
@ -1101,10 +1116,9 @@ when not defined(NimrodVM):
|
||||||
if x[i] != y[i]: return false
|
if x[i] != y[i]: return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc find*[T, S](a: T, item: S): int {.inline.} =
|
proc find*[T, S: typeDesc](a: T, item: S): int {.inline.}=
|
||||||
## Returns the first index of `item` in `a` or -1 if not found. This requires
|
## Returns the first index of `item` in `a` or -1 if not found. This requires
|
||||||
## appropriate `==` and `items` procs to work.
|
## appropriate `items` and `==` procs to work.
|
||||||
result = 0
|
|
||||||
for i in items(a):
|
for i in items(a):
|
||||||
if i == item: return
|
if i == item: return
|
||||||
inc(result)
|
inc(result)
|
||||||
|
|
@ -1437,6 +1451,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
include "system/arithm"
|
include "system/arithm"
|
||||||
{.pop.} # stack trace
|
{.pop.} # stack trace
|
||||||
include "system/dyncalls"
|
include "system/dyncalls"
|
||||||
|
include "system/sets"
|
||||||
|
|
||||||
const
|
const
|
||||||
GenericSeqSize = (2 * sizeof(int))
|
GenericSeqSize = (2 * sizeof(int))
|
||||||
|
|
|
||||||
0
lib/system/alloc.nim
Normal file → Executable file
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
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2006 Andreas Rumpf
|
# (c) Copyright 2009 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
0
lib/system/cellsets.nim
Normal file → Executable file
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
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2009 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
# with the application. We should not use dynamic memory here as that
|
# with the application. We should not use dynamic memory here as that
|
||||||
# would interfere with the GC and trigger ON/OFF errors if the
|
# would interfere with the GC and trigger ON/OFF errors if the
|
||||||
# user program corrupts memory. Unfortunately, for dispaying
|
# user program corrupts memory. Unfortunately, for dispaying
|
||||||
# variables we use the system.repr() proc which uses Nimrod
|
# variables we use the ``system.repr()`` proc which uses Nimrod
|
||||||
# strings and thus allocates memory from the heap. Pity, but
|
# strings and thus allocates memory from the heap. Pity, but
|
||||||
# I do not want to implement repr() twice. We also cannot deactivate
|
# I do not want to implement ``repr()`` twice. We also cannot deactivate
|
||||||
# the GC here as that might run out of memory too quickly...
|
# the GC here as that might run out of memory too quickly...
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue