mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 13:33:22 +00:00
overload resolution for proc vars
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
#
|
||||
|
||||
{
|
||||
'SymFlag': [ # already 28 flags!
|
||||
'SymFlag': [ # already 29 flags!
|
||||
'sfUsed', # read access of sym (for warnings) or simply used
|
||||
'sfStar', # symbol has * visibility
|
||||
'sfMinus', # symbol has - visibility
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
'sfResult', # variable is 'result' in proc
|
||||
'sfNoSideEffect', # proc has no side effects
|
||||
'sfSideEffect', # proc may have side effects; cannot prove it has none
|
||||
'sfMainModule', # module is the main module
|
||||
'sfSystemModule', # module is the system module
|
||||
'sfNoReturn', # proc never returns (an exit proc)
|
||||
@@ -47,6 +48,7 @@
|
||||
|
||||
'TypeFlag': [
|
||||
'tfVarargs', # procedure has C styled varargs
|
||||
'tfNoSideEffect', # procedure type does not allow side effects
|
||||
'tfFinal', # is the object final?
|
||||
'tfAcyclic', # type is acyclic (for GC optimization)
|
||||
'tfEnumHasWholes' # enum cannot be mapped into a range
|
||||
@@ -146,10 +148,11 @@
|
||||
'nkElseExpr',
|
||||
'nkLambda', # lambda expression
|
||||
'nkAccQuoted', # `a` as a node
|
||||
'nkHeaderQuoted', # `a(x: int)` as a node
|
||||
|
||||
'nkTableConstr', # a table constructor {expr: expr}
|
||||
'nkQualified', # describes a.b for qualified identifiers
|
||||
'nkBind', # ``bind expr`` node
|
||||
'nkSymChoice', # symbol choice node
|
||||
'nkHiddenStdConv', # an implicit standard type conversion
|
||||
'nkHiddenSubConv', # an implicit type conversion from a subtype
|
||||
# to a supertype
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
abstract addr and as asm
|
||||
block break
|
||||
bind block break
|
||||
case cast const continue converter
|
||||
discard div
|
||||
elif else end enum except exception
|
||||
elif else end enum except
|
||||
finally for from generic
|
||||
if implies import in include is isnot iterator
|
||||
lambda
|
||||
|
||||
@@ -36,19 +36,15 @@
|
||||
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
||||
{'errInvalidPragma': 'invalid pragma'},
|
||||
{'errUnknownPragma': "unknown pragma: '$1'"},
|
||||
{'errPragmaXHereNotAllowed': "pragma '$1' here not allowed"},
|
||||
{'errUnknownDirective': "unknown directive: '$1'"},
|
||||
{'errInvalidDirective': 'invalid directive'},
|
||||
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
|
||||
{'errEmptyAsm': 'empty asm statement makes no sense'},
|
||||
{'errAsgnInvalidInExpr': "'=' invalid in an expression; probably '==' meant"},
|
||||
{'errInvalidIndentation': 'invalid indentation'},
|
||||
{'errExceptionExpected': 'exception expected'},
|
||||
{'errExceptionAlreadyHandled': 'exception already handled'},
|
||||
{'errReturnNotAllowedHere': "'return' only allowed in routine"},
|
||||
{'errYieldNotAllowedHere': "'yield' only allowed in a loop of an iterator"},
|
||||
{'errInvalidNumberOfYieldExpr': "invalid number of 'yield' expresions"},
|
||||
{'errReturnInvalidInIterator': "'return' not allowed in iterator"},
|
||||
{'errCannotReturnExpr': 'current routine cannot return an expression'},
|
||||
{'errAttemptToRedefine': "attempt to redefine '$1'"},
|
||||
{'errStmtInvalidAfterReturn':
|
||||
@@ -78,21 +74,18 @@
|
||||
{'errColonOrEqualsExpected': "':' or '=' expected, but found '$1'"},
|
||||
{'errExprExpected': "expression expected, but found '$1'"},
|
||||
{'errUndeclaredIdentifier': "undeclared identifier: '$1'"},
|
||||
{'errUseQualifier': "ambigious identifier: '$1' -- use a qualifier"},
|
||||
{'errTwiceForwarded': "'$1' is forwarded twice"},
|
||||
{'errUseQualifier': "ambiguous identifier: '$1' -- use a qualifier"},
|
||||
{'errTypeExpected': 'type expected'},
|
||||
{'errSystemNeeds': "system module needs '$1'"},
|
||||
{'errExecutionOfProgramFailed': 'execution of an external program failed'},
|
||||
{'errNotOverloadable': "overloaded '$1' leads to ambigious calls"},
|
||||
{'errNotOverloadable': "overloaded '$1' leads to ambiguous calls"},
|
||||
{'errInvalidArgForX': "invalid argument for '$1'"},
|
||||
{'errStmtHasNoEffect': 'statement has no effect'},
|
||||
{'errXExpectsTypeOrValue': "'$1' expects a type or value"},
|
||||
{'errXExpectsArrayType': "'$1' expects an array type"},
|
||||
{'errIteratorCannotBeInstantiated':
|
||||
"'$1' cannot be instantiated because its body has not been compiled yet"},
|
||||
{'errExprWithNoTypeCannotBeConverted':
|
||||
'expression with no type cannot be converted'},
|
||||
{'errExprWithNoTypeCannotBeCasted': 'expression with no type cannot be casted'},
|
||||
{'errExprXAmbiguous': "expression '$1' ambiguous in this context"},
|
||||
{'errConstantDivisionByZero': 'constant division by zero'},
|
||||
{'errOrdinalTypeExpected': 'ordinal type expected'},
|
||||
{'errOrdinalOrFloatTypeExpected': 'ordinal or float type expected'},
|
||||
@@ -112,21 +105,17 @@
|
||||
{'errValueOutOfSetBounds': 'value out of set bounds'},
|
||||
{'errFieldInitTwice': "field initialized twice: '$1'"},
|
||||
{'errFieldNotInit': "field '$1' not initialized"},
|
||||
{'errExprCannotBeCalled': 'expression cannot be called'},
|
||||
{'errExprXCannotBeCalled': "expression '$1' cannot be called"},
|
||||
{'errExprHasNoType': 'expression has no type'},
|
||||
{'errExprXHasNoType': "expression '$1' has no type"},
|
||||
{'errExprXHasNoType': "expression '$1' has no type (or is ambiguous)"},
|
||||
{'errCastNotInSafeMode': "'cast' not allowed in safe mode"},
|
||||
{'errExprCannotBeCastedToX': 'expression cannot be casted to $1'},
|
||||
{'errUndefinedPrefixOpr': 'undefined prefix operator: $1'},
|
||||
{'errCommaOrParRiExpected': "',' or ')' expected"},
|
||||
{'errCurlyLeOrParLeExpected': "'{' or '(' expected"},
|
||||
{'errSectionExpected': "section ('type', 'proc', etc.) expected"},
|
||||
{'errImplemenationExpected': "'implementation' or end of file expected"},
|
||||
{'errRangeExpected': 'range expected'},
|
||||
{'errInvalidTypeDescription': 'invalid type description'},
|
||||
{'errAttemptToRedefineX': "attempt to redefine '$1'"},
|
||||
{'errMagicOnlyInSystem': "'magic' only allowed in system module"},
|
||||
{'errUnknownOperatorX': "unkown operator: '$1'"},
|
||||
{'errPowerOfTwoExpected': 'power of two expected'},
|
||||
{'errStringMayNotBeEmpty': 'string literal may not be empty'},
|
||||
{'errCallConvExpected': 'calling convention expected'},
|
||||
@@ -165,9 +154,8 @@
|
||||
{'errTypeMismatch': 'type mismatch: got ('},
|
||||
{'errButExpected': 'but expected one of: '},
|
||||
{'errButExpectedX': "but expected '$1'"},
|
||||
{'errAmbigiousCallXYZ': 'ambigious call; both $1 and $2 match for: $3'},
|
||||
{'errAmbiguousCallXYZ': 'ambiguous call; both $1 and $2 match for: $3'},
|
||||
{'errWrongNumberOfTypeParams': 'wrong number of type parameters'},
|
||||
{'errOutParamNoDefaultValue': 'out parameters cannot have default values'},
|
||||
{'errInlineProcHasNoAddress': 'an inline proc has no address'},
|
||||
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
|
||||
{'errPragmaOnlyInHeaderOfProc':
|
||||
@@ -177,22 +165,15 @@
|
||||
{'errNoSymbolToBorrowFromFound': "no symbol to borrow from found"},
|
||||
{'errDiscardValue': 'value returned by statement has to be discarded'},
|
||||
{'errInvalidDiscard': 'statement returns no value that can be discarded'},
|
||||
{'errUnknownPrecedence':
|
||||
"unknown precedence for operator; use 'infix: prec' pragma"},
|
||||
{'errIllegalConvFromXtoY': 'conversion from $1 to $2 is invalid'},
|
||||
{'errTypeMismatchExpectedXGotY': "type mismatch: expected '$1', but got '$2'"},
|
||||
{'errCannotBindXTwice': "cannot bind parameter '$1' twice"},
|
||||
{'errInvalidOrderInEnumX': "invalid order in enum '$1'"},
|
||||
{'errEnumXHasWholes': "enum '$1' has wholes"},
|
||||
{'errExceptExpected': "'except' or 'finally' expected"},
|
||||
{'errInvalidTry': "after catch all 'except' or 'finally' no section may follow"},
|
||||
{'errEofExpectedButXFound': "end of file expected, but found token '$1'"},
|
||||
{'errOptionExpected': "option expected, but found '$1'"},
|
||||
{'errCannotEvaluateForwardConst': 'cannot evaluate forwarded constant'},
|
||||
{'errXisNoLabel': "'$1' is not a label"},
|
||||
{'errXNeedsConcreteType': "'$1' needs to be of a non-generic type"},
|
||||
{'errNotAllCasesCovered': 'not all cases are covered'},
|
||||
{'errStringRange': 'string range in case statement not allowed'},
|
||||
{'errUnkownSubstitionVar': "unknown substitution variable: '$1'"},
|
||||
{'errComplexStmtRequiresInd': 'complex statement requires indentation'},
|
||||
{'errXisNotCallable': "'$1' is not callable"},
|
||||
@@ -204,7 +185,7 @@
|
||||
{'errNoReturnTypeForX': 'no return type for $1 allowed'},
|
||||
{'errConvNeedsOneArg': 'a type conversion needs exactly one argument'},
|
||||
{'errInvalidPragmaX': 'invalid pragma: $1'},
|
||||
{'errXNotAllowedHere': '$1 here not allowed'},
|
||||
{'errXNotAllowedHere': '$1 not allowed here'},
|
||||
{'errInvalidControlFlowX': 'invalid control flow: $1'},
|
||||
{'errATypeHasNoValue': 'a type has no value'},
|
||||
{'errXisNoType': "invalid type: '$1'"},
|
||||
@@ -214,11 +195,11 @@
|
||||
{'errInvalidExpressionX': "invalid expression: '$1'"},
|
||||
{'errEnumHasNoValueX': "enum has no value '$1'"},
|
||||
{'errNamedExprExpected': 'named expression expected'},
|
||||
{'errNamedExprNotAllowed': 'named expression here not allowed'},
|
||||
{'errNamedExprNotAllowed': 'named expression not allowed here'},
|
||||
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
|
||||
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
|
||||
{'errInvalidVisibilityX': "invalid invisibility: '$1'"},
|
||||
{'errInitHereNotAllowed': 'initialization here not allowed'},
|
||||
{'errInitHereNotAllowed': 'initialization not allowed here'},
|
||||
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
|
||||
{'errIteratorNotAllowed':
|
||||
"iterators can only be defined at the module's top level"},
|
||||
@@ -254,6 +235,7 @@
|
||||
{'errUnhandledExceptionX': "unhandled exception: $1"},
|
||||
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
|
||||
{'errXisNoMacroOrTemplate': "'$1' is no macro or template"},
|
||||
{'errXhasSideEffects': "'$1' can have side effects"},
|
||||
|
||||
# user error message:
|
||||
{'errUser': '$1'},
|
||||
|
||||
@@ -29,8 +29,8 @@ addrExpr ::= 'addr' '(' optInd expr ')'
|
||||
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')'
|
||||
| '[' ']' | '=' | literal)+ '`'
|
||||
| IDENT
|
||||
primary ::= (prefixOperator optInd)* (symbol | constructor |
|
||||
castExpr | addrExpr) (
|
||||
primary ::= ((prefixOperator | 'bind') optInd)* (symbol | constructor |
|
||||
castExpr | addrExpr) (
|
||||
'.' optInd symbol
|
||||
| '(' optInd namedExprList [SAD] ')'
|
||||
| '[' optInd
|
||||
@@ -42,7 +42,7 @@ primary ::= (prefixOperator optInd)* (symbol | constructor |
|
||||
literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
| CHAR_LIT | RCHAR_LIT
|
||||
| CHAR_LIT
|
||||
| NIL
|
||||
|
||||
constructor ::= literal
|
||||
|
||||
@@ -336,7 +336,7 @@ Precedence level Operators First characte
|
||||
|
||||
|
||||
The grammar's start symbol is ``module``. The grammar is LL(1) and therefore
|
||||
not ambigious.
|
||||
not ambiguous.
|
||||
|
||||
.. include:: grammar.txt
|
||||
:literal:
|
||||
@@ -920,6 +920,95 @@ each other:
|
||||
Most calling conventions exist only for the Windows 32-bit platform.
|
||||
|
||||
|
||||
Type relations
|
||||
--------------
|
||||
|
||||
The following section defines several relations on types that are needed to
|
||||
describe the type checking done by the compiler.
|
||||
|
||||
|
||||
Type equality
|
||||
~~~~~~~~~~~~~
|
||||
Nimrod uses structural type equivalence for most types. Only for objects,
|
||||
enumerations and abstract types name equivalence is used. The following
|
||||
algorithm determines type equality:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc typeEqualsAux(a, b: PType,
|
||||
s: var set[tuple[PType, PType]]): bool =
|
||||
if (a,b) in s: return true
|
||||
incl(s, (a,b))
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of int, intXX, float, floatXX, char, string, cstring, pointer, bool, nil:
|
||||
# leaf type: kinds identical; nothing more to check
|
||||
result = true
|
||||
of ref, ptr, var, set, seq, openarray:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s)
|
||||
of range:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s) and
|
||||
(a.rangeA == b.rangeA) and (a.rangeB == b.rangeB)
|
||||
of array:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s) and
|
||||
typeEqualsAux(a.indexType, b.indexType, s)
|
||||
of tuple:
|
||||
if a.tupleLen == b.tupleLen:
|
||||
for i in 0..a.tupleLen-1:
|
||||
if not typeEqualsAux(a[i], b[i], s): return false
|
||||
result = true
|
||||
of object, enum, abstract:
|
||||
result = a == b
|
||||
of proc:
|
||||
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
|
||||
typeEqualsAux(a.resultType, b.resultType, s) and
|
||||
a.callingConvention == b.callingConvention
|
||||
|
||||
proc typeEquals(a, b: PType): bool =
|
||||
var s: set[tuple[PType, PType]] = {}
|
||||
result = typeEqualsAux(a, b, s)
|
||||
|
||||
Since types are graphs which can have cycles, the above algorithm needs an
|
||||
auxiliary set ``s`` to detect this case.
|
||||
|
||||
|
||||
Subtype relation
|
||||
~~~~~~~~~~~~~~~~
|
||||
If object ``b`` inherits from ``a``, ``b`` is a subtype of ``a``. This subtype
|
||||
relation is extended to the types ``var``, ``ref``, ``ptr``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isSubtype(a, b: PType): bool =
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of object:
|
||||
var aa = a.baseType
|
||||
while aa != nil and aa != b: aa = aa.baseType
|
||||
result = aa == b
|
||||
of var, ref, ptr:
|
||||
result = isSubtype(a.baseType, b.baseType)
|
||||
|
||||
XXX nil is a special value!
|
||||
|
||||
|
||||
Convertible relation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
A type ``a`` is convertible to type ``b`` iff the following algorithm returns
|
||||
true:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isConvertible(a, b: PType): bool =
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of proc:
|
||||
var x = a.parameterTuple
|
||||
var y = b.parameterTuple
|
||||
if x.tupleLen == y.tupleLen:
|
||||
for i in 0.. x.tupleLen-1:
|
||||
if not isSubtype(x[i], y[i]): return false
|
||||
result = isSubType(b.resultType, a.resultType)
|
||||
|
||||
|
||||
|
||||
|
||||
Statements and expressions
|
||||
--------------------------
|
||||
@@ -927,8 +1016,7 @@ Nimrod uses the common statement/expression paradigm: `Statements`:idx: do not
|
||||
produce a value in contrast to expressions. Call expressions are statements.
|
||||
If the called procedure returns a value, it is not a valid statement
|
||||
as statements do not produce values. To evaluate an expression for
|
||||
side-effects and throwing its value away, one can use the ``discard``
|
||||
statement.
|
||||
side-effects and throw its value away, one can use the ``discard`` statement.
|
||||
|
||||
Statements are separated into `simple statements`:idx: and
|
||||
`complex statements`:idx:.
|
||||
@@ -1917,11 +2005,11 @@ iterator in which case the overloading resolution takes place:
|
||||
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x) # error: x is ambigious
|
||||
write(stdout, x) # error: x is ambiguous
|
||||
write(stdout, A.x) # no error: qualifier used
|
||||
|
||||
var x = 4
|
||||
write(stdout, x) # not ambigious: uses the module C's x
|
||||
write(stdout, x) # not ambiguous: uses the module C's x
|
||||
|
||||
|
||||
Messages
|
||||
|
||||
@@ -154,6 +154,9 @@ Index
|
||||
* `system.html#313 <system.html#313>`_
|
||||
* `system.html#314 <system.html#314>`_
|
||||
|
||||
`<=`:idx:
|
||||
`times.html#115 <times.html#115>`_
|
||||
|
||||
`<=`:idx:
|
||||
* `system.html#253 <system.html#253>`_
|
||||
* `system.html#254 <system.html#254>`_
|
||||
@@ -169,9 +172,6 @@ Index
|
||||
* `system.html#345 <system.html#345>`_
|
||||
* `system.html#346 <system.html#346>`_
|
||||
|
||||
`<=`:idx:
|
||||
`times.html#115 <times.html#115>`_
|
||||
|
||||
`<=%`:idx:
|
||||
* `system.html#305 <system.html#305>`_
|
||||
* `system.html#306 <system.html#306>`_
|
||||
@@ -201,7 +201,7 @@ Index
|
||||
* `macros.html#117 <macros.html#117>`_
|
||||
|
||||
`=~`:idx:
|
||||
`regexprs.html#111 <regexprs.html#111>`_
|
||||
`regexprs.html#108 <regexprs.html#108>`_
|
||||
|
||||
`>`:idx:
|
||||
`system.html#357 <system.html#357>`_
|
||||
@@ -218,18 +218,18 @@ Index
|
||||
`@`:idx:
|
||||
`system.html#365 <system.html#365>`_
|
||||
|
||||
`[]`:idx:
|
||||
`strtabs.html#107 <strtabs.html#107>`_
|
||||
|
||||
`[]`:idx:
|
||||
`macros.html#113 <macros.html#113>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`macros.html#114 <macros.html#114>`_
|
||||
`[]`:idx:
|
||||
`strtabs.html#107 <strtabs.html#107>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`strtabs.html#106 <strtabs.html#106>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`macros.html#114 <macros.html#114>`_
|
||||
|
||||
`[ESC]`:idx:
|
||||
`manual.html#134 <manual.html#134>`_
|
||||
|
||||
@@ -366,8 +366,7 @@ Index
|
||||
`xmlgen.html#111 <xmlgen.html#111>`_
|
||||
|
||||
`backslash`:idx:
|
||||
* `manual.html#127 <manual.html#127>`_
|
||||
* `regexprs.html#101 <regexprs.html#101>`_
|
||||
`manual.html#127 <manual.html#127>`_
|
||||
|
||||
`backspace`:idx:
|
||||
`manual.html#132 <manual.html#132>`_
|
||||
@@ -1228,7 +1227,7 @@ Index
|
||||
`system.html#156 <system.html#156>`_
|
||||
|
||||
`EInvalidRegEx`:idx:
|
||||
`regexprs.html#104 <regexprs.html#104>`_
|
||||
`regexprs.html#101 <regexprs.html#101>`_
|
||||
|
||||
`EInvalidValue`:idx:
|
||||
`system.html#148 <system.html#148>`_
|
||||
@@ -1265,12 +1264,12 @@ Index
|
||||
`enum_cursor_type`:idx:
|
||||
`mysql.html#237 <mysql.html#237>`_
|
||||
|
||||
`Enumeration`:idx:
|
||||
`manual.html#148 <manual.html#148>`_
|
||||
|
||||
`enumeration`:idx:
|
||||
`tut1.html#113 <tut1.html#113>`_
|
||||
|
||||
`Enumeration`:idx:
|
||||
`manual.html#148 <manual.html#148>`_
|
||||
|
||||
`enum_field_types`:idx:
|
||||
`mysql.html#202 <mysql.html#202>`_
|
||||
|
||||
@@ -1546,8 +1545,8 @@ Index
|
||||
* `strutils.html#124 <strutils.html#124>`_
|
||||
* `strutils.html#125 <strutils.html#125>`_
|
||||
* `strutils.html#126 <strutils.html#126>`_
|
||||
* `regexprs.html#109 <regexprs.html#109>`_
|
||||
* `regexprs.html#110 <regexprs.html#110>`_
|
||||
* `regexprs.html#106 <regexprs.html#106>`_
|
||||
* `regexprs.html#107 <regexprs.html#107>`_
|
||||
|
||||
`findChars`:idx:
|
||||
`strutils.html#123 <strutils.html#123>`_
|
||||
@@ -1631,9 +1630,6 @@ Index
|
||||
* `system.html#478 <system.html#478>`_
|
||||
* `system.html#479 <system.html#479>`_
|
||||
|
||||
`generic character types`:idx:
|
||||
`regexprs.html#102 <regexprs.html#102>`_
|
||||
|
||||
`Generics`:idx:
|
||||
* `manual.html#207 <manual.html#207>`_
|
||||
* `tut2.html#108 <tut2.html#108>`_
|
||||
@@ -2258,11 +2254,11 @@ Index
|
||||
`xmlgen.html#150 <xmlgen.html#150>`_
|
||||
|
||||
`match`:idx:
|
||||
* `regexprs.html#106 <regexprs.html#106>`_
|
||||
* `regexprs.html#107 <regexprs.html#107>`_
|
||||
* `regexprs.html#103 <regexprs.html#103>`_
|
||||
* `regexprs.html#104 <regexprs.html#104>`_
|
||||
|
||||
`matchLen`:idx:
|
||||
`regexprs.html#108 <regexprs.html#108>`_
|
||||
`regexprs.html#105 <regexprs.html#105>`_
|
||||
|
||||
`math`:idx:
|
||||
`nimrodc.html#118 <nimrodc.html#118>`_
|
||||
@@ -2301,7 +2297,7 @@ Index
|
||||
`mysql.html#191 <mysql.html#191>`_
|
||||
|
||||
`MaxSubpatterns`:idx:
|
||||
`regexprs.html#105 <regexprs.html#105>`_
|
||||
`regexprs.html#102 <regexprs.html#102>`_
|
||||
|
||||
`MAX_TINYINT_WIDTH`:idx:
|
||||
`mysql.html#190 <mysql.html#190>`_
|
||||
@@ -3095,12 +3091,12 @@ Index
|
||||
`ord`:idx:
|
||||
`system.html#172 <system.html#172>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal`:idx:
|
||||
`system.html#114 <system.html#114>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal types`:idx:
|
||||
`manual.html#141 <manual.html#141>`_
|
||||
|
||||
@@ -3623,16 +3619,16 @@ Index
|
||||
`system.html#419 <system.html#419>`_
|
||||
|
||||
`reBinary`:idx:
|
||||
`regexprs.html#116 <regexprs.html#116>`_
|
||||
`regexprs.html#113 <regexprs.html#113>`_
|
||||
|
||||
`Recursive module dependancies`:idx:
|
||||
`manual.html#216 <manual.html#216>`_
|
||||
|
||||
`reEmail`:idx:
|
||||
`regexprs.html#119 <regexprs.html#119>`_
|
||||
`regexprs.html#116 <regexprs.html#116>`_
|
||||
|
||||
`reFloat`:idx:
|
||||
`regexprs.html#118 <regexprs.html#118>`_
|
||||
`regexprs.html#115 <regexprs.html#115>`_
|
||||
|
||||
`REFRESH_DES_KEY_FILE`:idx:
|
||||
`mysql.html#154 <mysql.html#154>`_
|
||||
@@ -3680,13 +3676,13 @@ Index
|
||||
`nimrodc.html#112 <nimrodc.html#112>`_
|
||||
|
||||
`reHex`:idx:
|
||||
`regexprs.html#115 <regexprs.html#115>`_
|
||||
|
||||
`reIdentifier`:idx:
|
||||
`regexprs.html#112 <regexprs.html#112>`_
|
||||
|
||||
`reIdentifier`:idx:
|
||||
`regexprs.html#109 <regexprs.html#109>`_
|
||||
|
||||
`reInteger`:idx:
|
||||
`regexprs.html#114 <regexprs.html#114>`_
|
||||
`regexprs.html#111 <regexprs.html#111>`_
|
||||
|
||||
`removeDir`:idx:
|
||||
`os.html#150 <os.html#150>`_
|
||||
@@ -3695,10 +3691,10 @@ Index
|
||||
`os.html#141 <os.html#141>`_
|
||||
|
||||
`reNatural`:idx:
|
||||
`regexprs.html#113 <regexprs.html#113>`_
|
||||
`regexprs.html#110 <regexprs.html#110>`_
|
||||
|
||||
`reOctal`:idx:
|
||||
`regexprs.html#117 <regexprs.html#117>`_
|
||||
`regexprs.html#114 <regexprs.html#114>`_
|
||||
|
||||
`repeatChar`:idx:
|
||||
`strutils.html#148 <strutils.html#148>`_
|
||||
@@ -3724,7 +3720,7 @@ Index
|
||||
`manual.html#189 <manual.html#189>`_
|
||||
|
||||
`reURL`:idx:
|
||||
`regexprs.html#120 <regexprs.html#120>`_
|
||||
`regexprs.html#117 <regexprs.html#117>`_
|
||||
|
||||
`round`:idx:
|
||||
`math.html#121 <math.html#121>`_
|
||||
@@ -3889,9 +3885,6 @@ Index
|
||||
* `system.html#226 <system.html#226>`_
|
||||
* `system.html#227 <system.html#227>`_
|
||||
|
||||
`simple assertions`:idx:
|
||||
`regexprs.html#103 <regexprs.html#103>`_
|
||||
|
||||
`simple statements`:idx:
|
||||
`manual.html#174 <manual.html#174>`_
|
||||
|
||||
@@ -5154,6 +5147,9 @@ Index
|
||||
* `manual.html#156 <manual.html#156>`_
|
||||
* `tut2.html#103 <tut2.html#103>`_
|
||||
|
||||
`verbose`:idx:
|
||||
`regexprs.html#118 <regexprs.html#118>`_
|
||||
|
||||
`vertical tabulator`:idx:
|
||||
`manual.html#126 <manual.html#126>`_
|
||||
|
||||
|
||||
17
doc/tut1.txt
17
doc/tut1.txt
@@ -264,7 +264,7 @@ For integers or other ordinal types value ranges are also possible:
|
||||
However, the above code does not compile: The reason is that you have to cover
|
||||
every value that ``n`` may contain, but the code only handles the values
|
||||
``0..8``. Since it is not very practical to list every other possible integer
|
||||
(though it is possible thanks to the range notation!), we fix this by telling
|
||||
(though it is possible thanks to the range notation), we fix this by telling
|
||||
the compiler that for every other value nothing should be done:
|
||||
|
||||
.. code-block:: nimrod
|
||||
@@ -624,7 +624,8 @@ Nimrod provides the ability to overload procedures similar to C++:
|
||||
.. code-block:: nimrod
|
||||
proc toString(x: int): string = ...
|
||||
proc toString(x: bool): string =
|
||||
if x: return "true" else: return "false"
|
||||
if x: return "true"
|
||||
else: return "false"
|
||||
|
||||
Echo(toString(13)) # calls the toString(x: int) proc
|
||||
Echo(toString(true)) # calls the toString(x: bool) proc
|
||||
@@ -634,7 +635,7 @@ The compiler chooses the most appropriate proc for the ``toString`` calls. How
|
||||
this overloading resolution algorithm works exactly is not discussed here
|
||||
(it will be specified in the manual soon).
|
||||
However, it does not lead to nasty suprises and is based on a quite simple
|
||||
unification algorithm. Ambigious calls are reported as errors.
|
||||
unification algorithm. Ambiguous calls are reported as errors.
|
||||
|
||||
|
||||
Operators
|
||||
@@ -643,7 +644,7 @@ The Nimrod library makes heavy use of overloading - one reason for this is that
|
||||
each operator like ``+`` is a just an overloaded proc. The parser lets you
|
||||
use operators in `infix notation` (``a + b``) or `prefix notation` (``+ a``).
|
||||
An infix operator always receives two arguments, a prefix operator always one.
|
||||
Postfix operators are not possible, because this would be ambigious: Does
|
||||
Postfix operators are not possible, because this would be ambiguous: Does
|
||||
``a @ @ b`` mean ``(a) @ (@b)`` or ``(a@) @ (b)``? It always means
|
||||
``(a) @ (@b)``, because there are no postfix operators in Nimrod.
|
||||
|
||||
@@ -1331,7 +1332,7 @@ This is best illustrated by an example:
|
||||
|
||||
|
||||
A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If
|
||||
the symbol is ambigious, it even *has* to be qualified. A symbol is ambigious
|
||||
the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous
|
||||
if it is defined in two (or more) different modules and both modules are
|
||||
imported by a third one:
|
||||
|
||||
@@ -1344,11 +1345,11 @@ imported by a third one:
|
||||
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x) # error: x is ambigious
|
||||
write(stdout, x) # error: x is ambiguous
|
||||
write(stdout, A.x) # no error: qualifier used
|
||||
|
||||
var x = 4
|
||||
write(stdout, x) # not ambigious: uses the module C's x
|
||||
write(stdout, x) # not ambiguous: uses the module C's x
|
||||
|
||||
|
||||
But this rule does not apply to procedures or iterators. Here the overloading
|
||||
@@ -1367,7 +1368,7 @@ rules apply:
|
||||
write(stdout, x("")) # no error: B.x is called
|
||||
|
||||
proc x*(a: int): string = nil
|
||||
write(stdout, x(3)) # ambigious: which `x` is to call?
|
||||
write(stdout, x(3)) # ambiguous: which `x` is to call?
|
||||
|
||||
|
||||
From statement
|
||||
|
||||
13
doc/tut2.txt
13
doc/tut2.txt
@@ -34,7 +34,7 @@ While Nimrod's support for object oriented programming (OOP) is minimalistic,
|
||||
powerful OOP technics can be used. OOP is seen as *one* way to design a
|
||||
program, not *the only* way. Often a procedural approach leads to simpler
|
||||
and more efficient code. In particular, prefering aggregation over inheritance
|
||||
often results in a better design.
|
||||
is often the better design.
|
||||
|
||||
|
||||
Objects
|
||||
@@ -446,8 +446,7 @@ containers:
|
||||
# this uses an explicit stack (which is more efficient anyway):
|
||||
var stack: seq[PBinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack[stack.len-1]
|
||||
setLen(stack, stack.len-1) # pop `n` of the stack
|
||||
var n = stack.pop()
|
||||
while n != nil:
|
||||
yield n
|
||||
add(stack, n.ri) # push right subtree onto the stack
|
||||
@@ -562,11 +561,11 @@ via a special ``:`` syntax:
|
||||
block:
|
||||
var fn = filename
|
||||
var f: TFile
|
||||
if openFile(f, fn, mode):
|
||||
if open(f, fn, mode):
|
||||
try:
|
||||
actions
|
||||
finally:
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
quit("cannot open: " & fn)
|
||||
|
||||
@@ -593,9 +592,7 @@ Macros enable advanced compile-time code tranformations, but they
|
||||
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||
Nimrod's syntax is flexible enough anyway.
|
||||
|
||||
`Macros`:idx: can be used to implement `domain specific languages`:idx:.
|
||||
|
||||
To write macros, one needs to know how the Nimrod concrete syntax is converted
|
||||
To write a macro, one needs to know how the Nimrod concrete syntax is converted
|
||||
to an abstract syntax tree (AST). The AST is documented in the
|
||||
`macros <macros.html>`_ module.
|
||||
|
||||
|
||||
@@ -66,6 +66,4 @@ Currently, the following C compilers are supported under Windows:
|
||||
- | Digital Mars C++
|
||||
| http://www.digitalmars.com/download/freecompiler.html
|
||||
|
||||
For better compile times I recommend Digital Mars C++ -- it is easy to install
|
||||
and a small package.
|
||||
|
||||
However, most testing is done with GCC.
|
||||
|
||||
4
koch.py
4
koch.py
@@ -253,8 +253,8 @@ class Changed:
|
||||
c = Changed("unique_name", "file1.pas file2.pas file3.pas")
|
||||
if c.check():
|
||||
Exec("fpc file1.pas")
|
||||
# Exec raises an exception if it fails, thus if we get to here, it was
|
||||
# a success:
|
||||
# Exec raises an exception if it fails, thus if we reach the
|
||||
# next statement, it was a success:
|
||||
c.success()
|
||||
"""
|
||||
def __init__(self, id, files, explain=false,
|
||||
|
||||
3675
lib/posix/posix.nim
3675
lib/posix/posix.nim
File diff suppressed because it is too large
Load Diff
@@ -45,27 +45,27 @@ type
|
||||
nnkCurly, nnkBracket, nnkBracketExpr, nnkPragmaExpr,
|
||||
nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr,
|
||||
nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda,
|
||||
nnkAccQuoted, nnkHeaderQuoted, nnkTableConstr, nnkQualified,
|
||||
nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv,
|
||||
nnkCast, nnkAddr, nnkHiddenAddr, nnkHiddenDeref,
|
||||
nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64,
|
||||
nnkChckRange, nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray,
|
||||
nnkAsgn, nnkFastAsgn, nnkDefaultTypeParam, nnkGenericParams,
|
||||
nnkFormalParams, nnkOfInherit, nnkModule, nnkProcDef,
|
||||
nnkConverterDef, nnkMacroDef, nnkTemplateDef, nnkIteratorDef,
|
||||
nnkOfBranch, nnkElifBranch, nnkExceptBranch, nnkElse,
|
||||
nnkMacroStmt, nnkAsmStmt, nnkPragma, nnkIfStmt,
|
||||
nnkWhenStmt, nnkForStmt, nnkWhileStmt, nnkCaseStmt,
|
||||
nnkVarSection, nnkConstSection, nnkConstDef, nnkTypeSection,
|
||||
nnkTypeDef, nnkYieldStmt, nnkTryStmt, nnkFinally,
|
||||
nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt,
|
||||
nnkBlockStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt,
|
||||
nnkFromStmt, nnkImportAs, nnkIncludeStmt, nnkCommentStmt,
|
||||
nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkBlockType,
|
||||
nnkVm, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy,
|
||||
nnkRecList, nnkRecCase, nnkRecWhen, nnkRefTy,
|
||||
nnkPtrTy, nnkVarTy, nnkAbstractTy, nnkProcTy,
|
||||
nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
||||
nnkAccQuoted, nnkTableConstr, nnkQualified, nnkBind,
|
||||
nnkSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv,
|
||||
nnkConv, nnkCast, nnkAddr, nnkHiddenAddr,
|
||||
nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF,
|
||||
nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString,
|
||||
nnkPassAsOpenArray, nnkAsgn, nnkFastAsgn, nnkDefaultTypeParam,
|
||||
nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkModule,
|
||||
nnkProcDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef,
|
||||
nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch,
|
||||
nnkElse, nnkMacroStmt, nnkAsmStmt, nnkPragma,
|
||||
nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkWhileStmt,
|
||||
nnkCaseStmt, nnkVarSection, nnkConstSection, nnkConstDef,
|
||||
nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkTryStmt,
|
||||
nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt,
|
||||
nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkStmtList,
|
||||
nnkImportStmt, nnkFromStmt, nnkImportAs, nnkIncludeStmt,
|
||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType,
|
||||
nnkBlockType, nnkVm, nnkTypeOfExpr, nnkObjectTy,
|
||||
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
||||
nnkRefTy, nnkPtrTy, nnkVarTy, nnkAbstractTy,
|
||||
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
||||
TNimNodeKinds* = set[TNimrodNodeKind]
|
||||
TNimrodTypeKind* = enum
|
||||
ntyNone, ntyBool, ntyChar, ntyEmpty,
|
||||
|
||||
@@ -556,9 +556,9 @@ proc sameFileContent*(path1, path2: string): bool =
|
||||
bufSize = 8192 # 8K buffer
|
||||
var
|
||||
a, b: TFile
|
||||
if not openFile(a, path1): return false
|
||||
if not openFile(b, path2):
|
||||
closeFile(a)
|
||||
if not open(a, path1): return false
|
||||
if not open(b, path2):
|
||||
close(a)
|
||||
return false
|
||||
var bufA = alloc(bufsize)
|
||||
var bufB = alloc(bufsize)
|
||||
@@ -576,8 +576,8 @@ proc sameFileContent*(path1, path2: string): bool =
|
||||
if readA != bufSize: break # end of file
|
||||
dealloc(bufA)
|
||||
dealloc(bufB)
|
||||
closeFile(a)
|
||||
closeFile(b)
|
||||
close(a)
|
||||
close(b)
|
||||
|
||||
proc copyFile*(dest, source: string) =
|
||||
## Copies a file from `source` to `dest`. If this fails,
|
||||
@@ -590,9 +590,9 @@ proc copyFile*(dest, source: string) =
|
||||
bufSize = 8192 # 8K buffer
|
||||
var
|
||||
d, s: TFile
|
||||
if not openFile(s, source): OSError()
|
||||
if not openFile(d, dest, fmWrite):
|
||||
closeFile(s)
|
||||
if not open(s, source): OSError()
|
||||
if not open(d, dest, fmWrite):
|
||||
close(s)
|
||||
OSError()
|
||||
var
|
||||
buf: Pointer = alloc(bufsize)
|
||||
@@ -603,8 +603,8 @@ proc copyFile*(dest, source: string) =
|
||||
if bytesread != bufSize: break
|
||||
if bytesread != bytesWritten: OSError()
|
||||
dealloc(buf)
|
||||
closeFile(s)
|
||||
closeFile(d)
|
||||
close(s)
|
||||
close(d)
|
||||
|
||||
proc moveFile*(dest, source: string) =
|
||||
## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
|
||||
@@ -954,7 +954,7 @@ proc getHomeDir*(): string =
|
||||
when defined(windows): return getEnv("USERPROFILE") & "\\"
|
||||
else: return getEnv("HOME") & "/"
|
||||
|
||||
proc getConfigDir*(): string {.noSideEffect.} =
|
||||
proc getConfigDir*(): string =
|
||||
## Returns the config directory of the current user for applications.
|
||||
when defined(windows): return getEnv("APPDATA") & "\\"
|
||||
else: return getEnv("HOME") & "/.config/"
|
||||
|
||||
@@ -405,17 +405,17 @@ else:
|
||||
|
||||
proc inputStream(p: PProcess): PStream =
|
||||
var f: TFile
|
||||
if not openFile(f, p.inputHandle, fmWrite): OSError()
|
||||
if not open(f, p.inputHandle, fmWrite): OSError()
|
||||
result = newFileStream(f)
|
||||
|
||||
proc outputStream(p: PProcess): PStream =
|
||||
var f: TFile
|
||||
if not openFile(f, p.outputHandle, fmRead): OSError()
|
||||
if not open(f, p.outputHandle, fmRead): OSError()
|
||||
result = newFileStream(f)
|
||||
|
||||
proc errorStream(p: PProcess): PStream =
|
||||
var f: TFile
|
||||
if not openFile(f, p.errorHandle, fmRead): OSError()
|
||||
if not open(f, p.errorHandle, fmRead): OSError()
|
||||
result = newFileStream(f)
|
||||
|
||||
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
|
||||
|
||||
@@ -152,3 +152,25 @@ const ## common regular expressions
|
||||
reURL* = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms\-help):" &
|
||||
r"((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b"
|
||||
## describes an URL
|
||||
|
||||
proc verbose*(pattern: string): string {.noSideEffect.} =
|
||||
## deletes whitespace from a pattern that is not escaped or in a character
|
||||
## class. This is modelled after Perl's ``/x`` modifier.
|
||||
result = ""
|
||||
var i = 0
|
||||
while i < pattern.len:
|
||||
case pattern[i]
|
||||
of ' ', '\t':
|
||||
inc i
|
||||
of '\\':
|
||||
add result, '\\'
|
||||
add result, pattern[i+1]
|
||||
inc i, 2
|
||||
of '[':
|
||||
while pattern[i] != ']' and pattern[i] != '\0':
|
||||
add result, pattern[i]
|
||||
inc i
|
||||
else:
|
||||
add result, pattern[i]
|
||||
inc i
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ type
|
||||
TFileStream* = object of TStream
|
||||
f: TFile
|
||||
|
||||
proc fsClose(s: PFileStream) = closeFile(s.f)
|
||||
proc fsClose(s: PFileStream) = close(s.f)
|
||||
proc fsAtEnd(s: PFileStream): bool = return EndOfFile(s.f)
|
||||
proc fsSetPosition(s: PFileStream, pos: int) = setFilePos(s.f, pos)
|
||||
proc fsGetPosition(s: PFileStream): int = return int(getFilePos(s.f))
|
||||
@@ -171,7 +171,7 @@ proc newFileStream*(filename: string, mode: TFileMode): PFileStream =
|
||||
## creates a new stream from the file named `filename` with the mode `mode`.
|
||||
## If the file cannot be opened, nil is returned.
|
||||
var f: TFile
|
||||
if OpenFile(f, filename, mode): result = newFileStream(f)
|
||||
if Open(f, filename, mode): result = newFileStream(f)
|
||||
|
||||
|
||||
when true:
|
||||
|
||||
@@ -150,15 +150,18 @@ proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect.}
|
||||
## Searches for `chars` in `s` starting at position `start`. If `s` contains
|
||||
## none of the characters in `chars`, -1 is returned.
|
||||
|
||||
proc replaceStr*(s, sub, by: string): string {.noSideEffect.}
|
||||
proc replaceStr*(s, sub, by: string): string {.noSideEffect, deprecated.}
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
## **Deprecated since version 0.8.0**: Use `replace` instead.
|
||||
|
||||
proc replaceStr*(s: string, sub, by: char): string {.noSideEffect.}
|
||||
proc replaceStr*(s: string, sub, by: char): string {.noSideEffect, deprecated.}
|
||||
## optimized version for characters.
|
||||
## **Deprecated since version 0.8.0**: Use `replace` instead.
|
||||
|
||||
proc deleteStr*(s: var string, first, last: int)
|
||||
proc deleteStr*(s: var string, first, last: int) {.deprecated.}
|
||||
## Deletes in `s` the characters at position `first`..`last`. This modifies
|
||||
## `s` itself, it does not return a copy.
|
||||
## **Deprecated since version 0.8.0**: Use `delete` instead.
|
||||
|
||||
proc toOctal*(c: char): string
|
||||
## Converts a character `c` to its octal representation. The resulting
|
||||
@@ -185,7 +188,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
|
||||
## for word in split(";;this;is;an;;example;;;", {';'}):
|
||||
## writeln(stdout, word)
|
||||
##
|
||||
## produces in the same output.
|
||||
## produces the same output.
|
||||
var
|
||||
first: int = 0
|
||||
last: int = 0
|
||||
@@ -315,17 +318,15 @@ proc intToStr*(x: int, minchars: int = 1): string
|
||||
proc ParseInt*(s: string): int {.noSideEffect.}
|
||||
## Parses a decimal integer value contained in `s`. If `s` is not
|
||||
## a valid integer, `EInvalidValue` is raised.
|
||||
# XXX: make this biggestint!
|
||||
|
||||
proc ParseBiggestInt*(s: string): biggestInt {.noSideEffect.}
|
||||
## Parses a decimal integer value contained in `s`. If `s` is not
|
||||
## a valid integer, `EInvalidValue` is raised.
|
||||
|
||||
proc ParseFloat*(s: string, start = 0): float {.noSideEffect.}
|
||||
proc ParseFloat*(s: string): float {.noSideEffect.}
|
||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||
## a valid floating point number, `EInvalidValue` is raised. ``NAN``,
|
||||
## ``INF``, ``-INF`` are also supported (case insensitive comparison).
|
||||
# XXX: make this biggestfloat.
|
||||
|
||||
# the stringify and format operators:
|
||||
proc toString*[Ty](x: Ty): string
|
||||
@@ -439,10 +440,15 @@ proc findNormalized(x: string, inArray: openarray[string]): int =
|
||||
proc addf(s: var string, formatstr: string, a: openarray[string]) =
|
||||
const PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'}
|
||||
var i = 0
|
||||
var num = 0
|
||||
while i < len(formatstr):
|
||||
if formatstr[i] == '$':
|
||||
case formatstr[i+1] # again we use the fact that strings
|
||||
# are zero-terminated here
|
||||
of '#':
|
||||
add s, a[num]
|
||||
inc i, 2
|
||||
inc num
|
||||
of '$':
|
||||
add s, '$'
|
||||
inc(i, 2)
|
||||
@@ -452,6 +458,7 @@ proc addf(s: var string, formatstr: string, a: openarray[string]) =
|
||||
while formatstr[i] in {'0'..'9'}:
|
||||
j = j * 10 + ord(formatstr[i]) - ord('0')
|
||||
inc(i)
|
||||
num = j
|
||||
add s, a[j - 1]
|
||||
of '{':
|
||||
var j = i+1
|
||||
@@ -510,6 +517,31 @@ proc splitSeq(s: string, seps: set[char]): seq[string] =
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc join*(a: openArray[string], sep: string): string =
|
||||
## concatenates all strings in `a` separating them with `sep`.
|
||||
if len(a) > 0:
|
||||
var L = sep.len * (a.len-1)
|
||||
for i in 0..high(a): inc(L, a[i].len)
|
||||
result = newString(L)
|
||||
setLen(result, 0)
|
||||
add(result, a[0])
|
||||
for i in 1..high(a):
|
||||
add(result, sep)
|
||||
add(result, a[i])
|
||||
else:
|
||||
result = ""
|
||||
|
||||
proc join*(a: openArray[string]): string =
|
||||
## concatenates all strings in `a`.
|
||||
if len(a) > 0:
|
||||
var L = 0
|
||||
for i in 0..high(a): inc(L, a[i].len)
|
||||
result = newString(L)
|
||||
setLen(result, 0)
|
||||
for i in 0..high(a): add(result, a[i])
|
||||
else:
|
||||
result = ""
|
||||
|
||||
proc strip(s: string, leading = true, trailing = true): string =
|
||||
const
|
||||
chars: set[Char] = Whitespace
|
||||
@@ -638,7 +670,8 @@ proc contains(s: string, c: char): bool =
|
||||
proc contains(s, sub: string): bool =
|
||||
return find(s, sub) >= 0
|
||||
|
||||
proc replaceStr(s, sub, by: string): string =
|
||||
proc replace*(s, sub, by: string): string =
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
var a: TSkipTable
|
||||
result = ""
|
||||
preprocessSub(sub, a)
|
||||
@@ -652,7 +685,8 @@ proc replaceStr(s, sub, by: string): string =
|
||||
# copy the rest:
|
||||
add result, copy(s, i)
|
||||
|
||||
proc replaceStr(s: string, sub, by: char): string =
|
||||
proc replace*(s: string, sub, by: char): string =
|
||||
## optimized version for characters.
|
||||
result = newString(s.len)
|
||||
var i = 0
|
||||
while i < s.len:
|
||||
@@ -660,17 +694,23 @@ proc replaceStr(s: string, sub, by: char): string =
|
||||
else: result[i] = s[i]
|
||||
inc(i)
|
||||
|
||||
proc deleteStr(s: var string, first, last: int) =
|
||||
proc delete*(s: var string, first, last: int) =
|
||||
## Deletes in `s` the characters at position `first`..`last`. This modifies
|
||||
## `s` itself, it does not return a copy.
|
||||
var
|
||||
i = first
|
||||
# example: "abc___uvwxyz\0" (___ is to be deleted)
|
||||
# --> first == 3, last == 5
|
||||
# s[first..] = s[last+1..]
|
||||
var
|
||||
i = first
|
||||
while last+i+1 < len(s):
|
||||
s[i] = s[last+i+1]
|
||||
inc(i)
|
||||
setlen(s, len(s)-(last-first+1))
|
||||
|
||||
proc replaceStr(s, sub, by: string): string = return replace(s, sub, by)
|
||||
proc replaceStr(s: string, sub, by: char): string = return replace(s, sub, by)
|
||||
proc deleteStr*(s: var string, first, last: int) = delete(s, first, last)
|
||||
|
||||
# parsing numbers:
|
||||
|
||||
proc toHex(x: BiggestInt, len: int): string =
|
||||
@@ -734,11 +774,11 @@ proc ParseBiggestInt(s: string): biggestInt =
|
||||
if index == -1:
|
||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
|
||||
proc ParseFloat(s: string, start = 0): float =
|
||||
proc ParseFloat(s: string): float =
|
||||
var
|
||||
esign = 1.0
|
||||
sign = 1.0
|
||||
i = start
|
||||
i = 0
|
||||
exponent: int
|
||||
flags: int
|
||||
result = 0.0
|
||||
|
||||
@@ -69,11 +69,12 @@ proc `or`*(x, y: bool): bool {.magic: "Or", noSideEffect.}
|
||||
proc `xor`*(x, y: bool): bool {.magic: "Xor", noSideEffect.}
|
||||
## Boolean `exclusive or`; returns true iff ``x != y``.
|
||||
|
||||
proc new*[T](a: var ref T) {.magic: "New".}
|
||||
proc new*[T](a: var ref T) {.magic: "New", noSideEffect.}
|
||||
## creates a new object of type ``T`` and returns a safe (traced)
|
||||
## reference to it in ``a``.
|
||||
|
||||
proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {.magic: "NewFinalize".}
|
||||
proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {.
|
||||
magic: "NewFinalize", noSideEffect.}
|
||||
## creates a new object of type ``T`` and returns a safe (traced)
|
||||
## reference to it in ``a``. When the garbage collector frees the object,
|
||||
## `finalizer` is called. The `finalizer` may not keep a reference to the
|
||||
@@ -230,17 +231,17 @@ proc pred*[T](x: ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.}
|
||||
## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised
|
||||
## or a compile time error occurs.
|
||||
|
||||
proc inc*[T](x: var ordinal[T], y = 1) {.magic: "Inc".}
|
||||
proc inc*[T](x: var ordinal[T], y = 1) {.magic: "Inc", noSideEffect.}
|
||||
## increments the ordinal ``x`` by ``y``. If such a value does not
|
||||
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
|
||||
## short notation for: ``x = succ(x, y)``.
|
||||
|
||||
proc dec*[T](x: var ordinal[T], y = 1) {.magic: "Dec".}
|
||||
proc dec*[T](x: var ordinal[T], y = 1) {.magic: "Dec", noSideEffect.}
|
||||
## decrements the ordinal ``x`` by ``y``. If such a value does not
|
||||
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
|
||||
## short notation for: ``x = pred(x, y)``.
|
||||
|
||||
proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq".}
|
||||
proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
|
||||
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
||||
## This is equivalent to ``s = []; setlen(s, len)``, but more
|
||||
## efficient since no relocation is needed.
|
||||
@@ -255,11 +256,11 @@ proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
|
||||
## always an int.
|
||||
|
||||
# set routines:
|
||||
proc incl*[T](x: var set[T], y: T) {.magic: "Incl".}
|
||||
proc incl*[T](x: var set[T], y: T) {.magic: "Incl", noSideEffect.}
|
||||
## includes element ``y`` to the set ``x``. This is the same as
|
||||
## ``x = x + {y}``, but it might be more efficient.
|
||||
|
||||
proc excl*[T](x: var set[T], y: T) {.magic: "Excl".}
|
||||
proc excl*[T](x: var set[T], y: T) {.magic: "Excl", noSideEffect.}
|
||||
## excludes element ``y`` to the set ``x``. This is the same as
|
||||
## ``x = x - {y}``, but it might be more efficient.
|
||||
|
||||
@@ -641,8 +642,8 @@ proc `&` * (x: char, y: string): string {.
|
||||
magic: "ConStrStr", noSideEffect, merge.}
|
||||
## is the `concatenation operator`. It concatenates `x` and `y`.
|
||||
|
||||
proc add*(x: var string, y: char) {.magic: "AppendStrCh".}
|
||||
proc add*(x: var string, y: string) {.magic: "AppendStrStr".}
|
||||
proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
|
||||
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
|
||||
|
||||
when not defined(ECMAScript):
|
||||
{.push overflow_checks:off}
|
||||
@@ -663,8 +664,8 @@ else:
|
||||
`x`[0][len] = 0
|
||||
"""
|
||||
|
||||
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem".}
|
||||
proc add *[T](x: var seq[T], y: seq[T]) {.magic: "AppendSeqSeq".}
|
||||
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
|
||||
proc add *[T](x: var seq[T], y: seq[T]) {.magic: "AppendSeqSeq", noSideEffect.}
|
||||
## Generic proc for adding a data item `y` to a container `x`.
|
||||
## For containers that have an order, `add` means *append*. New generic
|
||||
## containers should also call their adding proc `add` for consistency.
|
||||
@@ -811,7 +812,8 @@ proc copy*(s: string, first, last: int): string {.
|
||||
## the first and last characters that shall be copied. If ``last``
|
||||
## is omitted, it is treated as ``high(s)``.
|
||||
|
||||
proc setLen*(s: var string, newlen: int) {.magic: "SetLengthStr".}
|
||||
proc setLen*(s: var string, newlen: int) {.
|
||||
magic: "SetLengthStr", noSideEffect.}
|
||||
## sets the length of `s` to `newlen`.
|
||||
## If the current length is greater than the new length,
|
||||
## ``s`` will be truncated.
|
||||
@@ -873,20 +875,21 @@ proc dealloc*(p: Pointer) {.noconv.}
|
||||
## or other memory may be corrupted. So this procedure is really
|
||||
## *unsafe*.
|
||||
|
||||
proc setLen*[T](s: var seq[T], newlen: int) {.magic: "SetLengthSeq".}
|
||||
proc setLen*[T](s: var seq[T], newlen: int) {.
|
||||
magic: "SetLengthSeq", noSideEffect.}
|
||||
## sets the length of `s` to `newlen`.
|
||||
## ``T`` may be any sequence type.
|
||||
## If the current length is greater than the new length,
|
||||
## ``s`` will be truncated.
|
||||
|
||||
proc assert*(cond: bool) {.magic: "Assert".}
|
||||
proc assert*(cond: bool) {.magic: "Assert", noSideEffect.}
|
||||
## provides a means to implement `programming by contracts` in Nimrod.
|
||||
## ``assert`` evaluates expression ``cond`` and if ``cond`` is false, it
|
||||
## raises an ``EAssertionFailure`` exception. However, the compiler may
|
||||
## not generate any code at all for ``assert`` if it is advised to do so.
|
||||
## Thus one should use ``assert`` for debugging purposes only.
|
||||
|
||||
proc swap*[T](a, b: var T) {.magic: "Swap".}
|
||||
proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.}
|
||||
## swaps the values `a` and `b`. This is often more efficient than
|
||||
## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms.
|
||||
|
||||
@@ -934,7 +937,7 @@ proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
|
||||
## used instead. (In other words: *Overwriting* is possible.)
|
||||
|
||||
# undocumented:
|
||||
proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
|
||||
proc getRefcount*[T](x: ref T): int {.importc: "getRefcount", noSideEffect.}
|
||||
## retrieves the reference count of an heap-allocated object. The
|
||||
## value is implementation-dependant.
|
||||
|
||||
@@ -1107,18 +1110,19 @@ proc find*[T, S](a: T, item: S): int {.inline.} =
|
||||
inc(result)
|
||||
result = -1
|
||||
|
||||
proc pop*[T](s: var seq[T]): T {.inline.} =
|
||||
proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
|
||||
## returns the last item of `s` and decreases ``s.len`` by one. This treats
|
||||
## `s` as a stack and implements the common *pop* operation.
|
||||
var L = s.len-1
|
||||
result = s[L]
|
||||
setLen(s, L)
|
||||
|
||||
proc each*[T, S](data: openArray[T], op: proc (x: T): S): seq[S] =
|
||||
proc each*[T, S](data: openArray[T], op: proc (x: T): S): seq[S] {.
|
||||
noSideEffect.} =
|
||||
## The well-known ``map`` operation from functional programming. Applies
|
||||
## `op` to every item in `data` and returns the result as a sequence.
|
||||
result = @[]
|
||||
for d in items(data): add(result, op(d))
|
||||
newSeq(result, data.len)
|
||||
for i in 0..data.len-1: result[i] = op(data[i])
|
||||
|
||||
|
||||
# ----------------- FPU ------------------------------------------------------
|
||||
@@ -1293,7 +1297,16 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
## does not work because the program writes to ``stderr``.
|
||||
|
||||
proc OpenFile*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool {.deprecated.}
|
||||
## **Deprecated since version 0.8.0**: Use `open` instead.
|
||||
|
||||
proc OpenFile*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool {.deprecated.}
|
||||
## **Deprecated since version 0.8.0**: Use `open` instead.
|
||||
|
||||
proc Open*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
@@ -1301,14 +1314,19 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
## that the programmer needs to provide an appropriate error message anyway
|
||||
## (yes, even in scripts).
|
||||
|
||||
proc OpenFile*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool
|
||||
proc Open*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool
|
||||
## Creates a ``TFile`` from a `filehandle` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
|
||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
|
||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.}
|
||||
## Closes the file.
|
||||
## **Deprecated since version 0.8.0**: Use `close` instead.
|
||||
|
||||
proc Close*(f: TFile) {.importc: "fclose", nodecl.}
|
||||
## Closes the file.
|
||||
|
||||
proc EndOfFile*(f: TFile): Bool
|
||||
## Returns true iff `f` is at the end.
|
||||
proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.}
|
||||
@@ -1394,13 +1412,13 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
## If the file does not exist `EIO` is raised.
|
||||
var
|
||||
f: TFile
|
||||
if not openFile(f, filename):
|
||||
if not open(f, filename):
|
||||
raise newException(EIO, "cannot open: " & filename)
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
CloseFile(f)
|
||||
Close(f)
|
||||
|
||||
proc fileHandle*(f: TFile): TFileHandle {.importc: "fileno",
|
||||
header: "<stdio.h>"}
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
|
||||
{.push hints:off}
|
||||
|
||||
proc c_strcmp(a, b: CString): cint {.nodecl, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: cint): cint {.nodecl, importc: "memcmp".}
|
||||
proc c_strcmp(a, b: CString): cint {.nodecl, noSideEffect, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: cint): cint {.
|
||||
nodecl, noSideEffect, importc: "memcmp".}
|
||||
proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
|
||||
proc c_strlen(a: CString): int {.nodecl, importc: "strlen".}
|
||||
proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}
|
||||
proc c_memset(p: pointer, value: cint, size: int) {.nodecl, importc: "memset".}
|
||||
|
||||
type
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
# simple integer arithmetic with overflow checking
|
||||
|
||||
proc raiseOverflow {.compilerproc, noinline.} =
|
||||
proc raiseOverflow {.compilerproc, noinline, noreturn.} =
|
||||
# a single proc to reduce code size to a minimum
|
||||
raise newException(EOverflow, "over- or underflow")
|
||||
|
||||
proc raiseDivByZero {.compilerproc, noinline.} =
|
||||
proc raiseDivByZero {.compilerproc, noinline, noreturn.} =
|
||||
raise newException(EDivByZero, "divison by zero")
|
||||
|
||||
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
|
||||
@@ -81,7 +81,7 @@ proc ListBreakPoints() =
|
||||
write(stdout, "***\n")
|
||||
|
||||
proc openAppend(filename: string): TFile =
|
||||
if openFile(result, filename, fmAppend):
|
||||
if open(result, filename, fmAppend):
|
||||
write(result, "----------------------------------------\n")
|
||||
|
||||
proc dbgRepr(p: pointer, typ: PNimType): string =
|
||||
@@ -329,7 +329,7 @@ proc dbgOut(s: string, start: int, currFrame: PExtendedFrame) =
|
||||
debugOut("[Warning] could not open or create file ")
|
||||
return
|
||||
dbgEvaluate(stream, s, i, currFrame)
|
||||
closeFile(stream)
|
||||
close(stream)
|
||||
|
||||
proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
|
||||
var dbgTemp: string
|
||||
@@ -343,7 +343,7 @@ proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
|
||||
debugOut("[Warning] could not open or create file ")
|
||||
return
|
||||
ListFrame(stream, currFrame)
|
||||
closeFile(stream)
|
||||
close(stream)
|
||||
|
||||
proc CommandPrompt() =
|
||||
# if we return from this routine, user code executes again
|
||||
|
||||
@@ -71,13 +71,13 @@ proc write(f: TFile, a: openArray[string]) =
|
||||
proc readFile(filename: string): string =
|
||||
var f: TFile
|
||||
try:
|
||||
if openFile(f, filename):
|
||||
if open(f, filename):
|
||||
var len = getFileSize(f)
|
||||
if len < high(int):
|
||||
result = newString(int(len))
|
||||
if readBuffer(f, addr(result[0]), int(len)) != len:
|
||||
result = nil
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
result = nil
|
||||
except EIO:
|
||||
@@ -112,9 +112,9 @@ const
|
||||
# should not be translated.
|
||||
|
||||
|
||||
proc OpenFile(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
proc Open(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
var
|
||||
p: pointer
|
||||
p = fopen(filename, FormatOpen[mode])
|
||||
@@ -129,10 +129,18 @@ proc OpenFile(f: var TFile, filename: string,
|
||||
proc fdopen(filehandle: TFileHandle, mode: cstring): TFile {.
|
||||
importc: pccHack & "fdopen", header: "<stdio.h>".}
|
||||
|
||||
proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
||||
proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
||||
f = fdopen(filehandle, FormatOpen[mode])
|
||||
result = f != nil
|
||||
|
||||
proc OpenFile(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
result = open(f, filename, mode, bufSize)
|
||||
|
||||
proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
||||
result = open(f, filehandle, mode)
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fread", noDecl.}
|
||||
|
||||
@@ -786,7 +786,7 @@ type
|
||||
mem_root*: MEM_ROOT # root allocations
|
||||
mysql*: PMYSQL # connection handle
|
||||
params*: PMYSQL_BIND # input parameters
|
||||
bind*: PMYSQL_BIND # input parameters
|
||||
`bind`*: PMYSQL_BIND # input parameters
|
||||
fields*: PMYSQL_FIELD # result set metadata
|
||||
result*: MYSQL_DATA # cached result set
|
||||
data_cursor*: PMYSQL_ROWS # current row in cached result
|
||||
@@ -1042,7 +1042,7 @@ proc mysql_stmt_execute*(stmt: PMYSQL_STMT): cint{.stdcall, dynlib: mysqllib,
|
||||
importc: "mysql_stmt_execute".}
|
||||
proc mysql_stmt_fetch*(stmt: PMYSQL_STMT): cint{.stdcall, dynlib: mysqllib,
|
||||
importc: "mysql_stmt_fetch".}
|
||||
proc mysql_stmt_fetch_column*(stmt: PMYSQL_STMT, bind: PMYSQL_BIND,
|
||||
proc mysql_stmt_fetch_column*(stmt: PMYSQL_STMT, `bind`: PMYSQL_BIND,
|
||||
column: cuint, offset: int): cint{.stdcall,
|
||||
dynlib: mysqllib, importc: "mysql_stmt_fetch_column".}
|
||||
proc mysql_stmt_store_result*(stmt: PMYSQL_STMT): cint{.stdcall,
|
||||
|
||||
110
nim/ast.pas
110
nim/ast.pas
@@ -78,27 +78,27 @@ type
|
||||
nkCurly, nkBracket, nkBracketExpr, nkPragmaExpr,
|
||||
nkRange, nkDotExpr, nkCheckedFieldExpr, nkDerefExpr,
|
||||
nkIfExpr, nkElifExpr, nkElseExpr, nkLambda,
|
||||
nkAccQuoted, nkHeaderQuoted, nkTableConstr, nkQualified,
|
||||
nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv, nkConv,
|
||||
nkCast, nkAddr, nkHiddenAddr, nkHiddenDeref,
|
||||
nkObjDownConv, nkObjUpConv, nkChckRangeF, nkChckRange64,
|
||||
nkChckRange, nkStringToCString, nkCStringToString, nkPassAsOpenArray,
|
||||
nkAsgn, nkFastAsgn, nkDefaultTypeParam, nkGenericParams,
|
||||
nkFormalParams, nkOfInherit, nkModule, nkProcDef,
|
||||
nkConverterDef, nkMacroDef, nkTemplateDef, nkIteratorDef,
|
||||
nkOfBranch, nkElifBranch, nkExceptBranch, nkElse,
|
||||
nkMacroStmt, nkAsmStmt, nkPragma, nkIfStmt,
|
||||
nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt,
|
||||
nkVarSection, nkConstSection, nkConstDef, nkTypeSection,
|
||||
nkTypeDef, nkYieldStmt, nkTryStmt, nkFinally,
|
||||
nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt,
|
||||
nkBlockStmt, nkDiscardStmt, nkStmtList, nkImportStmt,
|
||||
nkFromStmt, nkImportAs, nkIncludeStmt, nkCommentStmt,
|
||||
nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType,
|
||||
nkVm, nkTypeOfExpr, nkObjectTy, nkTupleTy,
|
||||
nkRecList, nkRecCase, nkRecWhen, nkRefTy,
|
||||
nkPtrTy, nkVarTy, nkAbstractTy, nkProcTy,
|
||||
nkEnumTy, nkEnumFieldDef, nkReturnToken);
|
||||
nkAccQuoted, nkTableConstr, nkQualified, nkBind,
|
||||
nkSymChoice, nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv,
|
||||
nkConv, nkCast, nkAddr, nkHiddenAddr,
|
||||
nkHiddenDeref, nkObjDownConv, nkObjUpConv, nkChckRangeF,
|
||||
nkChckRange64, nkChckRange, nkStringToCString, nkCStringToString,
|
||||
nkPassAsOpenArray, nkAsgn, nkFastAsgn, nkDefaultTypeParam,
|
||||
nkGenericParams, nkFormalParams, nkOfInherit, nkModule,
|
||||
nkProcDef, nkConverterDef, nkMacroDef, nkTemplateDef,
|
||||
nkIteratorDef, nkOfBranch, nkElifBranch, nkExceptBranch,
|
||||
nkElse, nkMacroStmt, nkAsmStmt, nkPragma,
|
||||
nkIfStmt, nkWhenStmt, nkForStmt, nkWhileStmt,
|
||||
nkCaseStmt, nkVarSection, nkConstSection, nkConstDef,
|
||||
nkTypeSection, nkTypeDef, nkYieldStmt, nkTryStmt,
|
||||
nkFinally, nkRaiseStmt, nkReturnStmt, nkBreakStmt,
|
||||
nkContinueStmt, nkBlockStmt, nkDiscardStmt, nkStmtList,
|
||||
nkImportStmt, nkFromStmt, nkImportAs, nkIncludeStmt,
|
||||
nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType,
|
||||
nkBlockType, nkVm, nkTypeOfExpr, nkObjectTy,
|
||||
nkTupleTy, nkRecList, nkRecCase, nkRecWhen,
|
||||
nkRefTy, nkPtrTy, nkVarTy, nkAbstractTy,
|
||||
nkProcTy, nkEnumTy, nkEnumFieldDef, nkReturnToken);
|
||||
TNodeKinds = set of TNodeKind;
|
||||
const
|
||||
NodeKindToStr: array [TNodeKind] of string = (
|
||||
@@ -113,48 +113,48 @@ const
|
||||
'nkCurly', 'nkBracket', 'nkBracketExpr', 'nkPragmaExpr',
|
||||
'nkRange', 'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr',
|
||||
'nkIfExpr', 'nkElifExpr', 'nkElseExpr', 'nkLambda',
|
||||
'nkAccQuoted', 'nkHeaderQuoted', 'nkTableConstr', 'nkQualified',
|
||||
'nkHiddenStdConv', 'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv',
|
||||
'nkCast', 'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref',
|
||||
'nkObjDownConv', 'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64',
|
||||
'nkChckRange', 'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray',
|
||||
'nkAsgn', 'nkFastAsgn', 'nkDefaultTypeParam', 'nkGenericParams',
|
||||
'nkFormalParams', 'nkOfInherit', 'nkModule', 'nkProcDef',
|
||||
'nkConverterDef', 'nkMacroDef', 'nkTemplateDef', 'nkIteratorDef',
|
||||
'nkOfBranch', 'nkElifBranch', 'nkExceptBranch', 'nkElse',
|
||||
'nkMacroStmt', 'nkAsmStmt', 'nkPragma', 'nkIfStmt',
|
||||
'nkWhenStmt', 'nkForStmt', 'nkWhileStmt', 'nkCaseStmt',
|
||||
'nkVarSection', 'nkConstSection', 'nkConstDef', 'nkTypeSection',
|
||||
'nkTypeDef', 'nkYieldStmt', 'nkTryStmt', 'nkFinally',
|
||||
'nkRaiseStmt', 'nkReturnStmt', 'nkBreakStmt', 'nkContinueStmt',
|
||||
'nkBlockStmt', 'nkDiscardStmt', 'nkStmtList', 'nkImportStmt',
|
||||
'nkFromStmt', 'nkImportAs', 'nkIncludeStmt', 'nkCommentStmt',
|
||||
'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType', 'nkBlockType',
|
||||
'nkVm', 'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy',
|
||||
'nkRecList', 'nkRecCase', 'nkRecWhen', 'nkRefTy',
|
||||
'nkPtrTy', 'nkVarTy', 'nkAbstractTy', 'nkProcTy',
|
||||
'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
|
||||
'nkAccQuoted', 'nkTableConstr', 'nkQualified', 'nkBind',
|
||||
'nkSymChoice', 'nkHiddenStdConv', 'nkHiddenSubConv', 'nkHiddenCallConv',
|
||||
'nkConv', 'nkCast', 'nkAddr', 'nkHiddenAddr',
|
||||
'nkHiddenDeref', 'nkObjDownConv', 'nkObjUpConv', 'nkChckRangeF',
|
||||
'nkChckRange64', 'nkChckRange', 'nkStringToCString', 'nkCStringToString',
|
||||
'nkPassAsOpenArray', 'nkAsgn', 'nkFastAsgn', 'nkDefaultTypeParam',
|
||||
'nkGenericParams', 'nkFormalParams', 'nkOfInherit', 'nkModule',
|
||||
'nkProcDef', 'nkConverterDef', 'nkMacroDef', 'nkTemplateDef',
|
||||
'nkIteratorDef', 'nkOfBranch', 'nkElifBranch', 'nkExceptBranch',
|
||||
'nkElse', 'nkMacroStmt', 'nkAsmStmt', 'nkPragma',
|
||||
'nkIfStmt', 'nkWhenStmt', 'nkForStmt', 'nkWhileStmt',
|
||||
'nkCaseStmt', 'nkVarSection', 'nkConstSection', 'nkConstDef',
|
||||
'nkTypeSection', 'nkTypeDef', 'nkYieldStmt', 'nkTryStmt',
|
||||
'nkFinally', 'nkRaiseStmt', 'nkReturnStmt', 'nkBreakStmt',
|
||||
'nkContinueStmt', 'nkBlockStmt', 'nkDiscardStmt', 'nkStmtList',
|
||||
'nkImportStmt', 'nkFromStmt', 'nkImportAs', 'nkIncludeStmt',
|
||||
'nkCommentStmt', 'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType',
|
||||
'nkBlockType', 'nkVm', 'nkTypeOfExpr', 'nkObjectTy',
|
||||
'nkTupleTy', 'nkRecList', 'nkRecCase', 'nkRecWhen',
|
||||
'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkAbstractTy',
|
||||
'nkProcTy', 'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
|
||||
type
|
||||
TSymFlag = (
|
||||
sfUsed, sfStar, sfMinus, sfInInterface,
|
||||
sfFromGeneric, sfGlobal, sfForward, sfImportc,
|
||||
sfExportc, sfVolatile, sfRegister, sfPure,
|
||||
sfResult, sfNoSideEffect, sfMainModule, sfSystemModule,
|
||||
sfNoReturn, sfAddrTaken, sfCompilerProc, sfCppMethod,
|
||||
sfDiscriminant, sfDeprecated, sfInClosure, sfTypeCheck,
|
||||
sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim,
|
||||
sfBorrow);
|
||||
sfResult, sfNoSideEffect, sfSideEffect, sfMainModule,
|
||||
sfSystemModule, sfNoReturn, sfAddrTaken, sfCompilerProc,
|
||||
sfCppMethod, sfDiscriminant, sfDeprecated, sfInClosure,
|
||||
sfTypeCheck, sfCompileTime, sfThreadVar, sfMerge,
|
||||
sfDeadCodeElim, sfBorrow);
|
||||
TSymFlags = set of TSymFlag;
|
||||
const
|
||||
SymFlagToStr: array [TSymFlag] of string = (
|
||||
'sfUsed', 'sfStar', 'sfMinus', 'sfInInterface',
|
||||
'sfFromGeneric', 'sfGlobal', 'sfForward', 'sfImportc',
|
||||
'sfExportc', 'sfVolatile', 'sfRegister', 'sfPure',
|
||||
'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule',
|
||||
'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', 'sfCppMethod',
|
||||
'sfDiscriminant', 'sfDeprecated', 'sfInClosure', 'sfTypeCheck',
|
||||
'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim',
|
||||
'sfBorrow');
|
||||
'sfResult', 'sfNoSideEffect', 'sfSideEffect', 'sfMainModule',
|
||||
'sfSystemModule', 'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc',
|
||||
'sfCppMethod', 'sfDiscriminant', 'sfDeprecated', 'sfInClosure',
|
||||
'sfTypeCheck', 'sfCompileTime', 'sfThreadVar', 'sfMerge',
|
||||
'sfDeadCodeElim', 'sfBorrow');
|
||||
type
|
||||
TTypeKind = (
|
||||
tyNone, tyBool, tyChar, tyEmpty,
|
||||
@@ -189,11 +189,13 @@ const
|
||||
'nfAllConst', 'nfTransf', 'nfSem');
|
||||
type
|
||||
TTypeFlag = (
|
||||
tfVarargs, tfFinal, tfAcyclic, tfEnumHasWholes);
|
||||
tfVarargs, tfNoSideEffect, tfFinal, tfAcyclic,
|
||||
tfEnumHasWholes);
|
||||
TTypeFlags = set of TTypeFlag;
|
||||
const
|
||||
TypeFlagToStr: array [TTypeFlag] of string = (
|
||||
'tfVarargs', 'tfFinal', 'tfAcyclic', 'tfEnumHasWholes');
|
||||
'tfVarargs', 'tfNoSideEffect', 'tfFinal', 'tfAcyclic',
|
||||
'tfEnumHasWholes');
|
||||
type
|
||||
TSymKind = (
|
||||
skUnknownSym, skConditional, skDynLib, skParam,
|
||||
|
||||
@@ -220,8 +220,7 @@ end;
|
||||
function addrLoc(const a: TLoc): PRope;
|
||||
begin
|
||||
result := a.r;
|
||||
if not (lfIndirect in a.flags) then
|
||||
result := con('&'+'', result)
|
||||
if not (lfIndirect in a.flags) then result := con('&'+'', result)
|
||||
end;
|
||||
|
||||
function rdCharLoc(const a: TLoc): PRope;
|
||||
@@ -2257,32 +2256,6 @@ begin
|
||||
end;
|
||||
|
||||
// ---------------------- generation of complex constants ---------------------
|
||||
(*
|
||||
function transformRecordExpr(n: PNode): PNode;
|
||||
var
|
||||
i: int;
|
||||
t: PType;
|
||||
field: PSym;
|
||||
begin
|
||||
result := copyNode(n);
|
||||
newSons(result, sonsLen(n));
|
||||
t := getUniqueType(skipTypes(n.Typ, abstractVarRange));
|
||||
if t.n = nil then
|
||||
InternalError(n.info, 'transformRecordExpr: invalid type');
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
assert(n.sons[i].kind = nkExprColonExpr);
|
||||
assert(n.sons[i].sons[0].kind = nkSym);
|
||||
field := n.sons[i].sons[0].sym;
|
||||
field := lookupInRecord(t.n, field.name);
|
||||
if field = nil then
|
||||
InternalError(n.sons[i].info, 'transformRecordExpr: unknown field');
|
||||
if result.sons[field.position] <> nil then begin
|
||||
InternalError(n.sons[i].info, 'transformRecordExpr: value twice: ' +
|
||||
renderTree(n.sons[i]));
|
||||
end;
|
||||
result.sons[field.position] := copyTree(n.sons[i].sons[1]);
|
||||
end;
|
||||
end; *)
|
||||
|
||||
function genNamedConstExpr(p: BProc; n: PNode): PRope;
|
||||
begin
|
||||
|
||||
@@ -139,16 +139,22 @@ function ropeFormatNamedVars(const frmt: TFormatStr;
|
||||
const varnames: array of string;
|
||||
const varvalues: array of PRope): PRope;
|
||||
var
|
||||
i, j, L, start, idx: int;
|
||||
i, j, L, start, idx, num: int;
|
||||
id: string;
|
||||
begin
|
||||
i := strStart;
|
||||
L := length(frmt);
|
||||
result := nil;
|
||||
num := 0;
|
||||
while i <= L + StrStart - 1 do begin
|
||||
if frmt[i] = '$' then begin
|
||||
inc(i); // skip '$'
|
||||
case frmt[i] of
|
||||
'#': begin
|
||||
app(result, varvalues[num]);
|
||||
inc(num);
|
||||
inc(i);
|
||||
end;
|
||||
'$': begin
|
||||
app(result, '$'+'');
|
||||
inc(i)
|
||||
@@ -162,6 +168,7 @@ begin
|
||||
end;
|
||||
if j > high(varvalues) + 1 then
|
||||
internalError('ropeFormatNamedVars');
|
||||
num := j;
|
||||
app(result, varvalues[j - 1])
|
||||
end;
|
||||
'A'..'Z', 'a'..'z', #128..#255: begin
|
||||
@@ -515,17 +522,17 @@ begin
|
||||
result := renderRstSons(d, n);
|
||||
L := ropeLen(result);
|
||||
result := ropef('$n$1$2$n$1$3', [ind, result,
|
||||
toRope(repeatChar(L, lvlToChar[n.level]))]);
|
||||
toRope(repeatChar(L, lvlToChar[n.level]))]);
|
||||
end;
|
||||
rnOverline: begin
|
||||
result := renderRstSons(d, n);
|
||||
L := ropeLen(result);
|
||||
result := ropef('$n$1$3$n$1$2$n$1$3', [ind, result,
|
||||
toRope(repeatChar(L, lvlToChar[n.level]))]);
|
||||
toRope(repeatChar(L, lvlToChar[n.level]))]);
|
||||
end;
|
||||
rnTransition:
|
||||
result := ropef('$n$n$1$2$n$n',
|
||||
[ind, toRope(repeatChar(78-d.indent, '-'))]);
|
||||
[ind, toRope(repeatChar(78-d.indent, '-'))]);
|
||||
rnParagraph: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropef('$n$n$1$2', [ind, result]);
|
||||
@@ -1003,7 +1010,4 @@ begin
|
||||
generateIndex(d);
|
||||
end;
|
||||
|
||||
// #FFD700
|
||||
// #9f9b75
|
||||
|
||||
end.
|
||||
|
||||
132
nim/evals.pas
132
nim/evals.pas
@@ -35,8 +35,9 @@ type
|
||||
|
||||
TEvalContext = object(passes.TPassContext)
|
||||
module: PSym;
|
||||
tos: PStackFrame; // top of a tos tos
|
||||
tos: PStackFrame; // top of stack
|
||||
lastException: PNode;
|
||||
optEval: bool; // evaluation done for optimization purposes
|
||||
end;
|
||||
PEvalContext = ^TEvalContext;
|
||||
|
||||
@@ -44,12 +45,15 @@ function newStackFrame(): PStackFrame;
|
||||
procedure pushStackFrame(c: PEvalContext; t: PStackFrame);
|
||||
procedure popStackFrame(c: PEvalContext);
|
||||
|
||||
function newEvalContext(module: PSym; const filename: string): PEvalContext;
|
||||
function newEvalContext(module: PSym; const filename: string;
|
||||
optEval: bool): PEvalContext;
|
||||
|
||||
function eval(c: PEvalContext; n: PNode): PNode;
|
||||
// eval never returns nil! This simplifies the code a lot and
|
||||
// makes it faster too.
|
||||
|
||||
function evalConstExpr(module: PSym; e: PNode): PNode;
|
||||
|
||||
function evalPass(): TPass;
|
||||
|
||||
implementation
|
||||
@@ -71,13 +75,15 @@ begin
|
||||
{@emit result.params := @[];}
|
||||
end;
|
||||
|
||||
function newEvalContext(module: PSym; const filename: string): PEvalContext;
|
||||
function newEvalContext(module: PSym; const filename: string;
|
||||
optEval: bool): PEvalContext;
|
||||
begin
|
||||
new(result);
|
||||
{@ignore}
|
||||
fillChar(result^, sizeof(result^), 0);
|
||||
{@emit}
|
||||
result.module := module;
|
||||
result.optEval := optEval;
|
||||
end;
|
||||
|
||||
procedure pushStackFrame(c: PEvalContext; t: PStackFrame);
|
||||
@@ -228,32 +234,35 @@ begin
|
||||
case result.kind of
|
||||
nkBreakStmt, nkReturnToken: begin end;
|
||||
nkExceptBranch: begin
|
||||
// exception token!
|
||||
exc := result;
|
||||
i := 1;
|
||||
len := sonsLen(n);
|
||||
while (i < len) and (n.sons[i].kind = nkExceptBranch) do begin
|
||||
blen := sonsLen(n.sons[i]);
|
||||
if blen = 1 then begin
|
||||
// general except section:
|
||||
result := evalAux(c, n.sons[i].sons[0]);
|
||||
exc := result;
|
||||
break
|
||||
end
|
||||
else begin
|
||||
for j := 0 to blen-2 do begin
|
||||
assert(n.sons[i].sons[j].kind = nkType);
|
||||
if exc.typ.id = n.sons[i].sons[j].typ.id then begin
|
||||
result := evalAux(c, n.sons[i].sons[blen-1]);
|
||||
exc := result;
|
||||
break
|
||||
end
|
||||
if sonsLen(result) >= 1 then begin
|
||||
// creating a nkExceptBranch without sons means that it could not be
|
||||
// evaluated
|
||||
exc := result;
|
||||
i := 1;
|
||||
len := sonsLen(n);
|
||||
while (i < len) and (n.sons[i].kind = nkExceptBranch) do begin
|
||||
blen := sonsLen(n.sons[i]);
|
||||
if blen = 1 then begin
|
||||
// general except section:
|
||||
result := evalAux(c, n.sons[i].sons[0]);
|
||||
exc := result;
|
||||
break
|
||||
end
|
||||
else begin
|
||||
for j := 0 to blen-2 do begin
|
||||
assert(n.sons[i].sons[j].kind = nkType);
|
||||
if exc.typ.id = n.sons[i].sons[j].typ.id then begin
|
||||
result := evalAux(c, n.sons[i].sons[blen-1]);
|
||||
exc := result;
|
||||
break
|
||||
end
|
||||
end
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
result := evalFinally(c, n, exc);
|
||||
end;
|
||||
result := evalFinally(c, n, exc);
|
||||
end
|
||||
end
|
||||
else
|
||||
result := evalFinally(c, n, emptyNode);
|
||||
end
|
||||
@@ -339,6 +348,7 @@ begin
|
||||
if n.typ <> nil then d.params[0] := getNullValue(n.typ, n.info);
|
||||
pushStackFrame(c, d);
|
||||
result := evalAux(c, prc);
|
||||
if result.kind = nkExceptBranch then exit;
|
||||
if n.typ <> nil then result := d.params[0];
|
||||
popStackFrame(c);
|
||||
end;
|
||||
@@ -572,13 +582,24 @@ begin
|
||||
if result.intVal <> 0 then result := evalAux(c, n.sons[2])
|
||||
end;
|
||||
|
||||
function evalNoOpt(c: PEvalContext; n: PNode): PNode;
|
||||
begin
|
||||
result := newNodeI(nkExceptBranch, n.info);
|
||||
// creating a nkExceptBranch without sons means that it could not be
|
||||
// evaluated
|
||||
end;
|
||||
|
||||
function evalNew(c: PEvalContext; n: PNode): PNode;
|
||||
var
|
||||
t: PType;
|
||||
begin
|
||||
t := skipTypes(n.sons[1].typ, abstractVar);
|
||||
result := newNodeIT(nkRefTy, n.info, t);
|
||||
addSon(result, getNullValue(t.sons[0], n.info));
|
||||
if c.optEval then
|
||||
result := evalNoOpt(c, n)
|
||||
else begin
|
||||
t := skipTypes(n.sons[1].typ, abstractVar);
|
||||
result := newNodeIT(nkRefTy, n.info, t);
|
||||
addSon(result, getNullValue(t.sons[0], n.info));
|
||||
end
|
||||
end;
|
||||
|
||||
function evalDeref(c: PEvalContext; n: PNode): PNode;
|
||||
@@ -740,6 +761,7 @@ end;
|
||||
function evalSetLengthStr(c: PEvalContext; n: PNode): PNode;
|
||||
var
|
||||
a, b: PNode;
|
||||
oldLen, newLen: int;
|
||||
begin
|
||||
result := evalAux(c, n.sons[1]);
|
||||
if result.kind = nkExceptBranch then exit;
|
||||
@@ -748,7 +770,16 @@ begin
|
||||
if result.kind = nkExceptBranch then exit;
|
||||
b := result;
|
||||
case a.kind of
|
||||
nkStrLit..nkTripleStrLit: setLength(a.strVal, int(getOrdValue(b)));
|
||||
nkStrLit..nkTripleStrLit: begin
|
||||
{@ignore}
|
||||
oldLen := length(a.strVal);
|
||||
{@emit}
|
||||
newLen := int(getOrdValue(b));
|
||||
setLength(a.strVal, newLen);
|
||||
{@ignore}
|
||||
FillChar(a.strVal[oldLen+1], newLen-oldLen, 0);
|
||||
{@emit}
|
||||
end
|
||||
else InternalError(n.info, 'evalSetLengthStr')
|
||||
end;
|
||||
result := emptyNode
|
||||
@@ -1241,6 +1272,7 @@ end;
|
||||
function evalAux(c: PEvalContext; n: PNode): PNode;
|
||||
var
|
||||
i: int;
|
||||
a: PNode;
|
||||
begin
|
||||
result := emptyNode;
|
||||
dec(gNestedEvals);
|
||||
@@ -1254,13 +1286,22 @@ begin
|
||||
nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand:
|
||||
result := evalMagicOrCall(c, n);
|
||||
nkCurly, nkBracket, nkRange: begin
|
||||
result := copyNode(n);
|
||||
for i := 0 to sonsLen(n)-1 do addSon(result, evalAux(c, n.sons[i]));
|
||||
a := copyNode(n);
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
result := evalAux(c, n.sons[i]);
|
||||
if result.kind = nkExceptBranch then exit;
|
||||
addSon(a, result);
|
||||
end;
|
||||
result := a
|
||||
end;
|
||||
nkPar: begin
|
||||
result := copyTree(n);
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
result.sons[i].sons[1] := evalAux(c, n.sons[i].sons[1]);
|
||||
a := copyTree(n);
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
result := evalAux(c, n.sons[i].sons[1]);
|
||||
if result.kind = nkExceptBranch then exit;
|
||||
a.sons[i].sons[1] := result;
|
||||
end;
|
||||
result := a
|
||||
end;
|
||||
nkBracketExpr: result := evalArrayAccess(c, n);
|
||||
nkDotExpr: result := evalFieldAccess(c, n);
|
||||
@@ -1313,15 +1354,30 @@ begin
|
||||
gWhileCounter := evalMaxIterations;
|
||||
gNestedEvals := evalMaxRecDepth;
|
||||
result := evalAux(c, n);
|
||||
if result.kind = nkExceptBranch then
|
||||
if (result.kind = nkExceptBranch) and (sonsLen(result) >= 1) then
|
||||
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ));
|
||||
end;
|
||||
|
||||
function evalConstExpr(module: PSym; e: PNode): PNode;
|
||||
var
|
||||
p: PEvalContext;
|
||||
s: PStackFrame;
|
||||
begin
|
||||
p := newEvalContext(module, '', true);
|
||||
s := newStackFrame();
|
||||
s.call := e;
|
||||
pushStackFrame(p, s);
|
||||
result := eval(p, e);
|
||||
if (result <> nil) and (result.kind = nkExceptBranch) then
|
||||
result := nil;
|
||||
popStackFrame(p);
|
||||
end;
|
||||
|
||||
function myOpen(module: PSym; const filename: string): PPassContext;
|
||||
var
|
||||
c: PEvalContext;
|
||||
begin
|
||||
c := newEvalContext(module, filename);
|
||||
c := newEvalContext(module, filename, false);
|
||||
pushStackFrame(c, newStackFrame());
|
||||
result := c;
|
||||
end;
|
||||
|
||||
@@ -68,8 +68,8 @@ begin
|
||||
if (check <> nil) and (check.id <> copy.id) then begin
|
||||
if not (s.kind in OverloadableSyms) then begin
|
||||
// s and check need to be qualified:
|
||||
IntSetIncl(c.AmbigiousSymbols, copy.id);
|
||||
IntSetIncl(c.AmbigiousSymbols, check.id);
|
||||
IntSetIncl(c.AmbiguousSymbols, copy.id);
|
||||
IntSetIncl(c.AmbiguousSymbols, check.id);
|
||||
end
|
||||
end;
|
||||
StrTableAdd(c.tab.stack[importTablePos], copy);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
//
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2008 Andreas Rumpf
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
@@ -19,7 +19,8 @@ uses
|
||||
{$include 'config.inc'}
|
||||
|
||||
type
|
||||
TOverloadIterMode = (oimNoQualifier, oimSelfModule, oimOtherModule);
|
||||
TOverloadIterMode = (oimDone, oimNoQualifier, oimSelfModule, oimOtherModule,
|
||||
oimSymChoice);
|
||||
TOverloadIter = record
|
||||
stackPtr: int;
|
||||
it: TIdentIter;
|
||||
@@ -43,7 +44,7 @@ procedure addInterfaceOverloadableSymAt(c: PContext; sym: PSym; at: int);
|
||||
function lookUp(c: PContext; n: PNode): PSym;
|
||||
// Looks up a symbol. Generates an error in case of nil.
|
||||
|
||||
function QualifiedLookUp(c: PContext; n: PNode; ambigiousCheck: bool): PSym;
|
||||
function QualifiedLookUp(c: PContext; n: PNode; ambiguousCheck: bool): PSym;
|
||||
|
||||
function InitOverloadIter(out o: TOverloadIter; c: PContext; n: PNode): PSym;
|
||||
function nextOverloadIter(var o: TOverloadIter; c: PContext; n: PNode): PSym;
|
||||
@@ -139,22 +140,22 @@ begin
|
||||
result := SymtabGet(c.Tab, n.sym.name);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
|
||||
include(result.flags, sfUsed);
|
||||
//include(result.flags, sfUsed);
|
||||
end;
|
||||
nkIdent: begin
|
||||
result := SymtabGet(c.Tab, n.ident);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.ident.s);
|
||||
include(result.flags, sfUsed);
|
||||
//include(result.flags, sfUsed);
|
||||
end
|
||||
else InternalError(n.info, 'lookUp');
|
||||
end;
|
||||
if IntSetContains(c.AmbigiousSymbols, result.id) then
|
||||
if IntSetContains(c.AmbiguousSymbols, result.id) then
|
||||
liMessage(n.info, errUseQualifier, result.name.s);
|
||||
if result.kind = skStub then loadStub(result);
|
||||
end;
|
||||
|
||||
function QualifiedLookUp(c: PContext; n: PNode; ambigiousCheck: bool): PSym;
|
||||
function QualifiedLookUp(c: PContext; n: PNode; ambiguousCheck: bool): PSym;
|
||||
var
|
||||
m: PSym;
|
||||
ident: PIdent;
|
||||
@@ -164,16 +165,16 @@ begin
|
||||
result := SymtabGet(c.Tab, n.ident);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
else if ambigiousCheck
|
||||
and IntSetContains(c.AmbigiousSymbols, result.id) then
|
||||
else if ambiguousCheck
|
||||
and IntSetContains(c.AmbiguousSymbols, result.id) then
|
||||
liMessage(n.info, errUseQualifier, n.ident.s)
|
||||
end;
|
||||
nkSym: begin
|
||||
result := SymtabGet(c.Tab, n.sym.name);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
|
||||
else if ambigiousCheck
|
||||
and IntSetContains(c.AmbigiousSymbols, result.id) then
|
||||
else if ambiguousCheck
|
||||
and IntSetContains(c.AmbiguousSymbols, result.id) then
|
||||
liMessage(n.info, errUseQualifier, n.sym.name.s)
|
||||
end;
|
||||
nkDotExpr, nkQualified: begin
|
||||
@@ -200,7 +201,7 @@ begin
|
||||
renderTree(n.sons[1]));
|
||||
end
|
||||
end;
|
||||
nkAccQuoted: result := QualifiedLookup(c, n.sons[0], ambigiousCheck);
|
||||
nkAccQuoted: result := QualifiedLookup(c, n.sons[0], ambiguousCheck);
|
||||
else begin
|
||||
result := nil;
|
||||
//liMessage(n.info, errIdentifierExpected, '')
|
||||
@@ -224,15 +225,18 @@ begin
|
||||
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident);
|
||||
end;
|
||||
end;
|
||||
nkSym: begin
|
||||
nkSym: begin
|
||||
result := n.sym;
|
||||
o.mode := oimDone;
|
||||
(*
|
||||
o.stackPtr := c.tab.tos;
|
||||
o.mode := oimNoQualifier;
|
||||
while (result = nil) do begin
|
||||
dec(o.stackPtr);
|
||||
if o.stackPtr < 0 then break;
|
||||
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name);
|
||||
end;
|
||||
end;
|
||||
end; *)
|
||||
end;
|
||||
nkDotExpr, nkQualified: begin
|
||||
o.mode := oimOtherModule;
|
||||
o.m := qualifiedLookUp(c, n.sons[0], false);
|
||||
@@ -258,6 +262,11 @@ begin
|
||||
end
|
||||
end;
|
||||
nkAccQuoted: result := InitOverloadIter(o, c, n.sons[0]);
|
||||
nkSymChoice: begin
|
||||
o.mode := oimSymChoice;
|
||||
result := n.sons[0].sym;
|
||||
o.stackPtr := 1
|
||||
end;
|
||||
else begin end
|
||||
end;
|
||||
if (result <> nil) and (result.kind = skStub) then loadStub(result);
|
||||
@@ -266,6 +275,7 @@ end;
|
||||
function nextOverloadIter(var o: TOverloadIter; c: PContext; n: PNode): PSym;
|
||||
begin
|
||||
case o.mode of
|
||||
oimDone: result := nil;
|
||||
oimNoQualifier: begin
|
||||
if n.kind = nkAccQuoted then
|
||||
result := nextOverloadIter(o, c, n.sons[0]) // BUGFIX
|
||||
@@ -282,6 +292,14 @@ begin
|
||||
end;
|
||||
oimSelfModule: result := nextIdentIter(o.it, c.tab.stack[ModuleTablePos]);
|
||||
oimOtherModule: result := nextIdentIter(o.it, o.m.tab);
|
||||
oimSymChoice: begin
|
||||
if o.stackPtr < sonsLen(n) then begin
|
||||
result := n.sons[o.stackPtr].sym;
|
||||
inc(o.stackPtr);
|
||||
end
|
||||
else
|
||||
result := nil
|
||||
end;
|
||||
end;
|
||||
if (result <> nil) and (result.kind = skStub) then loadStub(result);
|
||||
end;
|
||||
|
||||
62
nim/msgs.pas
62
nim/msgs.pas
@@ -1,7 +1,7 @@
|
||||
//
|
||||
//
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2008 Andreas Rumpf
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
@@ -79,19 +79,15 @@ type
|
||||
errNoneSpeedOrSizeExpected,
|
||||
errInvalidPragma,
|
||||
errUnknownPragma,
|
||||
errPragmaXHereNotAllowed,
|
||||
errUnknownDirective,
|
||||
errInvalidDirective,
|
||||
errAtPopWithoutPush,
|
||||
errEmptyAsm,
|
||||
errAsgnInvalidInExpr,
|
||||
errInvalidIndentation,
|
||||
errExceptionExpected,
|
||||
errExceptionAlreadyHandled,
|
||||
errReturnNotAllowedHere,
|
||||
errYieldNotAllowedHere,
|
||||
errInvalidNumberOfYieldExpr,
|
||||
errReturnInvalidInIterator,
|
||||
errCannotReturnExpr,
|
||||
errAttemptToRedefine,
|
||||
errStmtInvalidAfterReturn,
|
||||
@@ -116,7 +112,6 @@ type
|
||||
errExprExpected,
|
||||
errUndeclaredIdentifier,
|
||||
errUseQualifier,
|
||||
errTwiceForwarded,
|
||||
errTypeExpected,
|
||||
errSystemNeeds,
|
||||
errExecutionOfProgramFailed,
|
||||
@@ -126,8 +121,7 @@ type
|
||||
errXExpectsTypeOrValue,
|
||||
errXExpectsArrayType,
|
||||
errIteratorCannotBeInstantiated,
|
||||
errExprWithNoTypeCannotBeConverted,
|
||||
errExprWithNoTypeCannotBeCasted,
|
||||
errExprXAmbiguous,
|
||||
errConstantDivisionByZero,
|
||||
errOrdinalTypeExpected,
|
||||
errOrdinalOrFloatTypeExpected,
|
||||
@@ -145,21 +139,17 @@ type
|
||||
errValueOutOfSetBounds,
|
||||
errFieldInitTwice,
|
||||
errFieldNotInit,
|
||||
errExprCannotBeCalled,
|
||||
errExprXCannotBeCalled,
|
||||
errExprHasNoType,
|
||||
errExprXHasNoType,
|
||||
errCastNotInSafeMode,
|
||||
errExprCannotBeCastedToX,
|
||||
errUndefinedPrefixOpr,
|
||||
errCommaOrParRiExpected,
|
||||
errCurlyLeOrParLeExpected,
|
||||
errSectionExpected,
|
||||
errImplemenationExpected,
|
||||
errRangeExpected,
|
||||
errInvalidTypeDescription,
|
||||
errAttemptToRedefineX,
|
||||
errMagicOnlyInSystem,
|
||||
errUnknownOperatorX,
|
||||
errPowerOfTwoExpected,
|
||||
errStringMayNotBeEmpty,
|
||||
errCallConvExpected,
|
||||
@@ -193,9 +183,8 @@ type
|
||||
errTypeMismatch,
|
||||
errButExpected,
|
||||
errButExpectedX,
|
||||
errAmbigiousCallXYZ,
|
||||
errAmbiguousCallXYZ,
|
||||
errWrongNumberOfTypeParams,
|
||||
errOutParamNoDefaultValue,
|
||||
errInlineProcHasNoAddress,
|
||||
errXCannotBeInParamDecl,
|
||||
errPragmaOnlyInHeaderOfProc,
|
||||
@@ -204,21 +193,15 @@ type
|
||||
errNoSymbolToBorrowFromFound,
|
||||
errDiscardValue,
|
||||
errInvalidDiscard,
|
||||
errUnknownPrecedence,
|
||||
errIllegalConvFromXtoY,
|
||||
errTypeMismatchExpectedXGotY,
|
||||
errCannotBindXTwice,
|
||||
errInvalidOrderInEnumX,
|
||||
errEnumXHasWholes,
|
||||
errExceptExpected,
|
||||
errInvalidTry,
|
||||
errEofExpectedButXFound,
|
||||
errOptionExpected,
|
||||
errCannotEvaluateForwardConst,
|
||||
errXisNoLabel,
|
||||
errXNeedsConcreteType,
|
||||
errNotAllCasesCovered,
|
||||
errStringRange,
|
||||
errUnkownSubstitionVar,
|
||||
errComplexStmtRequiresInd,
|
||||
errXisNotCallable,
|
||||
@@ -279,6 +262,7 @@ type
|
||||
errUnhandledExceptionX,
|
||||
errCyclicTree,
|
||||
errXisNoMacroOrTemplate,
|
||||
errXhasSideEffects,
|
||||
errUser,
|
||||
warnCannotOpenFile,
|
||||
warnOctalEscape,
|
||||
@@ -338,19 +322,15 @@ const
|
||||
'''none'', ''speed'' or ''size'' expected',
|
||||
'invalid pragma',
|
||||
'unknown pragma: ''$1''',
|
||||
'pragma ''$1'' here not allowed',
|
||||
'unknown directive: ''$1''',
|
||||
'invalid directive',
|
||||
'''pop'' without a ''push'' pragma',
|
||||
'empty asm statement makes no sense',
|
||||
'''='' invalid in an expression; probably ''=='' meant',
|
||||
'invalid indentation',
|
||||
'exception expected',
|
||||
'exception already handled',
|
||||
'''return'' only allowed in routine',
|
||||
'''yield'' only allowed in a loop of an iterator',
|
||||
'invalid number of ''yield'' expresions',
|
||||
'''return'' not allowed in iterator',
|
||||
'current routine cannot return an expression',
|
||||
'attempt to redefine ''$1''',
|
||||
'statement not allowed after ''return'', ''break'' or ''raise''',
|
||||
@@ -374,19 +354,17 @@ const
|
||||
''':'' or ''='' expected, but found ''$1''',
|
||||
'expression expected, but found ''$1''',
|
||||
'undeclared identifier: ''$1''',
|
||||
'ambigious identifier: ''$1'' -- use a qualifier',
|
||||
'''$1'' is forwarded twice',
|
||||
'ambiguous identifier: ''$1'' -- use a qualifier',
|
||||
'type expected',
|
||||
'system module needs ''$1''',
|
||||
'execution of an external program failed',
|
||||
'overloaded ''$1'' leads to ambigious calls',
|
||||
'overloaded ''$1'' leads to ambiguous calls',
|
||||
'invalid argument for ''$1''',
|
||||
'statement has no effect',
|
||||
'''$1'' expects a type or value',
|
||||
'''$1'' expects an array type',
|
||||
'''$1'' cannot be instantiated because its body has not been compiled yet',
|
||||
'expression with no type cannot be converted',
|
||||
'expression with no type cannot be casted',
|
||||
'expression ''$1'' ambiguous in this context',
|
||||
'constant division by zero',
|
||||
'ordinal type expected',
|
||||
'ordinal or float type expected',
|
||||
@@ -404,21 +382,17 @@ const
|
||||
'value out of set bounds',
|
||||
'field initialized twice: ''$1''',
|
||||
'field ''$1'' not initialized',
|
||||
'expression cannot be called',
|
||||
'expression ''$1'' cannot be called',
|
||||
'expression has no type',
|
||||
'expression ''$1'' has no type',
|
||||
'expression ''$1'' has no type (or is ambiguous)',
|
||||
'''cast'' not allowed in safe mode',
|
||||
'expression cannot be casted to $1',
|
||||
'undefined prefix operator: $1',
|
||||
''','' or '')'' expected',
|
||||
'''{'' or ''('' expected',
|
||||
'section (''type'', ''proc'', etc.) expected',
|
||||
'''implementation'' or end of file expected',
|
||||
'range expected',
|
||||
'invalid type description',
|
||||
'attempt to redefine ''$1''',
|
||||
'''magic'' only allowed in system module',
|
||||
'unkown operator: ''$1''',
|
||||
'power of two expected',
|
||||
'string literal may not be empty',
|
||||
'calling convention expected',
|
||||
@@ -452,9 +426,8 @@ const
|
||||
'type mismatch: got (',
|
||||
'but expected one of: ',
|
||||
'but expected ''$1''',
|
||||
'ambigious call; both $1 and $2 match for: $3',
|
||||
'ambiguous call; both $1 and $2 match for: $3',
|
||||
'wrong number of type parameters',
|
||||
'out parameters cannot have default values',
|
||||
'an inline proc has no address',
|
||||
'$1 cannot be declared in parameter declaration',
|
||||
'pragmas are only in the header of a proc allowed',
|
||||
@@ -463,21 +436,15 @@ const
|
||||
'no symbol to borrow from found',
|
||||
'value returned by statement has to be discarded',
|
||||
'statement returns no value that can be discarded',
|
||||
'unknown precedence for operator; use ''infix: prec'' pragma',
|
||||
'conversion from $1 to $2 is invalid',
|
||||
'type mismatch: expected ''$1'', but got ''$2''',
|
||||
'cannot bind parameter ''$1'' twice',
|
||||
'invalid order in enum ''$1''',
|
||||
'enum ''$1'' has wholes',
|
||||
'''except'' or ''finally'' expected',
|
||||
'after catch all ''except'' or ''finally'' no section may follow',
|
||||
'end of file expected, but found token ''$1''',
|
||||
'option expected, but found ''$1''',
|
||||
'cannot evaluate forwarded constant',
|
||||
'''$1'' is not a label',
|
||||
'''$1'' needs to be of a non-generic type',
|
||||
'not all cases are covered',
|
||||
'string range in case statement not allowed',
|
||||
'unknown substitution variable: ''$1''',
|
||||
'complex statement requires indentation',
|
||||
'''$1'' is not callable',
|
||||
@@ -489,7 +456,7 @@ const
|
||||
'no return type for $1 allowed',
|
||||
'a type conversion needs exactly one argument',
|
||||
'invalid pragma: $1',
|
||||
'$1 here not allowed',
|
||||
'$1 not allowed here',
|
||||
'invalid control flow: $1',
|
||||
'a type has no value',
|
||||
'invalid type: ''$1''',
|
||||
@@ -499,11 +466,11 @@ const
|
||||
'invalid expression: ''$1''',
|
||||
'enum has no value ''$1''',
|
||||
'named expression expected',
|
||||
'named expression here not allowed',
|
||||
'named expression not allowed here',
|
||||
'''$1'' expects one type parameter',
|
||||
'array expects two type parameters',
|
||||
'invalid invisibility: ''$1''',
|
||||
'initialization here not allowed',
|
||||
'initialization not allowed here',
|
||||
'''$1'' cannot be assigned to',
|
||||
'iterators can only be defined at the module''s top level',
|
||||
'iterator needs an implementation',
|
||||
@@ -538,6 +505,7 @@ const
|
||||
'unhandled exception: $1',
|
||||
'macro returned a cyclic abstract syntax tree',
|
||||
'''$1'' is no macro or template',
|
||||
'''$1'' can have side effects',
|
||||
'$1',
|
||||
'cannot open ''$1'' [CannotOpenFile]',
|
||||
'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
//
|
||||
//
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2008 Andreas Rumpf
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
//
|
||||
unit nimsets;
|
||||
|
||||
// this unit handles Morpork sets; it implements symbolic sets
|
||||
// the code here should be reused in the Morpork standard library
|
||||
// this unit handles Nimrod sets; it implements symbolic sets
|
||||
|
||||
interface
|
||||
|
||||
|
||||
@@ -40,12 +40,11 @@ const
|
||||
ImportBlackList: array [1..3] of string = (
|
||||
'nsystem', 'sysutils', 'charsets'
|
||||
);
|
||||
stdReplacements: array [1..20] of TReplaceTuple = (
|
||||
stdReplacements: array [1..19] of TReplaceTuple = (
|
||||
('include', 'incl'),
|
||||
('exclude', 'excl'),
|
||||
('pchar', 'cstring'),
|
||||
('close', 'closeFile'),
|
||||
('assignfile', 'openFile'),
|
||||
('assignfile', 'open'),
|
||||
('integer', 'int'),
|
||||
('longword', 'int32'),
|
||||
('cardinal', 'int'),
|
||||
@@ -62,10 +61,12 @@ const
|
||||
('len', 'length'),
|
||||
('setlength', 'setlen')
|
||||
);
|
||||
nimReplacements: array [1..30] of TReplaceTuple = (
|
||||
nimReplacements: array [1..32] of TReplaceTuple = (
|
||||
('nimread', 'read'),
|
||||
('nimwrite', 'write'),
|
||||
('nimclosefile', 'closeFile'),
|
||||
('nimclosefile', 'close'),
|
||||
('closefile', 'close'),
|
||||
('openfile', 'open'),
|
||||
('nsystem', 'system'),
|
||||
('ntime', 'times'),
|
||||
('nos', 'os'),
|
||||
@@ -1972,7 +1973,7 @@ begin
|
||||
if isHandledDirective(p) then
|
||||
addSon(result, parseDirective(p))
|
||||
else
|
||||
parMessage(p, errPragmaXHereNotAllowed, p.tok.ident.s)
|
||||
parMessage(p, errXNotAllowedHere, p.tok.ident.s)
|
||||
end
|
||||
else addSon(result, parseStmt(p))
|
||||
end;
|
||||
|
||||
@@ -313,9 +313,8 @@ end;
|
||||
function accExpr(var p: TParser): PNode;
|
||||
var
|
||||
x, y: PNode;
|
||||
info: TLineInfo;
|
||||
begin
|
||||
info := parLineInfo(p);
|
||||
result := newNodeP(nkAccQuoted, p);
|
||||
getTok(p); // skip `
|
||||
x := nil;
|
||||
y := nil;
|
||||
@@ -343,16 +342,7 @@ begin
|
||||
end
|
||||
end;
|
||||
end;
|
||||
if (p.tok.tokType = tkParLe) or (p.tok.tokType = tkColon) then begin
|
||||
result := newNodeP(nkHeaderQuoted, p);
|
||||
addSon(result, x);
|
||||
addSon(result, parseParamList(p));
|
||||
end
|
||||
else begin
|
||||
result := newNodeP(nkAccQuoted, p);
|
||||
addSon(result, x);
|
||||
end;
|
||||
result.info := info;
|
||||
addSon(result, x);
|
||||
eat(p, tkAccent);
|
||||
end;
|
||||
|
||||
@@ -665,6 +655,13 @@ begin
|
||||
optInd(p, a);
|
||||
addSon(result, primary(p));
|
||||
exit
|
||||
end
|
||||
else if p.tok.tokType = tkBind then begin
|
||||
result := newNodeP(nkBind, p);
|
||||
getTok(p);
|
||||
optInd(p, result);
|
||||
addSon(result, primary(p));
|
||||
exit
|
||||
end;
|
||||
result := identOrLiteral(p);
|
||||
while true do begin
|
||||
@@ -798,7 +795,7 @@ end;
|
||||
function isExprStart(const p: TParser): bool;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkLambda,
|
||||
tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkLambda, tkBind,
|
||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit: result := true;
|
||||
else result := false;
|
||||
end;
|
||||
|
||||
@@ -499,7 +499,11 @@ begin
|
||||
// otherwise header would not make sense
|
||||
if sym.loc.r = nil then sym.loc.r := toRope(sym.name.s)
|
||||
end;
|
||||
wNosideeffect: begin noVal(it); Include(sym.flags, sfNoSideEffect); end;
|
||||
wNosideeffect: begin
|
||||
noVal(it); Include(sym.flags, sfNoSideEffect);
|
||||
if sym.typ <> nil then include(sym.typ.flags, tfNoSideEffect);
|
||||
end;
|
||||
wSideEffect: begin noVal(it); Include(sym.flags, sfSideEffect); end;
|
||||
wNoReturn: begin noVal(it); Include(sym.flags, sfNoReturn); end;
|
||||
wDynLib: processDynLib(c, it, sym);
|
||||
wCompilerProc: begin
|
||||
@@ -597,7 +601,7 @@ end;
|
||||
procedure pragmaProc(c: PContext; s: PSym; n: PNode);
|
||||
begin
|
||||
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
|
||||
wImportc, wExportc, wNodecl, wMagic, wNosideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wNosideEffect, wSideEffect,
|
||||
wNoreturn, wDynLib, wHeader, wCompilerProc, wPure,
|
||||
wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow]);
|
||||
@@ -612,7 +616,8 @@ end;
|
||||
|
||||
procedure pragmaIterator(c: PContext; s: PSym; n: PNode);
|
||||
begin
|
||||
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
|
||||
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
|
||||
wNosideEffect, wSideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]);
|
||||
end;
|
||||
|
||||
@@ -630,7 +635,7 @@ end;
|
||||
procedure pragmaLambda(c: PContext; s: PSym; n: PNode);
|
||||
begin
|
||||
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
|
||||
wImportc, wExportc, wNodecl, wNosideEffect,
|
||||
wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect,
|
||||
wNoreturn, wDynLib, wHeader, wPure, wDeprecated]);
|
||||
end;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
//
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2008 Andreas Rumpf
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
@@ -498,8 +498,10 @@ begin
|
||||
nkCommand: result := lsub(n.sons[0])+lcomma(n, 1)+1;
|
||||
nkExprEqExpr, nkDefaultTypeParam, nkAsgn, nkFastAsgn: result := lsons(n)+3;
|
||||
nkPar, nkCurly, nkBracket: result := lcomma(n)+2;
|
||||
nkSymChoice: result := lsons(n) + length('()') + sonsLen(n)-1;
|
||||
nkTupleTy: result := lcomma(n)+length('tuple[]');
|
||||
nkQualified, nkDotExpr: result := lsons(n)+1;
|
||||
nkBind: result := lsons(n)+length('bind_');
|
||||
nkCheckedFieldExpr: result := lsub(n.sons[0]);
|
||||
nkLambda: result := lsons(n)+length('lambda__=_');
|
||||
nkConstDef, nkIdentDefs: begin
|
||||
@@ -531,7 +533,6 @@ begin
|
||||
nkDerefExpr: result := lsub(n.sons[0])+2;
|
||||
nkImportAs: result := lsons(n) + length('_as_');
|
||||
nkAccQuoted: result := lsub(n.sons[0]) + 2;
|
||||
nkHeaderQuoted: result := lsub(n.sons[0]) + lsub(n.sons[1]) + 2;
|
||||
|
||||
nkIfExpr: result := lsub(n.sons[0].sons[0])+lsub(n.sons[0].sons[1])
|
||||
+ lsons(n, 1) + length('if_:_');
|
||||
@@ -1023,6 +1024,14 @@ begin
|
||||
gcomma(g, n, 1);
|
||||
put(g, tkParRi, ')'+'');
|
||||
end;
|
||||
nkSymChoice: begin
|
||||
put(g, tkParLe, '('+'');
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
if i > 0 then put(g, tkOpr, '|'+'');
|
||||
gsub(g, n.sons[i], c);
|
||||
end;
|
||||
put(g, tkParRi, ')'+'');
|
||||
end;
|
||||
nkPar: begin
|
||||
put(g, tkParLe, '('+'');
|
||||
gcomma(g, n, c);
|
||||
@@ -1043,6 +1052,10 @@ begin
|
||||
put(g, tkDot, '.'+'');
|
||||
gsub(g, n.sons[1]);
|
||||
end;
|
||||
nkBind: begin
|
||||
putWithSpace(g, tkBind, 'bind');
|
||||
gsub(g, n.sons[0]);
|
||||
end;
|
||||
nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]);
|
||||
nkLambda: begin
|
||||
assert(n.sons[genericParamsPos] = nil);
|
||||
@@ -1119,12 +1132,6 @@ begin
|
||||
gsub(g, n.sons[0]);
|
||||
put(g, tkAccent, '`'+'');
|
||||
end;
|
||||
nkHeaderQuoted: begin
|
||||
put(g, tkAccent, '`'+'');
|
||||
gsub(g, n.sons[0]);
|
||||
gsub(g, n.sons[1]);
|
||||
put(g, tkAccent, '`'+'');
|
||||
end;
|
||||
nkIfExpr: begin
|
||||
putWithSpace(g, tkIf, 'if');
|
||||
gsub(g, n.sons[0].sons[0]);
|
||||
|
||||
@@ -488,22 +488,25 @@ end;
|
||||
|
||||
function ropef(const frmt: TFormatStr; const args: array of PRope): PRope;
|
||||
var
|
||||
i, j, len, start: int;
|
||||
i, j, len, start, num: int;
|
||||
begin
|
||||
i := strStart;
|
||||
len := length(frmt);
|
||||
result := nil;
|
||||
num := 0;
|
||||
while i <= len + StrStart - 1 do begin
|
||||
if frmt[i] = '$' then begin
|
||||
inc(i); // skip '$'
|
||||
case frmt[i] of
|
||||
'$': begin app(result, '$'+''); inc(i); end;
|
||||
'#': begin inc(i); app(result, args[num]); inc(num); end;
|
||||
'0'..'9': begin
|
||||
j := 0;
|
||||
repeat
|
||||
j := (j*10) + Ord(frmt[i]) - ord('0');
|
||||
inc(i);
|
||||
until (i > len + StrStart - 1) or not (frmt[i] in ['0'..'9']);
|
||||
num := j;
|
||||
if j > high(args)+1 then
|
||||
internalError('ropes: invalid format string $' + toString(j));
|
||||
app(result, args[j-1]);
|
||||
|
||||
@@ -53,10 +53,10 @@ type
|
||||
//cog.out(idents)
|
||||
//]]]
|
||||
tkAbstract, tkAddr, tkAnd, tkAs,
|
||||
tkAsm, tkBlock, tkBreak, tkCase,
|
||||
tkCast, tkConst, tkContinue, tkConverter,
|
||||
tkDiscard, tkDiv, tkElif, tkElse,
|
||||
tkEnd, tkEnum, tkExcept, tkException,
|
||||
tkAsm, tkBind, tkBlock, tkBreak,
|
||||
tkCase, tkCast, tkConst, tkContinue,
|
||||
tkConverter, tkDiscard, tkDiv, tkElif,
|
||||
tkElse, tkEnd, tkEnum, tkExcept,
|
||||
tkFinally, tkFor, tkFrom, tkGeneric,
|
||||
tkIf, tkImplies, tkImport, tkIn,
|
||||
tkInclude, tkIs, tkIsnot, tkIterator,
|
||||
@@ -97,10 +97,10 @@ const
|
||||
//cog.out(strings)
|
||||
//]]]
|
||||
'abstract', 'addr', 'and', 'as',
|
||||
'asm', 'block', 'break', 'case',
|
||||
'cast', 'const', 'continue', 'converter',
|
||||
'discard', 'div', 'elif', 'else',
|
||||
'end', 'enum', 'except', 'exception',
|
||||
'asm', 'bind', 'block', 'break',
|
||||
'case', 'cast', 'const', 'continue',
|
||||
'converter', 'discard', 'div', 'elif',
|
||||
'else', 'end', 'enum', 'except',
|
||||
'finally', 'for', 'from', 'generic',
|
||||
'if', 'implies', 'import', 'in',
|
||||
'include', 'is', 'isnot', 'iterator',
|
||||
|
||||
11
nim/sem.pas
11
nim/sem.pas
@@ -90,8 +90,6 @@ end;
|
||||
function semAndEvalConstExpr(c: PContext; n: PNode): PNode;
|
||||
var
|
||||
e: PNode;
|
||||
p: PEvalContext;
|
||||
s: PStackFrame;
|
||||
begin
|
||||
e := semExprWithType(c, n);
|
||||
if e = nil then begin
|
||||
@@ -101,12 +99,7 @@ begin
|
||||
result := getConstExpr(c.module, e);
|
||||
if result = nil then begin
|
||||
//writeln(output, renderTree(n));
|
||||
p := newEvalContext(c.module, '');
|
||||
s := newStackFrame();
|
||||
s.call := e;
|
||||
pushStackFrame(p, s);
|
||||
result := eval(p, e);
|
||||
popStackFrame(p);
|
||||
result := evalConstExpr(c.module, e);
|
||||
if (result = nil) or (result.kind = nkEmpty) then
|
||||
liMessage(n.info, errConstExprExpected);
|
||||
end
|
||||
@@ -135,7 +128,7 @@ var
|
||||
s: PStackFrame;
|
||||
begin
|
||||
include(sym.flags, sfUsed);
|
||||
p := newEvalContext(c.module, '');
|
||||
p := newEvalContext(c.module, '', false);
|
||||
s := newStackFrame();
|
||||
s.call := n;
|
||||
setLength(s.params, 2);
|
||||
|
||||
@@ -45,7 +45,7 @@ type
|
||||
module: PSym; // the module sym belonging to the context
|
||||
filename: string; // the module's filename
|
||||
tab: TSymTab; // each module has its own symbol table
|
||||
AmbigiousSymbols: TIntSet; // contains ids of all ambigious symbols (cannot
|
||||
AmbiguousSymbols: TIntSet; // contains ids of all ambiguous symbols (cannot
|
||||
// store this info in the syms themselves!)
|
||||
generics: PNode; // a list of the things to compile; list of
|
||||
// nkExprEqExpr nodes which contain the generic
|
||||
@@ -156,7 +156,7 @@ begin
|
||||
fillChar(result^, sizeof(result^), 0);
|
||||
{@emit}
|
||||
InitSymTab(result.tab);
|
||||
IntSetInit(result.AmbigiousSymbols);
|
||||
IntSetInit(result.AmbiguousSymbols);
|
||||
initLinkedList(result.optionStack);
|
||||
initLinkedList(result.libs);
|
||||
append(result.optionStack, newOptionEntry());
|
||||
|
||||
162
nim/semexprs.pas
162
nim/semexprs.pas
@@ -1,6 +1,6 @@
|
||||
//
|
||||
//
|
||||
// The Ethexor Morpork Compiler
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
@@ -110,18 +110,33 @@ begin
|
||||
end;
|
||||
|
||||
function semConv(c: PContext; n: PNode; s: PSym): PNode;
|
||||
var
|
||||
op: PNode;
|
||||
i: int;
|
||||
begin
|
||||
if sonsLen(n) <> 2 then liMessage(n.info, errConvNeedsOneArg);
|
||||
result := newNodeI(nkConv, n.info);
|
||||
result.typ := semTypeNode(c, n.sons[0], nil);
|
||||
addSon(result, copyTree(n.sons[0]));
|
||||
addSon(result, semExprWithType(c, n.sons[1]));
|
||||
checkConvertible(result.info, result.typ, result.sons[1].typ);
|
||||
op := result.sons[1];
|
||||
if op.kind <> nkSymChoice then
|
||||
checkConvertible(result.info, result.typ, op.typ)
|
||||
else begin
|
||||
for i := 0 to sonsLen(op)-1 do begin
|
||||
if sameType(result.typ, op.sons[i].typ) then begin
|
||||
include(op.sons[i].sym.flags, sfUsed);
|
||||
result := op.sons[i]; exit
|
||||
end
|
||||
end;
|
||||
liMessage(n.info, errUseQualifier, op.sons[0].sym.name.s);
|
||||
end
|
||||
end;
|
||||
|
||||
function semCast(c: PContext; n: PNode): PNode;
|
||||
begin
|
||||
if optSafeCode in gGlobalOptions then liMessage(n.info, errCastNotInSafeMode);
|
||||
include(c.p.owner.flags, sfSideEffect);
|
||||
checkSonsLen(n, 2);
|
||||
result := newNodeI(nkCast, n.info);
|
||||
result.typ := semTypeNode(c, n.sons[0], nil);
|
||||
@@ -354,7 +369,7 @@ function isAssignable(n: PNode): bool;
|
||||
begin
|
||||
result := false;
|
||||
case n.kind of
|
||||
nkSym: result := n.sym.kind in [skVar, skTemp];
|
||||
nkSym: result := (n.sym.kind in [skVar, skTemp]);
|
||||
nkDotExpr, nkQualified, nkBracketExpr: begin
|
||||
checkMinSonsLen(n, 1);
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then
|
||||
@@ -373,7 +388,7 @@ begin
|
||||
nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||
result := isAssignable(n.sons[0]);
|
||||
else begin end
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
function newHiddenAddrTaken(c: PContext; n: PNode): PNode;
|
||||
@@ -442,13 +457,31 @@ begin
|
||||
n.sons[i] := analyseIfAddressTaken(c, n.sons[i]);
|
||||
end;
|
||||
|
||||
function semDirectCallAnalyseEffects(c: PContext; n: PNode): PNode;
|
||||
var
|
||||
callee: PSym;
|
||||
begin
|
||||
result := semDirectCall(c, n);
|
||||
if result <> nil then begin
|
||||
if result.sons[0].kind <> nkSym then
|
||||
InternalError('semDirectCallAnalyseEffects');
|
||||
callee := result.sons[0].sym;
|
||||
if not (sfNoSideEffect in callee.flags) then
|
||||
if (sfForward in callee.flags)
|
||||
or ([sfImportc, sfSideEffect] * callee.flags <> []) then
|
||||
include(c.p.owner.flags, sfSideEffect);
|
||||
end
|
||||
end;
|
||||
|
||||
function semIndirectOp(c: PContext; n: PNode): PNode;
|
||||
var
|
||||
m: TCandidate;
|
||||
msg: string;
|
||||
i: int;
|
||||
prc: PNode;
|
||||
begin
|
||||
result := nil;
|
||||
prc := n.sons[0];
|
||||
checkMinSonsLen(n, 1);
|
||||
case n.sons[0].kind of
|
||||
nkDotExpr, nkQualified: begin
|
||||
@@ -457,8 +490,7 @@ begin
|
||||
if n.sons[0].kind = nkDotCall then begin // it is a static call!
|
||||
result := n.sons[0];
|
||||
result.kind := nkCall;
|
||||
for i := 1 to sonsLen(n)-1 do
|
||||
addSon(result, n.sons[i]);
|
||||
for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]);
|
||||
result := semExpr(c, result);
|
||||
exit
|
||||
end
|
||||
@@ -475,8 +507,8 @@ begin
|
||||
if m.state <> csMatch then begin
|
||||
msg := msgKindToString(errTypeMismatch);
|
||||
for i := 1 to sonsLen(n)-1 do begin
|
||||
if i > 1 then add(msg, ', ');
|
||||
add(msg, typeToString(n.sons[i].typ));
|
||||
if i <> sonsLen(n)-1 then add(msg, ', ');
|
||||
end;
|
||||
add(msg, ')' +{&} nl +{&} msgKindToString(errButExpected) +{&}
|
||||
nl +{&} typeToString(n.sons[0].typ));
|
||||
@@ -485,11 +517,21 @@ begin
|
||||
end
|
||||
else
|
||||
result := m.call;
|
||||
// we assume that a procedure that calls something indirectly
|
||||
// has side-effects:
|
||||
include(c.p.owner.flags, sfSideEffect);
|
||||
end
|
||||
else begin
|
||||
result := overloadedCallOpr(c, n);
|
||||
if result = nil then result := semDirectCall(c, n);
|
||||
if result = nil then liMessage(n.info, errExprCannotBeCalled);
|
||||
// Now that nkSym does not imply an iteration over the proc/iterator space,
|
||||
// the old ``prc`` (which is likely an nkIdent) has to be restored:
|
||||
if result = nil then begin
|
||||
n.sons[0] := prc;
|
||||
result := semDirectCallAnalyseEffects(c, n);
|
||||
end;
|
||||
if result = nil then
|
||||
liMessage(n.info, errExprXCannotBeCalled,
|
||||
renderTree(n, {@set}[renderNoComments]));
|
||||
end;
|
||||
fixAbstractType(c, result);
|
||||
analyseIfAddressTakenInCall(c, result);
|
||||
@@ -499,7 +541,7 @@ function semDirectOp(c: PContext; n: PNode): PNode;
|
||||
begin
|
||||
// this seems to be a hotspot in the compiler!
|
||||
semOpAux(c, n);
|
||||
result := semDirectCall(c, n);
|
||||
result := semDirectCallAnalyseEffects(c, n);
|
||||
if result = nil then begin
|
||||
result := overloadedCallOpr(c, n);
|
||||
if result = nil then
|
||||
@@ -508,45 +550,6 @@ begin
|
||||
fixAbstractType(c, result);
|
||||
analyseIfAddressTakenInCall(c, result);
|
||||
end;
|
||||
(*
|
||||
function semIncSucc(c: PContext; n: PNode; const opr: string): PNode;
|
||||
// handles Inc, Dec, Succ and Pred
|
||||
var
|
||||
a: PNode;
|
||||
typ: PType;
|
||||
begin
|
||||
checkMinSonsLen(n, 2);
|
||||
n.sons[1] := semExprWithType(c, n.sons[1]);
|
||||
typ := skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar]);
|
||||
if not isOrdinalType(typ) or enumHasWholes(typ) then
|
||||
liMessage(n.sons[1].Info, errOrdinalTypeExpected);
|
||||
if sonsLen(n) = 3 then begin
|
||||
n.sons[2] := semExprWithType(c, n.sons[2]);
|
||||
a := IndexTypesMatch(c, getSysType(tyInt), n.sons[2].typ, n.sons[2]);
|
||||
if a = nil then
|
||||
typeMismatch(n.sons[2], getSysType(tyInt), n.sons[2].typ);
|
||||
n.sons[2] := a;
|
||||
end
|
||||
else if sonsLen(n) = 2 then begin // default value of 1
|
||||
a := newIntNode(nkIntLit, 1);
|
||||
a.info := n.info;
|
||||
a.typ := getSysType(tyInt);
|
||||
addSon(n, a)
|
||||
end
|
||||
else
|
||||
liMessage(n.info, errInvalidArgForX, opr);
|
||||
result := n;
|
||||
end;
|
||||
|
||||
function semOrd(c: PContext; n: PNode): PNode;
|
||||
begin
|
||||
checkSonsLen(n, 2);
|
||||
n.sons[1] := semExprWithType(c, n.sons[1]);
|
||||
if not isOrdinalType(skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar])) then
|
||||
liMessage(n.Info, errOrdinalTypeExpected);
|
||||
n.typ := getSysType(tyInt);
|
||||
result := n
|
||||
end; *)
|
||||
|
||||
function semEcho(c: PContext; n: PNode): PNode;
|
||||
var
|
||||
@@ -632,18 +635,6 @@ begin
|
||||
mSizeOf: result := semSizeof(c, setMs(n, s));
|
||||
mIs: result := semIs(c, setMs(n, s));
|
||||
mEcho: result := semEcho(c, setMs(n, s));
|
||||
(*
|
||||
mSucc: begin
|
||||
result := semIncSucc(c, setMs(n, s), 'succ');
|
||||
result.typ := n.sons[1].typ;
|
||||
end;
|
||||
mPred: begin
|
||||
result := semIncSucc(c, setMs(n, s), 'pred');
|
||||
result.typ := n.sons[1].typ;
|
||||
end;
|
||||
mInc: result := semIncSucc(c, setMs(n, s), 'inc');
|
||||
ast.mDec: result := semIncSucc(c, setMs(n, s), 'dec');
|
||||
mOrd: result := semOrd(c, setMs(n, s)); *)
|
||||
else result := semDirectOp(c, n);
|
||||
end;
|
||||
end;
|
||||
@@ -655,16 +646,14 @@ end;
|
||||
|
||||
function semSym(c: PContext; n: PNode; s: PSym; flags: TExprFlags): PNode;
|
||||
begin
|
||||
result := newSymNode(s);
|
||||
result.info := n.info;
|
||||
result.typ := s.typ;
|
||||
include(s.flags, sfUsed);
|
||||
if (s.kind = skType) and not (efAllowType in flags) then
|
||||
liMessage(n.info, errATypeHasNoValue);
|
||||
case s.kind of
|
||||
skProc, skIterator, skConverter:
|
||||
skProc, skIterator, skConverter: begin
|
||||
if (s.magic <> mNone) then
|
||||
liMessage(n.info, errInvalidContextForBuiltinX, s.name.s);
|
||||
result := symChoice(c, n, s);
|
||||
end;
|
||||
skConst: begin
|
||||
(*
|
||||
Consider::
|
||||
@@ -678,20 +667,40 @@ begin
|
||||
copy `x`'s AST into each context, so that the type fixup phase can
|
||||
deal with two different ``[]``.
|
||||
*)
|
||||
include(s.flags, sfUsed);
|
||||
if s.typ.kind in ConstAbstractTypes then begin
|
||||
result := copyTree(s.ast);
|
||||
result.info := n.info;
|
||||
result.typ := s.typ;
|
||||
end
|
||||
else begin
|
||||
result := newSymNode(s);
|
||||
result.info := n.info;
|
||||
end
|
||||
end;
|
||||
skMacro: begin
|
||||
include(s.flags, sfUsed);
|
||||
result := semMacroExpr(c, n, s);
|
||||
end;
|
||||
skMacro: result := semMacroExpr(c, n, s);
|
||||
skTemplate: begin
|
||||
include(s.flags, sfUsed);
|
||||
// Templates and macros can be invoked without ``()``
|
||||
pushInfoContext(n.info);
|
||||
result := evalTemplate(c, n, s);
|
||||
popInfoContext();
|
||||
end;
|
||||
else begin end
|
||||
skVar: begin
|
||||
include(s.flags, sfUsed);
|
||||
// if a proc accesses a global variable, it is not side effect free
|
||||
if sfGlobal in s.flags then include(c.p.owner.flags, sfSideEffect);
|
||||
result := newSymNode(s);
|
||||
result.info := n.info;
|
||||
end;
|
||||
else begin
|
||||
include(s.flags, sfUsed);
|
||||
result := newSymNode(s);
|
||||
result.info := n.info;
|
||||
end
|
||||
end;
|
||||
checkDeprecated(n, s);
|
||||
end;
|
||||
@@ -1266,6 +1275,7 @@ begin
|
||||
result := semExpr(c, result, flags)
|
||||
end;
|
||||
end;
|
||||
nkBind: result := semExpr(c, n.sons[0], flags);
|
||||
nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand: begin
|
||||
// check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1);
|
||||
@@ -1326,11 +1336,7 @@ begin
|
||||
end;
|
||||
nkCurly: result := semSetConstr(c, n);
|
||||
nkBracket: result := semArrayConstr(c, n);
|
||||
nkLambda: result := semLambda(c, n); // handled in semstmts
|
||||
nkExprColonExpr: begin
|
||||
internalError(n.info, 'semExpr() to implement');
|
||||
// XXX: to implement for array constructors!
|
||||
end;
|
||||
nkLambda: result := semLambda(c, n);
|
||||
nkDerefExpr: begin
|
||||
checkSonsLen(n, 1);
|
||||
n.sons[0] := semExprWithType(c, n.sons[0]);
|
||||
@@ -1357,11 +1363,6 @@ begin
|
||||
checkSonsLen(n, 1);
|
||||
result := semExpr(c, n.sons[0]);
|
||||
end;
|
||||
nkHeaderQuoted: begin
|
||||
// look up the proc:
|
||||
internalError(n.info, 'semExpr() to implement');
|
||||
// XXX: to implement
|
||||
end;
|
||||
nkIfExpr: result := semIfExpr(c, n);
|
||||
nkStmtListExpr: result := semStmtListExpr(c, n);
|
||||
nkBlockExpr: result := semBlockExpr(c, n);
|
||||
@@ -1374,6 +1375,11 @@ begin
|
||||
checkSonsLen(n, 3);
|
||||
nkCheckedFieldExpr:
|
||||
checkMinSonsLen(n, 2);
|
||||
nkSymChoice: begin
|
||||
liMessage(n.info, errExprXAmbiguous,
|
||||
renderTree(n, {@set}[renderNoComments]));
|
||||
result := nil
|
||||
end
|
||||
else begin
|
||||
//InternalError(n.info, nodeKindToStr[n.kind]);
|
||||
liMessage(n.info, errInvalidExpressionX,
|
||||
|
||||
@@ -257,7 +257,7 @@ begin
|
||||
addSon(result, newIdentNode(getIdent(id.s+'='), n.info));
|
||||
addSon(result, semExpr(c, a.sons[0]));
|
||||
addSon(result, semExpr(c, n.sons[1]));
|
||||
result := semDirectCall(c, result);
|
||||
result := semDirectCallAnalyseEffects(c, result);
|
||||
if result <> nil then begin
|
||||
fixAbstractType(c, result);
|
||||
analyseIfAddressTakenInCall(c, result);
|
||||
@@ -277,7 +277,7 @@ begin
|
||||
addSonIfNotNil(result, semExpr(c, a.sons[1].sons[0]));
|
||||
addSonIfNotNil(result, semExpr(c, a.sons[1].sons[1]));
|
||||
addSon(result, semExpr(c, n.sons[1]));
|
||||
result := semDirectCall(c, result);
|
||||
result := semDirectCallAnalyseEffects(c, result);
|
||||
if result <> nil then begin
|
||||
fixAbstractType(c, result);
|
||||
analyseIfAddressTakenInCall(c, result);
|
||||
@@ -289,7 +289,7 @@ begin
|
||||
addSon(result, semExpr(c, a.sons[0]));
|
||||
addSon(result, semExpr(c, a.sons[1]));
|
||||
addSon(result, semExpr(c, n.sons[1]));
|
||||
result := semDirectCall(c, result);
|
||||
result := semDirectCallAnalyseEffects(c, result);
|
||||
if result <> nil then begin
|
||||
fixAbstractType(c, result);
|
||||
analyseIfAddressTakenInCall(c, result);
|
||||
@@ -322,7 +322,7 @@ begin
|
||||
result := n;
|
||||
checkSonsLen(n, 1);
|
||||
if not (c.p.owner.kind in [skConverter, skProc, skMacro]) then
|
||||
liMessage(n.info, errReturnNotAllowedHere);
|
||||
liMessage(n.info, errXNotAllowedHere, '''return''');
|
||||
if (n.sons[0] <> nil) then begin
|
||||
n.sons[0] := SemExprWithType(c, n.sons[0]);
|
||||
// check for type compatibility:
|
||||
@@ -624,9 +624,28 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function resolveGenericParams(c: PContext; n: PNode): PNode;
|
||||
function resolveGenericParams(c: PContext; n: PNode;
|
||||
withinBind: bool = false): PNode;
|
||||
var
|
||||
i: int;
|
||||
s: PSym;
|
||||
begin
|
||||
result := n;
|
||||
if n = nil then begin result := nil; exit end;
|
||||
case n.kind of
|
||||
nkIdent: begin
|
||||
if not withinBind then
|
||||
result := n
|
||||
else
|
||||
result := symChoice(c, n, lookup(c, n))
|
||||
end;
|
||||
nkSym..nkNilLit: result := n;
|
||||
nkBind: result := resolveGenericParams(c, n.sons[0], true);
|
||||
else begin
|
||||
result := n;
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
result.sons[i] := resolveGenericParams(c, n.sons[i], withinBind);
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function SemTypeSection(c: PContext; n: PNode): PNode;
|
||||
@@ -682,7 +701,7 @@ begin
|
||||
addSon(s.typ, nil);
|
||||
// process the type body for symbol lookup of generic params
|
||||
// we can use the same algorithm as for template parameters:
|
||||
a.sons[2] := resolveTemplateParams(c, a.sons[2]);
|
||||
a.sons[2] := resolveTemplateParams(c, a.sons[2], false);
|
||||
s.ast := a;
|
||||
if s.typ.containerID <> 0 then
|
||||
InternalError(a.info, 'semTypeSection: containerID');
|
||||
@@ -754,6 +773,13 @@ begin
|
||||
n.sons[codePos] := newSymNode(b);
|
||||
end;
|
||||
|
||||
procedure sideEffectsCheck(c: PContext; s: PSym);
|
||||
begin
|
||||
if [sfNoSideEffect, sfSideEffect] * s.flags =
|
||||
[sfNoSideEffect, sfSideEffect] then
|
||||
liMessage(s.info, errXhasSideEffects, s.name.s);
|
||||
end;
|
||||
|
||||
function semIterator(c: PContext; n: PNode): PNode;
|
||||
var
|
||||
s: PSym;
|
||||
@@ -972,6 +998,7 @@ begin
|
||||
else if sfBorrow in s.flags then
|
||||
semBorrow(c, n, s);
|
||||
end;
|
||||
sideEffectsCheck(c, s);
|
||||
closeScope(c.tab); // close scope for parameters
|
||||
popOwner();
|
||||
c.p := oldP; // restore
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
//
|
||||
// The Nimrod Compiler
|
||||
// (c) Copyright 2008 Andreas Rumpf
|
||||
// (c) Copyright 2009 Andreas Rumpf
|
||||
//
|
||||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
@@ -90,7 +90,37 @@ begin
|
||||
dec(evalTemplateCounter);
|
||||
end;
|
||||
|
||||
function resolveTemplateParams(c: PContext; n: PNode): PNode;
|
||||
function symChoice(c: PContext; n: PNode; s: PSym): PNode;
|
||||
var
|
||||
a: PSym;
|
||||
o: TOverloadIter;
|
||||
i: int;
|
||||
begin
|
||||
i := 0;
|
||||
a := initOverloadIter(o, c, n);
|
||||
while a <> nil do begin
|
||||
a := nextOverloadIter(o, c, n);
|
||||
inc(i);
|
||||
end;
|
||||
if i <= 1 then begin
|
||||
result := newSymNode(s);
|
||||
result.info := n.info;
|
||||
include(s.flags, sfUsed);
|
||||
end
|
||||
else begin
|
||||
// semantic checking requires a type; ``fitNode`` deal with it
|
||||
// appropriately
|
||||
result := newNodeIT(nkSymChoice, n.info, newTypeS(tyNone, c));
|
||||
a := initOverloadIter(o, c, n);
|
||||
while a <> nil do begin
|
||||
addSon(result, newSymNode(a));
|
||||
a := nextOverloadIter(o, c, n);
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function resolveTemplateParams(c: PContext; n: PNode;
|
||||
withinBind: bool): PNode;
|
||||
var
|
||||
i: int;
|
||||
s: PSym;
|
||||
@@ -98,20 +128,27 @@ begin
|
||||
if n = nil then begin result := nil; exit end;
|
||||
case n.kind of
|
||||
nkIdent: begin
|
||||
s := SymTabLocalGet(c.Tab, n.ident);
|
||||
if (s <> nil) then begin
|
||||
result := newSymNode(s);
|
||||
result.info := n.info
|
||||
if not withinBind then begin
|
||||
s := SymTabLocalGet(c.Tab, n.ident);
|
||||
if (s <> nil) then begin
|
||||
result := newSymNode(s);
|
||||
result.info := n.info
|
||||
end
|
||||
else
|
||||
result := n
|
||||
end
|
||||
else begin
|
||||
result := symChoice(c, n, lookup(c, n))
|
||||
end
|
||||
else
|
||||
result := n
|
||||
end;
|
||||
nkSym..nkNilLit: // atom
|
||||
result := n;
|
||||
nkBind:
|
||||
result := resolveTemplateParams(c, n.sons[0], true);
|
||||
else begin
|
||||
result := n;
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
result.sons[i] := resolveTemplateParams(c, n.sons[i]);
|
||||
result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind);
|
||||
end
|
||||
end
|
||||
end;
|
||||
@@ -200,7 +237,7 @@ begin
|
||||
if n.sons[genericParamsPos] <> nil then
|
||||
liMessage(n.info, errNoGenericParamsAllowedForX, 'template');
|
||||
// resolve parameters:
|
||||
n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos]);
|
||||
n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false);
|
||||
if params.sons[0].ident.id = ord(wExpr) then
|
||||
n.sons[codePos] := transformToExpr(n.sons[codePos]);
|
||||
|
||||
|
||||
@@ -46,6 +46,21 @@ begin
|
||||
assert(c.callee <> nil);
|
||||
end;
|
||||
|
||||
procedure copyCandidate(var a: TCandidate; const b: TCandidate);
|
||||
begin
|
||||
a.exactMatches := b.exactMatches;
|
||||
a.subtypeMatches := b.subtypeMatches;
|
||||
a.convMatches := b.convMatches;
|
||||
a.intConvMatches := b.intConvMatches;
|
||||
a.genericMatches := b.genericMatches;
|
||||
a.state := b.state;
|
||||
a.callee := b.callee;
|
||||
a.calleeSym := b.calleeSym;
|
||||
a.call := copyTree(b.call);
|
||||
a.baseTypeMatch := b.baseTypeMatch;
|
||||
copyIdTable(a.bindings, b.bindings);
|
||||
end;
|
||||
|
||||
function cmpCandidates(const a, b: TCandidate): int;
|
||||
begin
|
||||
result := a.exactMatches - b.exactMatches;
|
||||
@@ -552,8 +567,8 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function ParamTypesMatch(c: PContext; var m: TCandidate; f, a: PType;
|
||||
arg: PNode): PNode;
|
||||
function ParamTypesMatchAux(c: PContext; var m: TCandidate; f, a: PType;
|
||||
arg: PNode): PNode;
|
||||
var
|
||||
r: TTypeRelation;
|
||||
begin
|
||||
@@ -608,6 +623,57 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function ParamTypesMatch(c: PContext; var m: TCandidate; f, a: PType;
|
||||
arg: PNode): PNode;
|
||||
var
|
||||
i, cmp, best: int;
|
||||
x, y, z: TCandidate;
|
||||
r: TTypeRelation;
|
||||
begin
|
||||
if (arg = nil) or (arg.kind <> nkSymChoice) then
|
||||
result := ParamTypesMatchAux(c, m, f, a, arg)
|
||||
else begin
|
||||
// CAUTION: The order depends on the used hashing scheme. Thus it is
|
||||
// incorrect to simply use the first fitting match. However, to implement
|
||||
// this correctly is inefficient. We have to copy `m` here to be able to
|
||||
// roll back the side effects of the unification algorithm.
|
||||
initCandidate(x, m.callee);
|
||||
initCandidate(y, m.callee);
|
||||
initCandidate(z, m.callee);
|
||||
x.calleeSym := m.calleeSym;
|
||||
y.calleeSym := m.calleeSym;
|
||||
z.calleeSym := m.calleeSym;
|
||||
best := -1;
|
||||
for i := 0 to sonsLen(arg)-1 do begin
|
||||
copyCandidate(z, m);
|
||||
r := typeRel(z.bindings, f, arg.sons[i].typ);
|
||||
if r <> isNone then begin
|
||||
case x.state of
|
||||
csEmpty, csNoMatch: begin x := z; best := i; x.state := csMatch; end;
|
||||
csMatch: begin
|
||||
cmp := cmpCandidates(x, z);
|
||||
if cmp < 0 then begin best := i; x := z end // z is better than x
|
||||
else if cmp = 0 then y := z // z is as good as x
|
||||
else begin end // z is worse than x
|
||||
end
|
||||
end
|
||||
end
|
||||
end;
|
||||
if x.state = csEmpty then
|
||||
result := nil
|
||||
else if (y.state = csMatch) and (cmpCandidates(x, y) = 0) then begin
|
||||
if x.state <> csMatch then InternalError(arg.info, 'x.state is not csMatch');
|
||||
// ambiguous: more than one symbol fits
|
||||
result := nil
|
||||
end
|
||||
else begin
|
||||
// only one valid interpretation found:
|
||||
include(arg.sons[best].sym.flags, sfUsed);
|
||||
result := ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best]);
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function IndexTypesMatch(c: PContext; f, a: PType; arg: PNode): PNode;
|
||||
var
|
||||
m: TCandidate;
|
||||
@@ -796,7 +862,7 @@ begin
|
||||
//writeMatches(x);
|
||||
//writeMatches(y);
|
||||
liMessage(n.Info, errGenerated,
|
||||
format(msgKindToString(errAmbigiousCallXYZ),
|
||||
format(msgKindToString(errAmbiguousCallXYZ),
|
||||
[getProcHeader(x.calleeSym),
|
||||
getProcHeader(y.calleeSym), x.calleeSym.Name.s]))
|
||||
end
|
||||
|
||||
@@ -502,18 +502,25 @@ procedure addf(var result: string; const f: string; args: array of string);
|
||||
const
|
||||
PatternChars = ['a'..'z', 'A'..'Z', '0'..'9', '_', #128..#255];
|
||||
var
|
||||
i, j, x: int;
|
||||
i, j, x, num: int;
|
||||
begin
|
||||
i := 1;
|
||||
num := 0;
|
||||
while i <= length(f) do
|
||||
if f[i] = '$' then begin
|
||||
case f[i+1] of
|
||||
'#': begin
|
||||
inc(i, 2);
|
||||
add(result, args[num]);
|
||||
inc(num);
|
||||
end;
|
||||
'$': begin
|
||||
addChar(result, '$');
|
||||
inc(i, 2);
|
||||
end;
|
||||
'1'..'9': begin
|
||||
add(result, args[ord(f[i+1]) - ord('0') - 1]);
|
||||
num := ord(f[i+1]) - ord('0');
|
||||
add(result, args[num - 1]);
|
||||
inc(i, 2);
|
||||
end;
|
||||
'{': begin
|
||||
|
||||
@@ -15,6 +15,7 @@ unit transf;
|
||||
// * inlines constants
|
||||
// * performes contant folding
|
||||
// * introduces nkHiddenDeref, nkHiddenSubConv, etc.
|
||||
// * aggressive compile-time evaluation based on the side-effect analysis
|
||||
|
||||
interface
|
||||
|
||||
@@ -22,7 +23,7 @@ interface
|
||||
|
||||
uses
|
||||
sysutils, nsystem, charsets, strutils,
|
||||
lists, options, ast, astalgo, trees, treetab,
|
||||
lists, options, ast, astalgo, trees, treetab, evals,
|
||||
msgs, nos, idents, rnimsyn, types, passes, semfold, magicsys;
|
||||
|
||||
const
|
||||
@@ -822,7 +823,24 @@ begin
|
||||
end;
|
||||
if sonsLen(result) = 2 then
|
||||
result := result.sons[1];
|
||||
end;
|
||||
end
|
||||
(*
|
||||
else if result.sons[0].kind = nkSym then begin
|
||||
// optimization still too aggressive
|
||||
op := result.sons[0].sym;
|
||||
if (op.magic = mNone) and (op.kind = skProc)
|
||||
and ([sfSideEffect, sfForward, sfNoReturn, sfImportc] * op.flags = [])
|
||||
then begin
|
||||
for i := 1 to sonsLen(result)-1 do
|
||||
if not isConstExpr(result.sons[i]) then exit;
|
||||
// compile-time evaluation:
|
||||
a := evalConstExpr(c.module, result);
|
||||
if (a <> nil) and (a.kind <> nkEmpty) then begin
|
||||
messageout('evaluated at compile time: ' + rendertree(result));
|
||||
result := a
|
||||
end
|
||||
end
|
||||
end *)
|
||||
end;
|
||||
|
||||
function transform(c: PTransf; n: PNode): PNode;
|
||||
|
||||
@@ -65,16 +65,6 @@ function equalParams(a, b: PNode): TParamsEquality;
|
||||
function isOrdinalType(t: PType): Boolean;
|
||||
function enumHasWholes(t: PType): Boolean;
|
||||
|
||||
(*
|
||||
function skipRange(t: PType): PType;
|
||||
function skipGeneric(t: PType): PType;
|
||||
function skipGenericRange(t: PType): PType;
|
||||
function skipVar(t: PType): PType;
|
||||
function skipVarGeneric(t: PType): PType;
|
||||
function skipVarGenericRange(t: PType): PType;
|
||||
function skipPtrsGeneric(t: PType): PType;
|
||||
*)
|
||||
|
||||
const
|
||||
abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyAbstract, tyOrdinal];
|
||||
abstractVar = {@set}[tyVar, tyGenericInst, tyAbstract, tyOrdinal];
|
||||
|
||||
@@ -40,10 +40,10 @@ type
|
||||
//cog.out(idents)
|
||||
//]]]
|
||||
wAbstract, wAddr, wAnd, wAs,
|
||||
wAsm, wBlock, wBreak, wCase,
|
||||
wCast, wConst, wContinue, wConverter,
|
||||
wDiscard, wDiv, wElif, wElse,
|
||||
wEnd, wEnum, wExcept, wException,
|
||||
wAsm, wBind, wBlock, wBreak,
|
||||
wCase, wCast, wConst, wContinue,
|
||||
wConverter, wDiscard, wDiv, wElif,
|
||||
wElse, wEnd, wEnum, wExcept,
|
||||
wFinally, wFor, wFrom, wGeneric,
|
||||
wIf, wImplies, wImport, wIn,
|
||||
wInclude, wIs, wIsnot, wIterator,
|
||||
@@ -62,7 +62,7 @@ type
|
||||
// pragmas and command line options:
|
||||
wMagic, wTypeCheck, wFinal, wProfiler,
|
||||
wObjChecks, wImportc, wExportc, wAlign, wNodecl, wPure,
|
||||
wVolatile, wRegister, wNostatic, wHeader, wNosideeffect, wNoreturn,
|
||||
wVolatile, wRegister, wSideeffect, wHeader, wNosideeffect, wNoreturn,
|
||||
wMerge, wLib, wDynlib, wCompilerproc, wCppmethod, wFatal,
|
||||
wError, wWarning, wHint, wLine, wPush, wPop,
|
||||
wDefine, wUndef, wLinedir, wStacktrace, wLinetrace, wPragma,
|
||||
@@ -114,10 +114,10 @@ const
|
||||
//cog.out(strings)
|
||||
//]]]
|
||||
'abstract', 'addr', 'and', 'as',
|
||||
'asm', 'block', 'break', 'case',
|
||||
'cast', 'const', 'continue', 'converter',
|
||||
'discard', 'div', 'elif', 'else',
|
||||
'end', 'enum', 'except', 'exception',
|
||||
'asm', 'bind', 'block', 'break',
|
||||
'case', 'cast', 'const', 'continue',
|
||||
'converter', 'discard', 'div', 'elif',
|
||||
'else', 'end', 'enum', 'except',
|
||||
'finally', 'for', 'from', 'generic',
|
||||
'if', 'implies', 'import', 'in',
|
||||
'include', 'is', 'isnot', 'iterator',
|
||||
@@ -136,7 +136,7 @@ const
|
||||
// pragmas and command line options:
|
||||
'magic', 'typecheck', 'final', 'profiler',
|
||||
'objchecks', 'importc', 'exportc', 'align', 'nodecl', 'pure',
|
||||
'volatile', 'register', 'nostatic', 'header', 'nosideeffect', 'noreturn',
|
||||
'volatile', 'register', 'sideeffect', 'header', 'nosideeffect', 'noreturn',
|
||||
'merge', 'lib', 'dynlib', 'compilerproc', 'cppmethod', 'fatal',
|
||||
'error', 'warning', 'hint', 'line', 'push', 'pop',
|
||||
'define', 'undef', 'linedir', 'stacktrace', 'linetrace', 'pragma',
|
||||
|
||||
10
pycompab.py
10
pycompab.py
@@ -68,11 +68,16 @@ def Subs(frmt, *args, **substitution):
|
||||
a = args
|
||||
result = []
|
||||
i = 0
|
||||
num = 0
|
||||
L = len(frmt)
|
||||
while i < L:
|
||||
if frmt[i] == '$':
|
||||
i = i+1
|
||||
if frmt[i] == '$':
|
||||
if frmt[i] == '#':
|
||||
result.append(a[num])
|
||||
num = num+1
|
||||
i = i+1
|
||||
elif frmt[i] == '$':
|
||||
result.append('$')
|
||||
i = i+1
|
||||
elif frmt[i] == '{':
|
||||
@@ -91,7 +96,8 @@ def Subs(frmt, *args, **substitution):
|
||||
while i < len(frmt) and frmt[i] in chars: i = i + 1
|
||||
x = frmt[j:i]
|
||||
if x[0] in DIGITS:
|
||||
result.append(str(a[int(x)-1]))
|
||||
num = int(x)
|
||||
result.append(str(a[num-1]))
|
||||
else:
|
||||
result.append(str(d[x]))
|
||||
else:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Test ambigious symbols
|
||||
# Test ambiguous symbols
|
||||
|
||||
import mambsym1, mambsym2
|
||||
|
||||
var
|
||||
v: TExport #ERROR_MSG ambigious identifier
|
||||
v: TExport #ERROR_MSG ambiguous identifier
|
||||
|
||||
v = y
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Test ambigious symbols
|
||||
# Test ambiguous symbols
|
||||
|
||||
import mambsym1, times
|
||||
|
||||
var
|
||||
v = mDec #ERROR_MSG ambigious identifier
|
||||
v = mDec #ERROR_MSG ambiguous identifier
|
||||
|
||||
writeln(stdout, ord(v))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Test ambigious symbols
|
||||
# Test ambiguous symbols
|
||||
|
||||
import mambsys1, mambsys2
|
||||
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
# Test the closure implementation
|
||||
|
||||
proc map(n: var openarray[int], fn: proc (x: int): int {.closure}) =
|
||||
for i in 0..n.len-1:
|
||||
n[i] = fn(n[i])
|
||||
for i in 0..n.len-1: n[i] = fn(n[i])
|
||||
|
||||
proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int =
|
||||
result = 0
|
||||
for i in 0..n.len-1:
|
||||
result = fn(result, n[i])
|
||||
|
||||
var
|
||||
myData: array[0..9, int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
myData: array[0..4, int] = [0, 1, 2, 3, 4]
|
||||
|
||||
proc testA() =
|
||||
var p = 0
|
||||
map(myData, lambda (x: int): int =
|
||||
result = x + 1 shl (lambda (y: int): int =
|
||||
return y + 1
|
||||
return y + p
|
||||
)(0)
|
||||
inc(p), 88)
|
||||
inc(p))
|
||||
|
||||
testA()
|
||||
for x in items(myData):
|
||||
echo x
|
||||
write(stout, x)
|
||||
#OUT 2 4 6 8 10
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import
|
||||
unicode, cgi, terminal, libcurl, web,
|
||||
parsexml, parseopt, parsecfg,
|
||||
osproc, zipfiles,
|
||||
osproc,
|
||||
sdl, smpeg, sdl_gfx, sdl_net, sdl_mixer, sdl_ttf,
|
||||
sdl_image, sdl_mixer_nosmpeg,
|
||||
cursorfont, xatom, xf86vmode, xkb, xrandr, xshm, xvlib, keysym, xcms, xi,
|
||||
@@ -12,6 +12,10 @@ import
|
||||
cairowin32, cairoxlib,
|
||||
odbcsql,
|
||||
gl, glut, glu, glx, glext, wingl,
|
||||
zlib, lua, lualib, lauxlib, mysql, sqlite3, python, tcl
|
||||
lua, lualib, lauxlib, mysql, sqlite3, python, tcl
|
||||
|
||||
when defined(linux):
|
||||
import
|
||||
zlib, zipfiles
|
||||
|
||||
writeln(stdout, "test compilation of binding modules")
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
var
|
||||
a: int
|
||||
|
||||
a() #ERROR_MSG expression cannot be called
|
||||
a() #ERROR_MSG expression 'a()' cannot be called
|
||||
|
||||
@@ -281,9 +281,9 @@ proc buildDir(os, cpu: int): string =
|
||||
|
||||
proc writeFile(filename, content: string) =
|
||||
var f: TFile
|
||||
if openFile(f, filename, fmWrite):
|
||||
if open(f, filename, fmWrite):
|
||||
writeln(f, content)
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
quit("Cannot open for writing: " & filename)
|
||||
|
||||
@@ -296,8 +296,8 @@ proc srcdist(c: var TConfigData) =
|
||||
createDir(dir)
|
||||
var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " &
|
||||
"--gen_mapping " &
|
||||
" --os:$2 --cpu:$3 $1 $4") %
|
||||
[c.nimrodArgs, c.oses[osA-1], c.cpus[cpuA-1],
|
||||
" --os:$# --cpu:$# $# $#") %
|
||||
[c.oses[osA-1], c.cpus[cpuA-1], c.nimrodArgs,
|
||||
changeFileExt(c.infile, "nim")]
|
||||
echo("Executing: " & cmd)
|
||||
if executeShellCommand(cmd) != 0:
|
||||
@@ -327,14 +327,13 @@ proc srcdist(c: var TConfigData) =
|
||||
# --------------------- generate inno setup -----------------------------------
|
||||
proc setupDist(c: var TConfigData) =
|
||||
var scrpt = GenerateInnoSetup(c)
|
||||
var n = "build" / "install_$1_$2.iss" % [toLower(c.name), c.version]
|
||||
var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
|
||||
writeFile(n, scrpt)
|
||||
when defined(windows):
|
||||
if c.innoSetup.path.len == 0:
|
||||
c.innoSetup.path = "iscc.exe"
|
||||
var outcmd = if c.outdir.len == 0: "build" else: c.outdir
|
||||
var cmd = "$1 $2 /O$3 $4" % [c.innoSetup.path, c.innoSetup.flags,
|
||||
outcmd, n]
|
||||
var cmd = "$# $# /O$# $#" % [c.innoSetup.path, c.innoSetup.flags, outcmd, n]
|
||||
Echo("Executing: " & cmd)
|
||||
if executeShellCommand(cmd) == 0:
|
||||
removeFile(n)
|
||||
@@ -350,7 +349,7 @@ when haveZipLib:
|
||||
writeFile(deinstallShFile, GenerateDeinstallScript(c))
|
||||
|
||||
var proj = toLower(c.name)
|
||||
var n = "$1_$2.zip" % [proj, c.version]
|
||||
var n = "$#_$#.zip" % [proj, c.version]
|
||||
if c.outdir.len == 0: n = "build" / n
|
||||
else: n = c.outdir / n
|
||||
var z: TZipArchive
|
||||
|
||||
@@ -156,11 +156,11 @@ proc Exec(cmd: string) =
|
||||
proc buildDoc(c: var TConfigData, destPath: string) =
|
||||
# call nim for the documentation:
|
||||
for d in items(c.doc):
|
||||
Exec("nimrod rst2html $1 -o:$2 --index=$3/theindex $4" %
|
||||
Exec("nimrod rst2html $# -o:$# --index=$#/theindex $#" %
|
||||
[c.nimrodArgs, destPath / changeFileExt(extractFileTrunk(d), "html"),
|
||||
destpath, d])
|
||||
for d in items(c.srcdoc):
|
||||
Exec("nimrod doc $1 -o:$2 --index=$3/theindex $4" %
|
||||
Exec("nimrod doc $# -o:$# --index=$#/theindex $#" %
|
||||
[c.nimrodArgs, destPath / changeFileExt(extractFileTrunk(d), "html"),
|
||||
destpath, d])
|
||||
Exec("nimrod rst2html $1 -o:$2/theindex.html $2/theindex" %
|
||||
@@ -169,7 +169,7 @@ proc buildDoc(c: var TConfigData, destPath: string) =
|
||||
proc buildAddDoc(c: var TConfigData, destPath: string) =
|
||||
# build additional documentation (without the index):
|
||||
for d in items(c.webdoc):
|
||||
Exec("nimrod doc $1 -o:$2 $3" %
|
||||
Exec("nimrod doc $# -o:$# $#" %
|
||||
[c.nimrodArgs, destPath / changeFileExt(extractFileTrunk(d), "html"), d])
|
||||
|
||||
proc main(c: var TConfigData) =
|
||||
@@ -188,10 +188,10 @@ proc main(c: var TConfigData) =
|
||||
var content = readFile(temp)
|
||||
if isNil(content): quit("[Error] cannot open: " & temp)
|
||||
var f: TFile
|
||||
var outfile = "web/upload/$1.html" % file
|
||||
if openFile(f, outfile, fmWrite):
|
||||
var outfile = "web/upload/$#.html" % file
|
||||
if open(f, outfile, fmWrite):
|
||||
writeln(f, generateHTMLPage(c, file, content))
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
quit("[Error] cannot write file: " & outfile)
|
||||
removeFile(temp)
|
||||
|
||||
Reference in New Issue
Block a user