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