floating point checks

This commit is contained in:
Andreas Rumpf
2009-12-14 01:38:05 +01:00
parent 911c1cb301
commit 3b7ef2288f
30 changed files with 611 additions and 631 deletions

View File

@@ -1,99 +1,99 @@
# Configuration file for the Nimrod Compiler.
# (c) 2009 Andreas Rumpf
# Feel free to edit the default values as you need.
# You may set environment variables with
# @putenv "key" "val"
# Environment variables cannot be used in the options, however!
cc = gcc
# Configuration file for the Nimrod Compiler.
# (c) 2009 Andreas Rumpf
# Feel free to edit the default values as you need.
# You may set environment variables with
# @putenv "key" "val"
# Environment variables cannot be used in the options, however!
cc = gcc
@if nim:
# use the old fixed library for bootstrapping with Nim:
lib = "nimlib"
@end
path="$lib/pure"
path="$lib/impure"
path="$lib/wrappers"
path="$lib/wrappers/cairo"
path="$lib/wrappers/gtk"
path="$lib/wrappers/lua"
path="$lib/wrappers/opengl"
path="$lib/wrappers/pcre"
path="$lib/wrappers/sdl"
path="$lib/wrappers/x11"
path="$lib/wrappers/zip"
path="$lib/windows"
path="$lib/posix"
path="$lib/ecmas"
@if release or quick:
obj_checks:off
field_checks:off
range_checks:off
bound_checks:off
overflow_checks:off
assertions:off
stacktrace:off
debugger:off
line_dir:off
dead_code_elim:on
@end
@if release:
opt:speed
@end
# additional options always passed to the compiler:
--verbosity: "1"
path="$lib/pure"
path="$lib/impure"
path="$lib/wrappers"
path="$lib/wrappers/cairo"
path="$lib/wrappers/gtk"
path="$lib/wrappers/lua"
path="$lib/wrappers/opengl"
path="$lib/wrappers/pcre"
path="$lib/wrappers/sdl"
path="$lib/wrappers/x11"
path="$lib/wrappers/zip"
path="$lib/windows"
path="$lib/posix"
path="$lib/ecmas"
@if release or quick:
obj_checks:off
field_checks:off
range_checks:off
bound_checks:off
overflow_checks:off
assertions:off
stacktrace:off
debugger:off
line_dir:off
dead_code_elim:on
@end
@if release:
opt:speed
@end
# additional options always passed to the compiler:
--verbosity: "1"
--parallel_build: "0" # 0 to auto-detect number of processors
hint[LineTooLong]=off
#hint[XDeclaredButNotUsed]=off
@if unix:
@if not bsd:
gcc.options.linker = "-ldl"
@end
@end
# Configuration for the Intel C/C++ compiler:
icc.options.always = "-cxxlib"
icc.options.linker = "-cxxlib"
# Configuration for the GNU C/C++ compiler:
@if windows:
gcc.path = r"$nimrod\dist\mingw\bin"
@end
gcc.options.debug = "-g"
@if macosx:
gcc.options.always = "-w -fasm-blocks"
@else:
gcc.options.always = "-w"
@end
gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os"
#passl = "-pg"
# Configuration for the LLVM GCC compiler:
llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O2"
llvm_gcc.options.size = "-Os"
# Configuration for the Visual C/C++ compiler:
vcc.options.linker = r"/F33554432" # set the stack size to 8 MB
vcc.options.debug = "/RTC1 /ZI"
vcc.options.always = "/nologo"
vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"$nimrod\dist\dm\bin"
@end
# Configuration for the Tiny C Compiler:
tcc.options.always = "-w"
hint[LineTooLong]=off
#hint[XDeclaredButNotUsed]=off
@if unix:
@if not bsd:
gcc.options.linker = "-ldl"
@end
@end
# Configuration for the Intel C/C++ compiler:
icc.options.always = "-cxxlib"
icc.options.linker = "-cxxlib"
# Configuration for the GNU C/C++ compiler:
@if windows:
gcc.path = r"$nimrod\dist\mingw\bin"
@end
gcc.options.debug = "-g"
@if macosx:
gcc.options.always = "-w -fasm-blocks"
@else:
gcc.options.always = "-w"
@end
gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os"
#passl = "-pg"
# Configuration for the LLVM GCC compiler:
llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O2"
llvm_gcc.options.size = "-Os"
# Configuration for the Visual C/C++ compiler:
vcc.options.linker = r"/F33554432" # set the stack size to 8 MB
vcc.options.debug = "/RTC1 /ZI"
vcc.options.always = "/nologo"
vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"$nimrod\dist\dm\bin"
@end
# Configuration for the Tiny C Compiler:
tcc.options.always = "-w"

View File

@@ -7,10 +7,10 @@ Advanced commands::
check checks the project for syntax and semantic
parse parses a single file (for debugging Nimrod)
Advanced options:
-w, --warnings:on|off warnings ON|OFF
--warning[X]:on|off specific warning X ON|OFF
--hints:on|off hints ON|OFF
--hint[X]:on|off specific hint X ON|OFF
-w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off
--hint[X]:on|off turn specific hint X on|off
--lib:PATH set the system library path
-c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link
@@ -24,8 +24,8 @@ Advanced options:
-l, --passl:OPTION pass an option to the linker
--genMapping generate a mapping file containing
(Nimrod, mangled) identifier pairs
--lineDir:on|off generation of #line directive ON|OFF
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
--lineDir:on|off generation of #line directive on|off
--checkpoints:on|off turn checkpoints on|off; for debugging Nimrod
--skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC

View File

@@ -14,18 +14,20 @@ Options:
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules
--symbolFiles:on|off use symbol files to speed up compilation (buggy!)
--stackTrace:on|off code generation for stack trace ON|OFF
--lineTrace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF
-x, --checks:on|off code generation for all runtime checks ON|OFF
--objChecks:on|off code generation for obj conversion checks ON|OFF
--fieldChecks:on|off code generation for case variant fields ON|OFF
--rangeChecks:on|off code generation for range checks ON|OFF
--boundChecks:on|off code generation for bound checks ON|OFF
--overflowChecks:on|off code generation for over-/underflow checks ON|OFF
-a, --assertions:on|off code generation for assertions ON|OFF
--deadCodeElim:on|off whole program dead code elimination ON|OFF
--stackTrace:on|off turn stack tracing on|off
--lineTrace:on|off turn line tracing on|off
--debugger:on|off turn Embedded Nimrod Debugger on|off
-x, --checks:on|off turn all runtime checks on|off
--objChecks:on|off turn obj conversion checks on|off
--fieldChecks:on|off turn case variant field checks on|off
--rangeChecks:on|off turn range checks on|off
--boundChecks:on|off turn bound checks on|off
--overflowChecks:on|off turn int over-/underflow checks on|off
-a, --assertions:on|off turn assertions on|off
--floatChecks:on|off turn all floating point (NaN/Inf) checks on|off
--nanChecks:on|off turn NaN checks on|off
--infChecks:on|off turn Inf checks on|off
--deadCodeElim:on|off whole program dead code elimination on|off
--opt:none|speed|size optimize not at all or for speed|size
--app:console|gui|lib generate a console|GUI application|dynamic library
-r, --run run the compiled program with given arguments

View File

@@ -47,7 +47,7 @@ components called `locations`:idx:. A variable is basically a name for a
location. Each variable and location is of a certain `type`:idx:. The
variable's type is called `static type`:idx:, the location's type is called
`dynamic type`:idx:. If the static type is not the same as the dynamic type,
it is a supertype or subtype of the dynamic type.
it is a super-type or subtype of the dynamic type.
An `identifier`:idx: is a symbol declared as a name for a variable, type,
procedure, etc. The region of the program over which a declaration applies is
@@ -424,8 +424,8 @@ Integers, bool, characters and enumeration types (and subrange of these
types) belong to ordinal types.
Pre-defined numerical types
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pre-defined integer types
~~~~~~~~~~~~~~~~~~~~~~~~~
These integer types are pre-defined:
``int``
@@ -469,6 +469,14 @@ operation meaning
``int32`` type)
====================== ======================================================
`Automatic type conversion`:idx: is performed in expressions where different
kinds of integer types are used: the smaller type is converted to the larger.
For further details, see `Convertible relation`_.
Pre-defined floating point types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following floating point types are pre-defined:
``float``
@@ -482,16 +490,49 @@ floatXX
implementation supports ``float32`` and ``float64``. Literals of these types
have the suffix 'fXX.
`Automatic type conversion`:idx: is performed in expressions where different
kinds of integer types are used. However, if the type conversion
loses information, the `EOutOfRange`:idx: exception is raised (if the error
cannot be detected at compile time).
Automatic type conversion in expressions with different kinds
of floating point types is performed: the smaller type is
converted to the larger. Arithmetic performed on floating point types
follows the IEEE standard. Integer types are not converted to floating point
types automatically and vice versa.
of floating point types is performed: See `Convertible relation`_ for further
details. Arithmetic performed on floating point types follows the IEEE
standard. Integer types are not converted to floating point types automatically
and vice versa.
The IEEE standard defines five types of floating-point exceptions:
* Invalid: operations with mathematically invalid operands,
for example 0.0/0.0, sqrt(-1.0), and log(-37.8).
* Division by zero: divisor is zero and dividend is a finite nonzero number,
for example 1.0/0.0.
* Overflow: operation produces a result that exceeds the range of the exponent,
for example MAXDOUBLE+0.0000000000001e308.
* Underflow: operation produces a result that is too small to be represented
as a normal number, for example, MINDOUBLE * MINDOUBLE.
* Inexact: operation produces a result that cannot be represented with infinite
precision, for example, 2.0 / 3.0, log(1.1) and 0.1 in input.
The IEEE exceptions are either ignored at runtime or mapped to the
Nimrod exceptions: `EFloatInvalidOp`:idx, `EFloatDivByZero`:idx:,
`EFloatOverflow`:idx:, `EFloatUnderflow`:idx:, and `EFloatInexact`:idx:\.
These exceptions inherit from the `EFloatingPoint`:idx: base class.
Nimrod provides the pragmas `NaNChecks`:idx and `InfChecks`:idx:\ to control
whether the IEEE exceptions are ignored or trap a Nimrod exception:
.. code-block:: nimrod
{.NanChecks: on, InfChecks: on.}
var a = 1.0
var b = 0.0
echo b / b # raises EFloatInvalidOp
echo a / b # raises EFloatOverflow
In the current implementation ``EFloatDivByZero`` and ``EFloatInexact`` are
never raised. ``EFloatOverflow`` is raised instead of ``EFloatDivByZero``.
There is also a `floatChecks`:idx: pragma that is a short-cut for the
combination of ``NaNChecks`` and ``InfChecks`` pragmas. ``floatChecks`` are
turned off as default.
The only operations that are affected by the ``floatChecks`` pragma are
the ``+``, ``-``, ``*``, ``/`` operators for floating point types.
Boolean type

View File

@@ -7,6 +7,10 @@
.. contents::
"Look at you, hacker. A pathetic creature of meat and bone, panting and
sweating as you run through my corridors. How can you challenge a perfect,
immortal machine?"
Introduction
============
@@ -242,7 +246,7 @@ memory, but nothing worse happens.
DeadCodeElim Pragma
~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~
The `deadCodeElim`:idx: pragma only applies to whole modules: It tells the
compiler to activate (or deactivate) dead code elimination for the module the
pragma appers in.
@@ -304,13 +308,13 @@ Optimizing string handling
String assignments are sometimes expensive in Nimrod: They are required to
copy the whole string. However, the compiler is often smart enough to not copy
strings. Due to the argument passing semantics, strings are never copied when
passed to subroutines. The compiler does not copy strings that are result from
a procedure call, because the called procedure returns a new string anyway.
passed to subroutines. The compiler does not copy strings that are a result from
a procedure call, because the callee returns a new string anyway.
Thus it is efficient to do:
.. code-block:: Nimrod
var s = procA() # assignment will not copy the string; procA allocates a new
# string anyway
# string already
However it is not efficient to do:

View File

@@ -101,7 +101,7 @@ proc mean*(x: openarray[float]): float {.noSideEffect.} =
result = sum(x) / toFloat(len(x))
proc variance*(x: openarray[float]): float {.noSideEffect.} =
## computes the mean of the elements in `x`.
## computes the variance of the elements in `x`.
## If `x` is empty, NaN is returned.
result = 0.0
var m = mean(x)

View File

@@ -222,10 +222,10 @@ type
EFloatingPoint* = object of ESynch ## base class for floating point exceptions
EFloatInvalidOp* {.compilerproc.} =
object of EFloatingPoint ## Invalid operation according to IEEE: Raised by
## 0.0/0.0, sqrt(-1.0), and log(-37.8) for example.
## 0.0/0.0, for example.
EFloatDivByZero* {.compilerproc.} =
object of EFloatingPoint ## Division by zero. Divisor is zero and dividend
## is a finite nonzero number
## is a finite nonzero number.
EFloatOverflow* {.compilerproc.} =
object of EFloatingPoint ## Overflow. Operation produces a result
## that exceeds the range of the exponent

View File

@@ -314,3 +314,21 @@ when not defined(mulInt):
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
return result
raiseOverflow()
# We avoid setting the FPU control word here for compatibility with libraries
# written in other languages.
proc raiseFloatInvalidOp {.noinline, noreturn.} =
raise newException(EFloatInvalidOp, "FPU operation caused a NaN result")
proc nanCheck(x: float64) {.compilerProc, inline.} =
if x != x: raiseFloatInvalidOp()
proc raiseFloatOverflow(x: float64) {.noinline, noreturn.} =
if x > 0.0:
raise newException(EFloatOverflow, "FPU operation caused an overflow")
else:
raise newException(EFloatUnderflow, "FPU operations caused an underflow")
proc infCheck(x: float64) {.compilerProc, inline.} =
if x != 0.0 and x*0.5 == x: raiseFloatOverflow(x)

View File

@@ -37,16 +37,16 @@
when defined(MACOSX):
const
LUA_NAME* = "liblua(5.2|5.1|5.0).dylib"
LUA_LIB_NAME* = "liblua(5.2|5.1|5.0).dylib"
LUA_NAME* = "liblua(|5.2|5.1|5.0).dylib"
LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
elif defined(UNIX):
const
LUA_NAME* = "liblua(5.2|5.1|5.0).so.0"
LUA_LIB_NAME* = "liblua(5.2|5.1|5.0).so.0"
LUA_NAME* = "liblua(|5.2|5.1|5.0).so.(|0)"
LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).so.(|0)"
else:
const
LUA_NAME* = "lua(5.2|5.1|5.0).dll"
LUA_LIB_NAME* = "lua(5.2|5.1|5.0).dll"
LUA_NAME* = "lua(|5.2|5.1|5.0).dll"
LUA_LIB_NAME* = "lua(|5.2|5.1|5.0).dll"
type
size_t* = int
Psize_t* = ptr size_t
@@ -56,7 +56,8 @@ const
LUA_RELEASE* = "Lua 5.1.1"
LUA_VERSION_NUM* = 501
LUA_COPYRIGHT* = "Copyright (C) 1994-2006 Lua.org, PUC-Rio"
LUA_AUTHORS* = "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" # option for multiple returns in `lua_pcall' and `lua_call'
LUA_AUTHORS* = "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
# option for multiple returns in `lua_pcall' and `lua_call'
LUA_MULTRET* = - 1 #
#** pseudo-indices
#
@@ -74,19 +75,18 @@ const # thread status; 0 is OK
type
Plua_State* = Pointer
lua_CFunction* = proc (L: Plua_State): int{.cdecl.} #
#** functions that read/write blocks when loading/dumping Lua chunks
#
lua_CFunction* = proc (L: Plua_State): int{.cdecl.}
#
#** functions that read/write blocks when loading/dumping Lua chunks
#
type
lua_Reader* = proc (L: Plua_State, ud: Pointer, sz: Psize_t): cstring{.cdecl.}
lua_Writer* = proc (L: Plua_State, p: Pointer, sz: size_t, ud: Pointer): int{.
cdecl.} #
#** prototype for memory-allocation functions
#
cdecl.}
lua_Alloc* = proc (ud, theptr: Pointer, osize, nsize: size_t){.cdecl.}
const
const
LUA_TNONE* = - 1
LUA_TNIL* = 0
LUA_TBOOLEAN* = 1
@@ -218,9 +218,10 @@ proc lua_getallocf*(L: Plua_State, ud: ptr Pointer): lua_Alloc{.cdecl,
dynlib: LUA_NAME, importc.}
proc lua_setallocf*(L: Plua_State, f: lua_Alloc, ud: Pointer){.cdecl,
dynlib: LUA_NAME, importc.}
#
#** Garbage-collection functions and options
#
#
#** Garbage-collection functions and options
#
const
LUA_GCSTOP* = 0
LUA_GCRESTART* = 1
@@ -229,11 +230,13 @@ const
LUA_GCCOUNTB* = 4
LUA_GCSTEP* = 5
LUA_GCSETPAUSE* = 6
LUA_GCSETSTEPMUL* = 7 #
#** ===============================================================
#** some useful macros
#** ===============================================================
#
LUA_GCSETSTEPMUL* = 7
#
#** ===============================================================
#** some useful macros
#** ===============================================================
#
proc lua_pop*(L: Plua_State, n: int)
proc lua_newtable*(L: Plua_state)
@@ -252,18 +255,20 @@ proc lua_pushliteral*(L: Plua_State, s: cstring)
proc lua_setglobal*(L: Plua_State, s: cstring)
proc lua_getglobal*(L: Plua_State, s: cstring)
proc lua_tostring*(L: Plua_State, i: int): cstring
#
#** compatibility macros and functions
#
#
#** compatibility macros and functions
#
proc lua_getregistry*(L: Plua_State)
proc lua_getgccount*(L: Plua_State): int
type
lua_Chunkreader* = lua_Reader
lua_Chunkwriter* = lua_Writer #
#** {======================================================================
#** Debug API
#** =======================================================================
#
lua_Chunkwriter* = lua_Writer
#
#** {======================================================================
#** Debug API
#** =======================================================================
#
const
LUA_HOOKCALL* = 0
@@ -297,11 +302,13 @@ type
i_ci*: int # active function
Plua_Debug* = ptr lua_Debug
lua_Hook* = proc (L: Plua_State, ar: Plua_Debug){.cdecl.} #
#** {======================================================================
#** Debug API
#** =======================================================================
#
lua_Hook* = proc (L: Plua_State, ar: Plua_Debug){.cdecl.}
#
#** {======================================================================
#** Debug API
#** =======================================================================
#
proc lua_getstack*(L: Plua_State, level: int, ar: Plua_Debug): int{.cdecl,
dynlib: LUA_NAME, importc.}

View File

@@ -303,10 +303,10 @@ type
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
mDivI64, mModI64, mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
mDivI64, mModI64,
mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
mMinF64, mMaxF64, mAddU, mSubU, mMulU,
mDivU, mModU, mAddU64, mSubU64, mMulU64, mDivU64, mModU64, mEqI, mLeI, mLtI,
mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64, mLeU, mLtU, mLeU64, mLtU64,

View File

@@ -118,7 +118,8 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
frmt = "0x$1}$n"
appf(result, frmt, [toRope(toHex(Ze64(cs[i]), 2))])
else:
result = intLiteral(bitSetToWord(cs, size)) # result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
result = intLiteral(bitSetToWord(cs, size))
# result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
proc genSetNode(p: BProc, n: PNode): PRope =
var
@@ -384,14 +385,12 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
"modInt64"]
opr: array[mAddi..mModi64, string] = ["+", "-", "*", "/", "%", "+", "-",
"*", "/", "%"]
var
a, b: TLoc
t: PType
var a, b: TLoc
assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
t = skipTypes(e.typ, abstractRange)
var t = skipTypes(e.typ, abstractRange)
if getSize(t) >= platform.IntSize:
if optOverflowCheck in p.options:
useMagic(p.module, prc[m])
@@ -437,8 +436,12 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
const
binArithTab: array[mShrI..mXor, string] = ["(NI$3)((NU$3)($1) >> (NU$3)($2))", #
# ShrI
binArithTab: array[mAddF64..mXor, string] = [
"($1 + $2)", # AddF64
"($1 - $2)", # SubF64
"($1 * $2)", # MulF64
"($1 / $2)", # DivF64
"(NI$3)((NU$3)($1) >> (NU$3)($2))", # ShrI
"(NI$3)((NU$3)($1) << (NU$3)($2))", # ShlI
"(NI$3)($1 & $2)", # BitandI
"(NI$3)($1 | $2)", # BitorI
@@ -452,10 +455,6 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
"($1 ^ $2)", # BitxorI64
"(($1 <= $2) ? $1 : $2)", # MinI64
"(($1 >= $2) ? $1 : $2)", # MaxI64
"($1 + $2)", # AddF64
"($1 - $2)", # SubF64
"($1 * $2)", # MulF64
"($1 / $2)", # DivF64
"(($1 <= $2) ? $1 : $2)", # MinF64
"(($1 >= $2) ? $1 : $2)", # MaxF64
"(NI$3)((NU$3)($1) + (NU$3)($2))", # AddU
@@ -503,7 +502,8 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b) # BUGFIX: cannot use result-type here, as it may be a boolean
InitLocExpr(p, e.sons[2], b)
# BUGFIX: cannot use result-type here, as it may be a boolean
s = max(getSize(a.t), getSize(b.t)) * 8
putIntoDest(p, d, e.typ,
ropef(binArithTab[op], [rdLoc(a), rdLoc(b), toRope(s)]))
@@ -672,14 +672,12 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
genRecordField(p, e.sons[0], d)
proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
var
a, b: TLoc
ty: PType
first: PRope
var a, b: TLoc
initLocExpr(p, e.sons[0], a)
initLocExpr(p, e.sons[1], b)
ty = skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs)
first = intLiteral(firstOrd(ty)) # emit range check:
var ty = skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs)
var first = intLiteral(firstOrd(ty))
# emit range check:
if (optBoundsCheck in p.options):
if not isConstExpr(e.sons[1]):
# semantic pass has already checked for const index expressions
@@ -696,12 +694,10 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
ropef("$1[($2)-$3]", [rdLoc(a), rdCharLoc(b), first]))
proc genCStringElem(p: BProc, e: PNode, d: var TLoc) =
var
a, b: TLoc
ty: PType
var a, b: TLoc
initLocExpr(p, e.sons[0], a)
initLocExpr(p, e.sons[1], b)
ty = skipTypes(a.t, abstractVarRange)
var ty = skipTypes(a.t, abstractVarRange)
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
ropef("$1[$2]", [rdLoc(a), rdCharLoc(b)]))
@@ -719,12 +715,10 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
ropef("$1[$2]", [rdLoc(a), rdCharLoc(b)]))
proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
var
a, b: TLoc
ty: PType
var a, b: TLoc
initLocExpr(p, e.sons[0], a)
initLocExpr(p, e.sons[1], b)
ty = skipTypes(a.t, abstractVarRange)
var ty = skipTypes(a.t, abstractVarRange)
if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
if (optBoundsCheck in p.options):
@@ -770,7 +764,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
getTemp(p, e.typ, tmp) # force it into a temp!
expr(p, e.sons[1], tmp)
L = getLabel(p)
if m == mOr: # mAnd:
if m == mOr:
appf(p.s[cpsStmts], "if ($1) goto $2;$n", [rdLoc(tmp), L])
else:
appf(p.s[cpsStmts], "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
@@ -888,15 +882,12 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
# appendChar(tmp0, 'z');
# asgn(s, tmp0);
# }
var
a, tmp: TLoc
appends, lens: PRope
L: int
var a, tmp: TLoc
useMagic(p.module, "rawNewString")
getTemp(p, e.typ, tmp)
L = 0
appends = nil
lens = nil
var L = 0
var appends: PRope = nil
var lens: PRope = nil
for i in countup(0, sonsLen(e) - 2):
# compute the length expression:
initLocExpr(p, e.sons[i + 1], a)
@@ -1060,8 +1051,9 @@ proc genNewFinalize(p: BProc, e: PNode) =
oldModule: BModule
useMagic(p.module, "newObj")
refType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a) # This is a little hack:
# XXX this is also a bug, if the finalizer expression produces side-effects
InitLocExpr(p, e.sons[1], a)
# This is a little hack:
# XXX this is also a bug, if the finalizer expression produces side-effects
oldModule = p.module
p.module = gNimDat
InitLocExpr(p, e.sons[2], f)
@@ -1076,11 +1068,9 @@ proc genNewFinalize(p: BProc, e: PNode) =
genObjectInit(p, bt, a, false)
proc genRepr(p: BProc, e: PNode, d: var TLoc) =
var
a: TLoc
t: PType
var a: TLoc
InitLocExpr(p, e.sons[1], a)
t = skipTypes(e.sons[1].typ, abstractVarRange)
var t = skipTypes(e.sons[1].typ, abstractVarRange)
case t.kind
of tyInt..tyInt64:
UseMagic(p.module, "reprInt")
@@ -1108,8 +1098,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
of tyOpenArray:
useMagic(p.module, "reprOpenArray")
case a.t.kind
of tyOpenArray:
putIntoDest(p, d, e.typ, ropef("$1, $1Len0", [rdLoc(a)]))
of tyOpenArray: putIntoDest(p, d, e.typ, ropef("$1, $1Len0", [rdLoc(a)]))
of tyString, tySequence:
putIntoDest(p, d, e.typ, ropef("$1->data, $1->Sup.len", [rdLoc(a)]))
of tyArray, tyArrayConstr:
@@ -1137,8 +1126,7 @@ proc genDollar(p: BProc, n: PNode, d: var TLoc, magic, frmt: string) =
genAssignment(p, d, a, {})
proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var typ: PType
typ = skipTypes(e.sons[1].Typ, abstractPtrs)
var typ = skipTypes(e.sons[1].Typ, abstractPtrs)
case typ.kind
of tyOpenArray:
while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0]
@@ -1157,14 +1145,12 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: InternalError(e.info, "genArrayLen()")
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
var
a, b: TLoc
t: PType
var a, b: TLoc
assert(d.k == locNone)
useMagic(p.module, "setLengthSeq")
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
t = skipTypes(e.sons[1].typ, abstractVar)
var t = skipTypes(e.sons[1].typ, abstractVar)
appf(p.s[cpsStmts], "$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
getTypeDesc(p.module, t.sons[0])])
@@ -1202,8 +1188,7 @@ proc fewCmps(s: PNode): bool =
elif elemType(s.typ).Kind in {tyInt, tyInt16..tyInt64}:
result = true # better not emit the set if int is basetype!
else:
result = sonsLen(s) <=
8 # 8 seems to be a good value
result = sonsLen(s) <= 8 # 8 seems to be a good value
proc binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a), rdSetElemLoc(b, a.t)]))
@@ -1224,16 +1209,14 @@ proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
appf(p.s[cpsStmts], frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
proc genInOp(p: BProc, e: PNode, d: var TLoc) =
var
a, b, x, y: TLoc
length: int
var a, b, x, y: TLoc
if (e.sons[1].Kind == nkCurly) and fewCmps(e.sons[1]):
# a set constructor but not a constant set:
# do not emit the set, but generate a bunch of comparisons
initLocExpr(p, e.sons[2], a)
initLoc(b, locExpr, e.typ, OnUnknown)
b.r = toRope("(")
length = sonsLen(e.sons[1])
var length = sonsLen(e.sons[1])
for i in countup(0, length - 1):
if e.sons[1].sons[i].Kind == nkRange:
InitLocExpr(p, e.sons[1].sons[i].sons[0], x)
@@ -1255,56 +1238,45 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
const
lookupOpr: array[mLeSet..mSymDiffSet, string] = ["for ($1 = 0; $1 < $2; $1++) { $n" &
" $3 = (($4[$1] & ~ $5[$1]) == 0);$n" & " if (!$3) break;}$n", "for ($1 = 0; $1 < $2; $1++) { $n" &
lookupOpr: array[mLeSet..mSymDiffSet, string] = [
"for ($1 = 0; $1 < $2; $1++) { $n" &
" $3 = (($4[$1] & ~ $5[$1]) == 0);$n" &
" if (!$3) break;}$n", "for ($1 = 0; $1 < $2; $1++) { $n" &
" $3 = (($4[$1] & ~ $5[$1]) == 0);$n" & " if (!$3) break;}$n" &
"if ($3) $3 = (memcmp($4, $5, $2) != 0);$n", "&", "|", "& ~", "^"]
var
size: int
setType: PType
a, b, i: TLoc
ts: string
setType = skipTypes(e.sons[1].Typ, abstractVar)
size = int(getSize(setType))
"if ($3) $3 = (memcmp($4, $5, $2) != 0);$n",
"&", "|", "& ~", "^"]
var a, b, i: TLoc
var setType = skipTypes(e.sons[1].Typ, abstractVar)
var size = int(getSize(setType))
case size
of 1, 2, 4, 8:
case op
of mIncl:
ts = "NI" & $(size * 8)
var ts = "NI" & $(size * 8)
binaryStmtInExcl(p, e, d,
"$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n")
of mExcl:
ts = "NI" & $(size * 8)
var ts = "NI" & $(size * 8)
binaryStmtInExcl(p, e, d, "$1 &= ~(1 << ((" & ts & ")($2) % (sizeof(" &
ts & ")*8)));$n")
of mCard:
if size <= 4: unaryExprChar(p, e, d, "countBits32", "countBits32($1)")
else: unaryExprChar(p, e, d, "countBits64", "countBits64($1)")
of mLtSet:
binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))")
of mLeSet:
binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)")
of mEqSet:
binaryExpr(p, e, d, "", "($1 == $2)")
of mMulSet:
binaryExpr(p, e, d, "", "($1 & $2)")
of mPlusSet:
binaryExpr(p, e, d, "", "($1 | $2)")
of mMinusSet:
binaryExpr(p, e, d, "", "($1 & ~ $2)")
of mSymDiffSet:
binaryExpr(p, e, d, "", "($1 ^ $2)")
of mLtSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))")
of mLeSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)")
of mEqSet: binaryExpr(p, e, d, "", "($1 == $2)")
of mMulSet: binaryExpr(p, e, d, "", "($1 & $2)")
of mPlusSet: binaryExpr(p, e, d, "", "($1 | $2)")
of mMinusSet: binaryExpr(p, e, d, "", "($1 & ~ $2)")
of mSymDiffSet: binaryExpr(p, e, d, "", "($1 ^ $2)")
of mInSet:
genInOp(p, e, d)
else: internalError(e.info, "genSetOp()")
else:
case op
of mIncl:
binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n")
of mExcl:
binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n")
of mCard:
unaryExprChar(p, e, d, "cardSet", "cardSet($1, " & $(size) & ')')
of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n")
of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n")
of mCard: unaryExprChar(p, e, d, "cardSet", "cardSet($1, " & $size & ')')
of mLtSet, mLeSet:
getTemp(p, getSysType(tyInt), i) # our counter
initLocExpr(p, e.sons[1], a)
@@ -1324,8 +1296,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
"for ($1 = 0; $1 < $2; $1++) $n" & " $3[$1] = $4[$1] $6 $5[$1];$n", [
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
toRope(lookupOpr[op])])
of mInSet:
genInOp(p, e, d)
of mInSet: genInOp(p, e, d)
else: internalError(e.info, "genSetOp")
proc genOrd(p: BProc, e: PNode, d: var TLoc) =
@@ -1347,10 +1318,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
[getTypeDesc(p.module, e.typ), rdCharLoc(a)]))
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
var
a: TLoc
dest: PType
dest = skipTypes(n.typ, abstractVar)
var a: TLoc
var dest = skipTypes(n.typ, abstractVar)
if not (optRangeCheck in p.options):
InitLocExpr(p, n.sons[0], a)
putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
@@ -1367,12 +1336,10 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
genCast(p, e, d)
proc passToOpenArray(p: BProc, n: PNode, d: var TLoc) =
var
a: TLoc
dest: PType
var a: TLoc
while n.sons[0].kind == nkPassAsOpenArray:
n.sons[0] = n.sons[0].sons[0] # BUGFIX
dest = skipTypes(n.typ, abstractVar)
var dest = skipTypes(n.typ, abstractVar)
case skipTypes(n.sons[0].typ, abstractVar).kind
of tyOpenArray:
initLocExpr(p, n.sons[0], a)
@@ -1398,11 +1365,9 @@ proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
ropef("cstrToNimstr($1)", [rdLoc(a)]))
proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
var
a, b: PNode
x: TLoc
a = e.sons[1]
b = e.sons[2]
var x: TLoc
var a = e.sons[1]
var b = e.sons[2]
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
binaryExpr(p, e, d, "", "($1 == $2)")
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
@@ -1431,9 +1396,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
expr(p, t.sons[i], arr)
proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
var
newSeq, elem, a, arr: TLoc
L: int
var newSeq, elem, a, arr: TLoc
if t.kind == nkBracket:
t.sons[1].typ = t.typ
genSeqConstr(p, t.sons[1], d)
@@ -1442,7 +1405,7 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
if d.k == locNone:
getTemp(p, t.typ, d)
# generate call to newSeq before adding the elements per hand:
L = int(lengthOrd(t.sons[1].typ))
var L = int(lengthOrd(t.sons[1].typ))
initLoc(newSeq, locExpr, t.typ, OnHeap)
newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
genTypeInfo(p.module, t.typ), intLiteral(L)])
@@ -1451,17 +1414,37 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
for i in countup(0, L - 1):
initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
elem.r = ropef("$1->data[$2]", [rdLoc(d), intLiteral(i)])
elem.s = OnHeap # we know that sequences are on the heap
elem.s = OnHeap # we know that sequences are on the heap
initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s)
arr.r = ropef("$1[$2]", [rdLoc(a), intLiteral(i)])
genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if {optNanCheck, optInfCheck} * p.options != {}:
const opr: array[mAddF64..mDivF64, string] = ["+", "-", "*", "/"]
var a, b: TLoc
assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
if optNanCheck in p.options:
useMagic(p.module, "nanCheck")
appf(p.s[cpsStmts], "nanCheck($1);$n", [rdLoc(d)])
if optInfCheck in p.options:
useMagic(p.module, "infCheck")
appf(p.s[cpsStmts], "infCheck($1);$n", [rdLoc(d)])
else:
binaryArith(p, e, d, m)
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var line, filen: PRope
case op
of mOr, mAnd: genAndOr(p, e, d, op)
of mNot..mToBiggestInt: unaryArith(p, e, d, op)
of mUnaryMinusI..mAbsI64: unaryArithOverflow(p, e, d, op)
of mAddF64..mDivF64: binaryFloatArith(p, e, d, op)
of mShrI..mXor: binaryArith(p, e, d, op)
of mAddi..mModi64: binaryArithOverflow(p, e, d, op)
of mRepr: genRepr(p, e, d)

View File

@@ -327,7 +327,7 @@ proc libCandidates(s: string, dest: var TStringSeq) =
if le >= 0 and ri > le:
var prefix = copy(s, 0, le - 1)
var suffix = copy(s, ri + 1)
for middle in split(copy(s, le + 1, ri - 1), {'|'}):
for middle in split(copy(s, le + 1, ri - 1), '|'):
libCandidates(prefix & middle & suffix, dest)
else:
add(dest, s)

View File

@@ -47,18 +47,20 @@ Options:
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules
--symbolFiles:on|off use symbol files to speed up compilation (buggy!)
--stackTrace:on|off code generation for stack trace ON|OFF
--lineTrace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF
-x, --checks:on|off code generation for all runtime checks ON|OFF
--objChecks:on|off code generation for obj conversion checks ON|OFF
--fieldChecks:on|off code generation for case variant fields ON|OFF
--rangeChecks:on|off code generation for range checks ON|OFF
--boundChecks:on|off code generation for bound checks ON|OFF
--overflowChecks:on|off code generation for over-/underflow checks ON|OFF
-a, --assertions:on|off code generation for assertions ON|OFF
--deadCodeElim:on|off whole program dead code elimination ON|OFF
--stackTrace:on|off turn stack tracing on|off
--lineTrace:on|off turn line tracing on|off
--debugger:on|off turn Embedded Nimrod Debugger on|off
-x, --checks:on|off turn all runtime checks on|off
--objChecks:on|off turn obj conversion checks on|off
--fieldChecks:on|off turn case variant field checks on|off
--rangeChecks:on|off turn range checks on|off
--boundChecks:on|off turn bound checks on|off
--overflowChecks:on|off turn int over-/underflow checks on|off
-a, --assertions:on|off turn assertions on|off
--floatChecks:on|off turn all floating point (NaN/Inf) checks on|off
--nanChecks:on|off turn NaN checks on|off
--infChecks:on|off turn Inf checks on|off
--deadCodeElim:on|off whole program dead code elimination on|off
--opt:none|speed|size optimize not at all or for speed|size
--app:console|gui|lib generate a console|GUI application|dynamic library
-r, --run run the compiled program with given arguments
@@ -76,10 +78,10 @@ Advanced commands::
check checks the project for syntax and semantic
parse parses a single file (for debugging Nimrod)
Advanced options:
-w, --warnings:on|off warnings ON|OFF
--warning[X]:on|off specific warning X ON|OFF
--hints:on|off hints ON|OFF
--hint[X]:on|off specific hint X ON|OFF
-w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off
--hint[X]:on|off turn specific hint X on|off
--lib:PATH set the system library path
-c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link
@@ -93,8 +95,8 @@ Advanced options:
-l, --passl:OPTION pass an option to the linker
--genMapping generate a mapping file containing
(Nimrod, mangled) identifier pairs
--lineDir:on|off generation of #line directive ON|OFF
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
--lineDir:on|off generation of #line directive on|off
--checkpoints:on|off turn checkpoints on|off; for debugging Nimrod
--skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
@@ -152,9 +154,8 @@ proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
info: TLineInfo) =
var i: int
cmd = ""
i = 0
var i = 0
if (i < len(switch) + 0) and (switch[i] == '-'): inc(i)
if (i < len(switch) + 0) and (switch[i] == '-'): inc(i)
while i < len(switch) + 0:
@@ -188,13 +189,9 @@ proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
info: TLineInfo) =
var
i, x: int
n: TNoteKind
id: string
id = "" # arg = "X]:on|off"
i = 0
n = hintMin
var id = "" # arg = "X]:on|off"
var i = 0
var n = hintMin
while (i < len(arg) + 0) and (arg[i] != ']'):
add(id, arg[i])
inc(i)
@@ -203,11 +200,11 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
if (i < len(arg) + 0) and (arg[i] in {':', '='}): inc(i)
else: InvalidCmdLineOption(pass, arg, info)
if state == wHint:
x = findStr(msgs.HintsToStr, id)
var x = findStr(msgs.HintsToStr, id)
if x >= 0: n = TNoteKind(x + ord(hintMin))
else: InvalidCmdLineOption(pass, arg, info)
else:
x = findStr(msgs.WarningsToStr, id)
var x = findStr(msgs.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin))
else: InvalidCmdLineOption(pass, arg, info)
case whichKeyword(copy(arg, i))
@@ -297,6 +294,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
if optProfiler in gOptions: DefineSymbol("profiler")
else: UndefSymbol("profiler")
of wChecks, wX: ProcessOnOffSwitch(checksOptions, arg, pass, info)
of wFloatChecks:
ProcessOnOffSwitch({optNanCheck, optInfCheck}, arg, pass, info)
of wInfChecks: ProcessOnOffSwitch({optInfCheck}, arg, pass, info)
of wNanChecks: ProcessOnOffSwitch({optNanCheck}, arg, pass, info)
of wObjChecks: ProcessOnOffSwitch({optObjCheck}, arg, pass, info)
of wFieldChecks: ProcessOnOffSwitch({optFieldCheck}, arg, pass, info)
of wRangeChecks: ProcessOnOffSwitch({optRangeCheck}, arg, pass, info)

View File

@@ -69,8 +69,9 @@ proc countDefinedSymbols(): int =
proc InitDefines() =
initStrTable(gSymbols)
DefineSymbol("nimrod") # 'nimrod' is always defined
# add platform specific symbols:
DefineSymbol("nimrod") # 'nimrod' is always defined
# add platform specific symbols:
case targetCPU
of cpuI386: DefineSymbol("x86")
of cpuIa64: DefineSymbol("itanium")
@@ -103,7 +104,7 @@ proc InitDefines() =
DefineSymbol("posix")
else:
nil
DefineSymbol("cpu" & $(cpu[targetCPU].bit))
DefineSymbol("cpu" & $cpu[targetCPU].bit)
DefineSymbol(normalize(endianToStr[cpu[targetCPU].endian]))
DefineSymbol(cpu[targetCPU].name)
DefineSymbol(platform.os[targetOS].name)

View File

@@ -536,7 +536,7 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
result = ropef("$n$n$1.. index::$n$2", [ind, result])
of rnContents:
result = ropef("$n$n$1.. contents::", [ind])
else: rawMessage(errCannotRenderX, rstnodeKindToStr[n.kind])
else: rawMessage(errCannotRenderX, $n.kind)
proc renderTocEntry(d: PDoc, e: TTocEntry): PRope =
result = dispF("<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>$n",
@@ -582,16 +582,12 @@ proc renderImage(d: PDoc, n: PRstNode): PRope =
if rsonsLen(n) >= 3: app(result, renderRstToOut(d, n.sons[2]))
proc renderCodeBlock(d: PDoc, n: PRstNode): PRope =
var
m: PRstNode
g: TGeneralTokenizer
langstr: string
lang: TSourceLanguage
result = nil
if n.sons[2] == nil: return
m = n.sons[2].sons[0]
var m = n.sons[2].sons[0]
if (m.kind != rnLeaf): InternalError("renderCodeBlock")
langstr = strip(getArgument(n))
var langstr = strip(getArgument(n))
var lang: TSourceLanguage
if langstr == "":
lang = langNimrod # default language
else:
@@ -600,12 +596,12 @@ proc renderCodeBlock(d: PDoc, n: PRstNode): PRope =
rawMessage(warnLanguageXNotSupported, langstr)
result = toRope(m.text)
else:
var g: TGeneralTokenizer
initGeneralTokenizer(g, m.text)
while true:
getNextToken(g, lang)
case g.kind
of gtEof:
break
of gtEof: break
of gtNone, gtWhitespace:
app(result, copy(m.text, g.start + 0, g.length + g.start - 1 + 0))
else:

View File

@@ -75,7 +75,7 @@ proc initCompRes(r: var TCompRes) =
proc initProc(p: var TProc, globals: PGlobals, module: BModule, procDef: PNode,
options: TOptions) =
p.blocks = @ []
p.blocks = @[]
p.options = options
p.module = module
p.procDef = procDef
@@ -87,8 +87,7 @@ const
tySet, tyVar, tyRef, tyPtr}
proc mapType(typ: PType): TEcmasTypeKind =
var t: PType
t = skipTypes(typ, abstractInst)
var t = skipTypes(typ, abstractInst)
case t.kind
of tyVar, tyRef, tyPtr:
if skipTypes(t.sons[0], abstractInst).kind in mappedToObject:
@@ -98,29 +97,20 @@ proc mapType(typ: PType): TEcmasTypeKind =
of tyPointer:
# treat a tyPointer like a typed pointer to an array of bytes
result = etyInt
of tyRange, tyDistinct, tyOrdinal:
result = mapType(t.sons[0])
of tyInt..tyInt64, tyEnum, tyChar:
result = etyInt
of tyBool:
result = etyBool
of tyFloat..tyFloat128:
result = etyFloat
of tySet:
result = etyObject # map a set to a table
of tyString, tySequence:
result = etyInt # little hack to get the right semantics
of tyRange, tyDistinct, tyOrdinal: result = mapType(t.sons[0])
of tyInt..tyInt64, tyEnum, tyChar: result = etyInt
of tyBool: result = etyBool
of tyFloat..tyFloat128: result = etyFloat
of tySet: result = etyObject # map a set to a table
of tyString, tySequence: result = etyInt # little hack to get right semantics
of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray:
result = etyObject
of tyNil:
result = etyNull
of tyNil: result = etyNull
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone,
tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc:
result = etyNone
of tyProc:
result = etyProc
of tyCString:
result = etyString
of tyProc: result = etyProc
of tyCString: result = etyString
proc mangle(name: string): string =
result = ""
@@ -132,7 +122,7 @@ proc mangle(name: string): string =
nil
of 'a'..'z', '0'..'9':
add(result, name[i])
else: result = result & 'X' & toHex(ord(name[i]), 2)
else: add(result, 'X' & toHex(ord(name[i]), 2))
proc mangleName(s: PSym): PRope =
result = s.loc.r
@@ -199,9 +189,8 @@ proc genObjectFields(p: var TProc, typ: PType, n: PNode): PRope =
else: internalError(n.info, "genObjectFields")
proc genObjectInfo(p: var TProc, typ: PType, name: PRope) =
var s: PRope
s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n", [name, toRope(ord(typ.kind))])
var s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n", [name, toRope(ord(typ.kind))])
prepend(p.globals.typeInfo, s)
appf(p.globals.typeInfo, "var NNI$1 = $2;$n",
[toRope(typ.id), genObjectFields(p, typ, typ.n)])
@@ -301,9 +290,9 @@ proc genOr(p: var TProc, a, b: PNode, r: var TCompRes) =
type
TMagicFrmt = array[0..3, string]
const # magic checked op; magic unchecked op; checked op; unchecked op
ops: array[mAddi..mStrToStr, TMagicFrmt] = [["addInt", "", "addInt($1, $2)",
"($1 + $2)"], # AddI
const # magic checked op; magic unchecked op; checked op; unchecked op
ops: array[mAddi..mStrToStr, TMagicFrmt] = [
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI
@@ -313,6 +302,10 @@ const # magic checked op; magic unchecked op; checked op
["mulInt64", "", "mulInt64($1, $2)", "($1 * $2)"], # MulI64
["divInt64", "", "divInt64($1, $2)", "Math.floor($1 / $2)"], # DivI64
["modInt64", "", "modInt64($1, $2)", "Math.floor($1 % $2)"], # ModI64
["", "", "($1 + $2)", "($1 + $2)"], # AddF64
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
@@ -327,10 +320,6 @@ const # magic checked op; magic unchecked op; checked op
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI64
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI64
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64
["", "", "($1 + $2)", "($1 + $2)"], # AddF64
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
["AddU", "AddU", "AddU($1, $2)", "AddU($1, $2)"], # AddU
@@ -461,8 +450,8 @@ proc genLineDir(p: var TProc, n: PNode, r: var TCompRes) =
appf(r.com, "F.line = $1;$n", [toRope(line)])
proc finishTryStmt(p: var TProc, r: var TCompRes, howMany: int) =
for i in countup(1, howMany): app(r.com, "excHandler = excHandler.prev;" &
tnl)
for i in countup(1, howMany):
app(r.com, "excHandler = excHandler.prev;" & tnl)
proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
var

23
rod/expand_importc.nim Executable file
View File

@@ -0,0 +1,23 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Simple tool to expand ``importc`` pragmas. Used for the clean up process of
## the diverse wrappers.
import
os, ropes, idents, ast, pnimsyn, rnimsyn
times, commands, scanner, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, platform, main, parseopt
if paramcount() == 0:
echo ""

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2008 Andreas Rumpf
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -37,15 +37,11 @@ proc getModuleFile(n: PNode): string =
result = ""
proc rawImportSymbol(c: PContext, s: PSym) =
var
check, copy, e: PSym
etyp: PType # enumeration type
it: TIdentIter
# This does not handle stubs, because otherwise loading on demand would be
# pointless in practice. So importing stubs is fine here!
copy = s # do not copy symbols when importing!
var copy = s # do not copy symbols when importing!
# check if we have already a symbol of the same name:
check = StrTableGet(c.tab.stack[importTablePos], s.name)
var check = StrTableGet(c.tab.stack[importTablePos], s.name)
if (check != nil) and (check.id != copy.id):
if not (s.kind in OverloadableSyms):
# s and check need to be qualified:
@@ -53,15 +49,16 @@ proc rawImportSymbol(c: PContext, s: PSym) =
IntSetIncl(c.AmbiguousSymbols, check.id)
StrTableAdd(c.tab.stack[importTablePos], copy)
if s.kind == skType:
etyp = s.typ
var etyp = s.typ
if etyp.kind in {tyBool, tyEnum}:
for j in countup(0, sonsLen(etyp.n) - 1):
e = etyp.n.sons[j].sym
var e = etyp.n.sons[j].sym
if (e.Kind != skEnumField):
InternalError(s.info, "rawImportSymbol")
# BUGFIX: because of aliases for enums the symbol may already
# have been put into the symbol table
# BUGFIX: but only iff they are the same symbols!
var it: TIdentIter
check = InitIdentIter(it, c.tab.stack[importTablePos], e.name)
while check != nil:
if check.id == e.id:
@@ -74,11 +71,8 @@ proc rawImportSymbol(c: PContext, s: PSym) =
addConverter(c, s) # rodgen assures that converters are no stubs
proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) =
var
s, e: PSym
it: TIdentIter
if (ident.kind != nkIdent): InternalError(ident.info, "importSymbol")
s = StrTableGet(fromMod.tab, ident.ident)
var s = StrTableGet(fromMod.tab, ident.ident)
if s == nil: liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s)
if s.kind == skStub: loadStub(s)
if not (s.Kind in ExportableSymKinds):
@@ -87,7 +81,8 @@ proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) =
case s.Kind
of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
# for a overloadable syms add all overloaded routines
e = InitIdentIter(it, fromMod.tab, s.name)
var it: TIdentIter
var e = InitIdentIter(it, fromMod.tab, s.name)
while e != nil:
if (e.name.id != s.Name.id): InternalError(ident.info, "importSymbol: 3")
rawImportSymbol(c, e)

View File

@@ -31,8 +31,7 @@ var compMods: TFileModuleMap = @ []
proc registerModule(filename: string, module: PSym) =
# all compiled modules
var length: int
length = len(compMods)
var length = len(compMods)
setlen(compMods, length + 1)
compMods[length].filename = filename
compMods[length].module = module
@@ -50,6 +49,9 @@ proc newModule(filename: string): PSym =
result.id = - 1 # for better error checking
result.kind = skModule
result.name = getIdent(splitFile(filename).name)
if not isNimrodIdentifier(result.name.s):
rawMessage(errIdentifierExpected, result.name.s)
result.owner = result # a module belongs to itself
result.info = newLineInfo(filename, 1, 1)
incl(result.flags, sfUsed)
@@ -68,11 +70,8 @@ proc importModule(filename: string): PSym =
liMessage(result.info, errAttemptToRedefine, result.Name.s)
proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym =
var
rd: PRodReader
f: string
rd = nil
f = addFileExt(filename, nimExt)
var rd: PRodReader = nil
var f = addFileExt(filename, nimExt)
result = newModule(filename)
if isMainFile: incl(result.flags, sfMainModule)
if isSystemFile: incl(result.flags, sfSystemModule)

View File

@@ -9,3 +9,4 @@
@elif vcc:
# cgen.speed = ""
@end

View File

@@ -17,11 +17,7 @@ var
cmdLineInfo: TLineInfo
proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
var
p: TOptParser
bracketLe: int
key, val: string
p = parseopt.init()
var p = parseopt.init()
while true:
parseopt.next(p)
case p.kind
@@ -30,10 +26,10 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
of cmdLongOption, cmdShortOption:
# hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
# we fix this here
bracketLe = strutils.find(p.key, '[')
var bracketLe = strutils.find(p.key, '[')
if bracketLe >= 0:
key = copy(p.key, 0, bracketLe - 1)
val = copy(p.key, bracketLe + 1) & ':' & p.val
var key = copy(p.key, 0, bracketLe - 1)
var val = copy(p.key, bracketLe + 1) & ':' & p.val
ProcessSwitch(key, val, pass, cmdLineInfo)
else:
ProcessSwitch(p.key, p.val, pass, cmdLineInfo)
@@ -49,21 +45,18 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
rawMessage(errArgsNeedRunOption)
proc HandleCmdLine() =
var
command, filename, prog: string
start: TTime
start = getTime()
var start = getTime()
if paramCount() == 0:
writeCommandLineUsage()
else:
# Process command line arguments:
command = ""
filename = ""
var command = ""
var filename = ""
ProcessCmdLine(passCmd1, command, filename)
if filename != "": options.projectPath = splitFile(filename).dir
nimconf.LoadConfig(filename) # load the right config file
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars()
command = ""
filename = ""
@@ -74,16 +67,12 @@ proc HandleCmdLine() =
rawMessage(hintSuccessX, [$(gLinesCompiled), $(getTime() - start)])
if optRun in gGlobalOptions:
when defined(unix):
prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
else:
prog = quoteIfContainsWhite(changeFileExt(filename, ""))
var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
execExternalProgram(prog & ' ' & arguments)
#{@emit
# GC_disableMarkAndSweep();
#}
cmdLineInfo = newLineInfo("command line", - 1, - 1)
condsyms.InitDefines()
HandleCmdLine()
quit(options.gExitcode)
quit(options.gExitcode)

View File

@@ -14,11 +14,14 @@ type # please make sure we have under 32 options
# (improves code efficiency a lot!)
TOption* = enum # **keep binary compatible**
optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
optOverflowCheck, optNilCheck, optAssert, optLineDir, optWarns, optHints,
optOverflowCheck, optNilCheck,
optNaNCheck, optInfCheck,
optAssert, optLineDir, optWarns, optHints,
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
optLineTrace, # line tracing support (includes stack tracing)
optEndb, # embedded debugger
optByRef, # use pass by ref for objects (for interfacing with C)
optByRef, # use pass by ref for objects
# (for interfacing with C)
optCheckpoints, # check for checkpoints (used for debugging)
optProfiler # profiler turned on
TOptions* = set[TOption]
@@ -50,12 +53,7 @@ type # please make sure we have under 32 options
const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
optOverflowCheck, optBoundsCheck, optAssert}
optionToStr*: array[TOption, string] = ["optNone", "optObjCheck",
"optFieldCheck", "optRangeCheck", "optBoundsCheck", "optOverflowCheck",
"optNilCheck", "optAssert", "optLineDir", "optWarns", "optHints",
"optOptimizeSpeed", "optOptimizeSize", "optStackTrace", "optLineTrace",
"optEmdb", "optByRef", "optCheckpoints", "optProfiler"]
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck}
var
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,

View File

@@ -32,7 +32,8 @@ const
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint,
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated}
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
wInfChecks, wNanChecks}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
@@ -220,6 +221,9 @@ proc processOption(c: PContext, n: PNode) =
of wBoundchecks: OnOff(c, n, {optBoundsCheck})
of wOverflowchecks: OnOff(c, n, {optOverflowCheck})
of wNilchecks: OnOff(c, n, {optNilCheck})
of wFloatChecks: OnOff(c, n, {optNanCheck, optInfCheck})
of wNaNchecks: OnOff(c, n, {optNanCheck})
of wInfChecks: OnOff(c, n, {optInfCheck})
of wAssertions: OnOff(c, n, {optAssert})
of wWarnings: OnOff(c, n, {optWarns})
of wHints: OnOff(c, n, {optHints})
@@ -434,7 +438,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef, wCallConv,
wDebugger, wProfiler:
wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks:
processOption(c, it) # calling conventions (boring...):
of firstCallConv..lastCallConv:
assert(sym != nil)

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
# This module implements a *reStructuredText* parser. A larget
# This module implements a *reStructuredText* parser. A large
# subset is provided.
import
@@ -33,25 +33,17 @@ type
rnFieldName, # consisting of a field name ...
rnFieldBody, # ... and a field body
rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString,
rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock, rnLineBlock, #
# the
# |
# thingie
rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock,
rnLineBlock, # the | thingie
rnLineBlockItem, # sons of the | thing
rnBlockQuote, # text just indented
rnTable, rnGridTable, rnTableRow, rnTableHeaderCell, rnTableDataCell, rnLabel, #
# used
# for
# footnotes
# and
# other
# things
rnTable, rnGridTable, rnTableRow, rnTableHeaderCell, rnTableDataCell,
rnLabel, # used for footnotes and other things
rnFootnote, # a footnote
rnCitation, # similar to footnote
rnStandaloneHyperlink, rnHyperlink, rnRef, rnDirective, # a directive
rnDirArg, rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock, rnContainer, #
# ``container``
# directive
rnDirArg, rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock,
rnContainer, # ``container`` directive
rnIndex, # index directve:
# .. index::
# key
@@ -64,22 +56,8 @@ type
rnInterpretedText, # "`"
rnInlineLiteral, # "``"
rnSubstitutionReferences, # "|"
rnLeaf # a leaf; the node's text field contains the leaf val
const
rstnodekindToStr*: array[TRstNodeKind, string] = ["Inner", "Headline",
"Overline", "Transition", "Paragraph", "BulletList", "BulletItem",
"EnumList", "EnumItem", "DefList", "DefItem", "DefName", "DefBody",
"FieldList", "Field", "FieldName", "FieldBody", "OptionList",
"OptionListItem", "OptionGroup", "Option", "OptionString", "OptionArgument",
"Description", "LiteralBlock", "QuotedLiteralBlock", "LineBlock",
"LineBlockItem", "BlockQuote", "Table", "GridTable", "TableRow",
"TableHeaderCell", "TableDataCell", "Label", "Footnote", "Citation",
"StandaloneHyperlink", "Hyperlink", "Ref", "Directive", "DirArg", "Raw",
"Title", "Contents", "Image", "Figure", "CodeBlock", "Container", "Index",
"SubstitutionDef", "GeneralRole", "Sub", "Sup", "Idx", "Emphasis",
"StrongEmphasis", "InterpretedText", "InlineLiteral",
"SubstitutionReferences", "Leaf"]
rnLeaf # a leaf; the node's text field contains the
# leaf val
type # the syntax tree of RST:
PRSTNode* = ref TRstNode
@@ -513,7 +491,6 @@ proc clearIndex(index: PRstNode, filename: string) =
proc setIndexPair(index, key, val: PRstNode) =
var e, a, b: PRstNode
# writeln(rstnodekindToStr[key.kind], ': ', rstnodekindToStr[val.kind]);
assert(index.kind == rnDefList)
assert(key.kind != rnDefName)
a = newRstNode(rnDefName)
@@ -590,7 +567,7 @@ proc isInlineMarkupEnd(p: TRstParser, markup: string): bool =
result = false
proc isInlineMarkupStart(p: TRstParser, markup: string): bool =
var c, d: Char
var d: Char
result = p.tok[p.idx].symbol == markup
if not result:
return # Rule 1:
@@ -606,7 +583,7 @@ proc isInlineMarkupStart(p: TRstParser, markup: string): bool =
if p.tok[p.idx - 1].symbol == "\\":
result = false
else:
c = p.tok[p.idx - 1].symbol[0]
var c = p.tok[p.idx - 1].symbol[0]
case c
of '\'', '\"': d = c
of '(': d = ')'
@@ -641,30 +618,19 @@ proc match(p: TRstParser, start: int, expr: string): bool =
# 'T' always true
# 'E' whitespace, indent or eof
# 'e' tkWord or '#' (for enumeration lists)
var
i, j, last, length: int
c: char
i = 0
j = start
last = len(expr) + 0 - 1
var i = 0
var j = start
var last = len(expr) + 0 - 1
while i <= last:
case expr[i]
of 'w':
result = p.tok[j].kind == tkWord
of ' ':
result = p.tok[j].kind == tkWhite
of 'i':
result = p.tok[j].kind == tkIndent
of 'p':
result = p.tok[j].kind == tkPunct
of 'a':
result = p.tok[j].kind == tkAdornment
of 'o':
result = p.tok[j].kind == tkOther
of 'T':
result = true
of 'E':
result = p.tok[j].kind in {tkEof, tkWhite, tkIndent}
of 'w': result = p.tok[j].kind == tkWord
of ' ': result = p.tok[j].kind == tkWhite
of 'i': result = p.tok[j].kind == tkIndent
of 'p': result = p.tok[j].kind == tkPunct
of 'a': result = p.tok[j].kind == tkAdornment
of 'o': result = p.tok[j].kind == tkOther
of 'T': result = true
of 'E': result = p.tok[j].kind in {tkEof, tkWhite, tkIndent}
of 'e':
result = (p.tok[j].kind == tkWord) or (p.tok[j].symbol == "#")
if result:
@@ -674,8 +640,8 @@ proc match(p: TRstParser, start: int, expr: string): bool =
else:
nil
else:
c = expr[i]
length = 0
var c = expr[i]
var length = 0
while (i <= last) and (expr[i] == c):
inc(i)
inc(length)
@@ -688,25 +654,22 @@ proc match(p: TRstParser, start: int, expr: string): bool =
result = true
proc fixupEmbeddedRef(n, a, b: PRstNode) =
var sep, incr: int
sep = - 1
var sep = - 1
for i in countdown(rsonsLen(n) - 2, 0):
if n.sons[i].text == "<":
sep = i
break
if (sep > 0) and (n.sons[sep - 1].text[0] == ' '): incr = 2
else: incr = 1
var incr = if (sep > 0) and (n.sons[sep - 1].text[0] == ' '): 2 else: 1
for i in countup(0, sep - incr): addSon(a, n.sons[i])
for i in countup(sep + 1, rsonsLen(n) - 2): addSon(b, n.sons[i])
proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode =
var a, b: PRstNode
result = n
if isInlineMarkupEnd(p, "_"):
inc(p.idx)
if (p.tok[p.idx - 2].symbol == "`") and (p.tok[p.idx - 3].symbol == ">"):
a = newRstNode(rnInner)
b = newRstNode(rnInner)
var a = newRstNode(rnInner)
var b = newRstNode(rnInner)
fixupEmbeddedRef(n, a, b)
if rsonsLen(a) == 0:
result = newRstNode(rnStandaloneHyperlink)
@@ -799,33 +762,32 @@ proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string,
else: rstMessage(p, errXExpected, postfix)
proc parseInline(p: var TRstParser, father: PRstNode) =
var n: PRstNode
case p.tok[p.idx].kind
of tkPunct:
if isInlineMarkupStart(p, "**"):
inc(p.idx)
n = newRstNode(rnStrongEmphasis)
var n = newRstNode(rnStrongEmphasis)
parseUntil(p, n, "**", true)
addSon(father, n)
elif isInlineMarkupStart(p, "*"):
inc(p.idx)
n = newRstNode(rnEmphasis)
var n = newRstNode(rnEmphasis)
parseUntil(p, n, "*", true)
addSon(father, n)
elif isInlineMarkupStart(p, "``"):
inc(p.idx)
n = newRstNode(rnInlineLiteral)
var n = newRstNode(rnInlineLiteral)
parseUntil(p, n, "``", false)
addSon(father, n)
elif isInlineMarkupStart(p, "`"):
inc(p.idx)
n = newRstNode(rnInterpretedText)
var n = newRstNode(rnInterpretedText)
parseUntil(p, n, "`", true)
n = parsePostfix(p, n)
addSon(father, n)
elif isInlineMarkupStart(p, "|"):
inc(p.idx)
n = newRstNode(rnSubstitutionReferences)
var n = newRstNode(rnSubstitutionReferences)
parseUntil(p, n, "|", false)
addSon(father, n)
else:
@@ -838,9 +800,8 @@ proc parseInline(p: var TRstParser, father: PRstNode) =
else: assert(false)
proc getDirective(p: var TRstParser): string =
var j: int
if (p.tok[p.idx].kind == tkWhite) and (p.tok[p.idx + 1].kind == tkWord):
j = p.idx
var j = p.idx
inc(p.idx)
result = p.tok[p.idx].symbol
inc(p.idx)
@@ -859,13 +820,12 @@ proc getDirective(p: var TRstParser): string =
result = ""
proc parseComment(p: var TRstParser): PRstNode =
var indent: int
case p.tok[p.idx].kind
of tkIndent, tkEof:
if p.tok[p.idx + 1].kind == tkIndent:
inc(p.idx) # empty comment
else:
indent = p.tok[p.idx].ival
var indent = p.tok[p.idx].ival
while True:
case p.tok[p.idx].kind
of tkEof:
@@ -903,18 +863,15 @@ proc parseLine(p: var TRstParser, father: PRstNode) =
proc parseSection(p: var TRstParser, result: PRstNode)
proc parseField(p: var TRstParser): PRstNode =
var
col, indent: int
fieldname, fieldbody: PRstNode
result = newRstNode(rnField)
col = p.tok[p.idx].col
var col = p.tok[p.idx].col
inc(p.idx) # skip :
fieldname = newRstNode(rnFieldname)
var fieldname = newRstNode(rnFieldname)
parseUntil(p, fieldname, ":", false)
fieldbody = newRstNode(rnFieldbody)
var fieldbody = newRstNode(rnFieldbody)
if p.tok[p.idx].kind != tkIndent: parseLine(p, fieldbody)
if p.tok[p.idx].kind == tkIndent:
indent = p.tok[p.idx].ival
var indent = p.tok[p.idx].ival
if indent > col:
pushInd(p, indent)
parseSection(p, fieldbody)
@@ -923,10 +880,9 @@ proc parseField(p: var TRstParser): PRstNode =
addSon(result, fieldbody)
proc parseFields(p: var TRstParser): PRstNode =
var col: int
result = nil
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx + 1].symbol == ":"):
col = p.tok[p.idx].ival # BUGFIX!
var col = p.tok[p.idx].ival # BUGFIX!
result = newRstNode(rnFieldList)
inc(p.idx)
while true:
@@ -938,17 +894,15 @@ proc parseFields(p: var TRstParser): PRstNode =
break
proc getFieldValue(n: PRstNode, fieldname: string): string =
var f: PRstNode
result = ""
if n.sons[1] == nil: return
if (n.sons[1].kind != rnFieldList):
InternalError("getFieldValue (2): " & rstnodeKindToStr[n.sons[1].kind])
InternalError("getFieldValue (2): " & $n.sons[1].kind)
for i in countup(0, rsonsLen(n.sons[1]) - 1):
f = n.sons[1].sons[i]
var f = n.sons[1].sons[i]
if cmpIgnoreStyle(addNodes(f.sons[0]), fieldname) == 0:
result = addNodes(f.sons[1])
if result == "":
result = "\x01\x01" # indicates that the field exists
if result == "": result = "\x01\x01" # indicates that the field exists
return
proc getArgument(n: PRstNode): string =
@@ -957,13 +911,10 @@ proc getArgument(n: PRstNode): string =
proc parseDotDot(p: var TRstParser): PRstNode
proc parseLiteralBlock(p: var TRstParser): PRstNode =
var
indent: int
n: PRstNode
result = newRstNode(rnLiteralBlock)
n = newRstNode(rnLeaf, "")
var n = newRstNode(rnLeaf, "")
if p.tok[p.idx].kind == tkIndent:
indent = p.tok[p.idx].ival
var indent = p.tok[p.idx].ival
inc(p.idx)
while True:
case p.tok[p.idx].kind
@@ -1003,8 +954,7 @@ proc tokenAfterNewline(p: TRstParser): int =
else: inc(result)
proc isLineBlock(p: TRstParser): bool =
var j: int
j = tokenAfterNewline(p)
var j = tokenAfterNewline(p)
result = (p.tok[p.idx].col == p.tok[j].col) and (p.tok[j].symbol == "|") or
(p.tok[j].col > p.tok[p.idx].col)
@@ -1015,8 +965,7 @@ proc predNL(p: TRstParser): bool =
(p.tok[p.idx - 1].ival == currInd(p))
proc isDefList(p: TRstParser): bool =
var j: int
j = tokenAfterNewline(p)
var j = tokenAfterNewline(p)
result = (p.tok[p.idx].col < p.tok[j].col) and
(p.tok[j].kind in {tkWord, tkOther, tkPunct}) and
(p.tok[j - 2].symbol != "::")
@@ -1063,17 +1012,14 @@ proc whichSection(p: TRstParser): TRstNodeKind =
else: result = rnLeaf
proc parseLineBlock(p: var TRstParser): PRstNode =
var
col: int
item: PRstNode
result = nil
if p.tok[p.idx + 1].kind == tkWhite:
col = p.tok[p.idx].col
var col = p.tok[p.idx].col
result = newRstNode(rnLineBlock)
pushInd(p, p.tok[p.idx + 2].col)
inc(p.idx, 2)
while true:
item = newRstNode(rnLineBlockItem)
var item = newRstNode(rnLineBlockItem)
parseSection(p, item)
addSon(result, item)
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
@@ -1120,12 +1066,11 @@ proc parseParagraphWrapper(p: var TRstParser): PRstNode =
parseParagraph(p, result)
proc parseHeadline(p: var TRstParser): PRstNode =
var c: Char
result = newRstNode(rnHeadline)
parseLine(p, result)
assert(p.tok[p.idx].kind == tkIndent)
assert(p.tok[p.idx + 1].kind == tkAdornment)
c = p.tok[p.idx + 1].symbol[0]
var c = p.tok[p.idx + 1].symbol[0]
inc(p.idx, 2)
result.level = getLevel(p.s.underlineToLevel, p.s.uLevel, c)
@@ -1136,8 +1081,7 @@ proc tokEnd(p: TRstParser): int =
result = p.tok[p.idx].col + len(p.tok[p.idx].symbol) - 1
proc getColumns(p: var TRstParser, cols: var TIntSeq) =
var L: int
L = 0
var L = 0
while true:
inc(L)
setlen(cols, L)
@@ -1161,8 +1105,8 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
q: TRstParser
a, b: PRstNode
result = newRstNode(rnTable)
cols = @ []
row = @ []
cols = @[]
row = @[]
a = nil
c = p.tok[p.idx].symbol[0]
while true:
@@ -1177,8 +1121,8 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
if a != nil:
for j in countup(0, rsonsLen(a) - 1): a.sons[j].kind = rnTableHeaderCell
if p.tok[p.idx].kind == tkEof: break
for j in countup(0, high(row)):
row[j] = "" # the following while loop iterates over the lines a single cell may span:
for j in countup(0, high(row)): row[j] = ""
# the following while loop iterates over the lines a single cell may span:
line = p.tok[p.idx].line
while true:
i = 0
@@ -1212,8 +1156,7 @@ proc parseTransition(p: var TRstParser): PRstNode =
if p.tok[p.idx].kind == tkIndent: inc(p.idx)
proc parseOverline(p: var TRstParser): PRstNode =
var c: char
c = p.tok[p.idx].symbol[0]
var c = p.tok[p.idx].symbol[0]
inc(p.idx, 2)
result = newRstNode(rnOverline)
while true:
@@ -1232,19 +1175,15 @@ proc parseOverline(p: var TRstParser): PRstNode =
if p.tok[p.idx].kind == tkIndent: inc(p.idx)
proc parseBulletList(p: var TRstParser): PRstNode =
var
bullet: string
col: int
item: PRstNode
result = nil
if p.tok[p.idx + 1].kind == tkWhite:
bullet = p.tok[p.idx].symbol
col = p.tok[p.idx].col
var bullet = p.tok[p.idx].symbol
var col = p.tok[p.idx].col
result = newRstNode(rnBulletList)
pushInd(p, p.tok[p.idx + 2].col)
inc(p.idx, 2)
while true:
item = newRstNode(rnBulletItem)
var item = newRstNode(rnBulletItem)
parseSection(p, item)
addSon(result, item)
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
@@ -1256,23 +1195,20 @@ proc parseBulletList(p: var TRstParser): PRstNode =
popInd(p)
proc parseOptionList(p: var TRstParser): PRstNode =
var
a, b, c: PRstNode
j: int
result = newRstNode(rnOptionList)
while true:
if match(p, p.idx, "-w") or match(p, p.idx, "--w") or
match(p, p.idx, "/w"):
a = newRstNode(rnOptionGroup)
b = newRstNode(rnDescription)
c = newRstNode(rnOptionListItem)
var a = newRstNode(rnOptionGroup)
var b = newRstNode(rnDescription)
var c = newRstNode(rnOptionListItem)
while not (p.tok[p.idx].kind in {tkIndent, tkEof}):
if (p.tok[p.idx].kind == tkWhite) and (len(p.tok[p.idx].symbol) > 1):
inc(p.idx)
break
addSon(a, newLeaf(p))
inc(p.idx)
j = tokenAfterNewline(p)
var j = tokenAfterNewline(p)
if (j > 0) and (p.tok[j - 1].kind == tkIndent) and
(p.tok[j - 1].ival > currInd(p)):
pushInd(p, p.tok[j - 1].ival)
@@ -1288,26 +1224,24 @@ proc parseOptionList(p: var TRstParser): PRstNode =
break
proc parseDefinitionList(p: var TRstParser): PRstNode =
var
j, col: int
a, b, c: PRstNode
result = nil
j = tokenAfterNewLine(p) - 1
var j = tokenAfterNewLine(p) - 1
if (j >= 1) and (p.tok[j].kind == tkIndent) and
(p.tok[j].ival > currInd(p)) and (p.tok[j - 1].symbol != "::"):
col = p.tok[p.idx].col
var col = p.tok[p.idx].col
result = newRstNode(rnDefList)
while true:
j = p.idx
a = newRstNode(rnDefName)
parseLine(p, a) #writeln('after def line: ', p.tok[p.idx].ival :1, ' ', col : 1);
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival > currInd(p)) and
var a = newRstNode(rnDefName)
parseLine(p, a)
if (p.tok[p.idx].kind == tkIndent) and
(p.tok[p.idx].ival > currInd(p)) and
(p.tok[p.idx + 1].symbol != "::") and
not (p.tok[p.idx + 1].kind in {tkIndent, tkEof}):
pushInd(p, p.tok[p.idx].ival)
b = newRstNode(rnDefBody)
var b = newRstNode(rnDefBody)
parseSection(p, b)
c = newRstNode(rnDefItem)
var c = newRstNode(rnDefItem)
addSon(c, a)
addSon(c, b)
addSon(result, c)
@@ -1329,23 +1263,20 @@ proc parseEnumList(p: var TRstParser): PRstNode =
const
wildcards: array[0..2, string] = ["(e) ", "e) ", "e. "]
wildpos: array[0..2, int] = [1, 0, 0]
var
w, col, j: int
item: PRstNode
result = nil
w = 0
var w = 0
while w <= 2:
if match(p, p.idx, wildcards[w]): break
inc(w)
if w <= 2:
col = p.tok[p.idx].col
var col = p.tok[p.idx].col
result = newRstNode(rnEnumList)
inc(p.idx, wildpos[w] + 3)
j = tokenAfterNewLine(p)
var j = tokenAfterNewLine(p)
if (p.tok[j].col == p.tok[p.idx].col) or match(p, j, wildcards[w]):
pushInd(p, p.tok[p.idx].col)
while true:
item = newRstNode(rnEnumItem)
var item = newRstNode(rnEnumItem)
parseSection(p, item)
addSon(result, item)
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
@@ -1363,19 +1294,15 @@ proc sonKind(father: PRstNode, i: int): TRstNodeKind =
if i < rsonsLen(father): result = father.sons[i].kind
proc parseSection(p: var TRstParser, result: PRstNode) =
var
a: PRstNode
k: TRstNodeKind
leave: bool
while true:
leave = false
var leave = false
assert(p.idx >= 0)
while p.tok[p.idx].kind == tkIndent:
if currInd(p) == p.tok[p.idx].ival:
inc(p.idx)
elif p.tok[p.idx].ival > currInd(p):
pushInd(p, p.tok[p.idx].ival)
a = newRstNode(rnBlockQuote)
var a = newRstNode(rnBlockQuote)
parseSection(p, a)
addSon(result, a)
popInd(p)
@@ -1384,39 +1311,27 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
break
if leave: break
if p.tok[p.idx].kind == tkEof: break
a = nil
k = whichSection(p)
var a: PRstNode = nil
var k = whichSection(p)
case k
of rnLiteralBlock:
inc(p.idx) # skip '::'
a = parseLiteralBlock(p)
of rnBulletList:
a = parseBulletList(p)
of rnLineblock:
a = parseLineBlock(p)
of rnDirective:
a = parseDotDot(p)
of rnEnumList:
a = parseEnumList(p)
of rnLeaf:
rstMessage(p, errNewSectionExpected)
of rnParagraph:
nil
of rnDefList:
a = parseDefinitionList(p)
of rnBulletList: a = parseBulletList(p)
of rnLineblock: a = parseLineBlock(p)
of rnDirective: a = parseDotDot(p)
of rnEnumList: a = parseEnumList(p)
of rnLeaf: rstMessage(p, errNewSectionExpected)
of rnParagraph: nil
of rnDefList: a = parseDefinitionList(p)
of rnFieldList:
dec(p.idx)
a = parseFields(p)
of rnTransition:
a = parseTransition(p)
of rnHeadline:
a = parseHeadline(p)
of rnOverline:
a = parseOverline(p)
of rnTable:
a = parseSimpleTable(p)
of rnOptionList:
a = parseOptionList(p)
of rnTransition: a = parseTransition(p)
of rnHeadline: a = parseHeadline(p)
of rnOverline: a = parseOverline(p)
of rnTable: a = parseSimpleTable(p)
of rnOptionList: a = parseOptionList(p)
else: InternalError("rst.parseSection()")
if (a == nil) and (k != rnDirective):
a = newRstNode(rnParagraph)
@@ -1491,14 +1406,10 @@ proc dirInclude(p: var TRstParser): PRstNode =
# The text encoding of the external data file. Defaults to the document's
# encoding (if specified).
#
var
n: PRstNode
filename, path: string
q: TRstParser
result = nil
n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
filename = strip(addNodes(n.sons[0]))
path = findFile(filename)
var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
var filename = strip(addNodes(n.sons[0]))
var path = findFile(filename)
if path == "":
rstMessage(p, errCannotOpenFile, filename)
else:
@@ -1507,6 +1418,7 @@ proc dirInclude(p: var TRstParser): PRstNode =
result = newRstNode(rnLiteralBlock)
addSon(result, newRstNode(rnLeaf, readFile(path)))
else:
var q: TRstParser
initParser(q, p.s)
q.filename = filename
getTokens(readFile(path), false, q.tok) # workaround a GCC bug:
@@ -1515,15 +1427,12 @@ proc dirInclude(p: var TRstParser): PRstNode =
result = parseDoc(q)
proc dirCodeBlock(p: var TRstParser): PRstNode =
var
n: PRstNode
filename, path: string
result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock)
filename = strip(getFieldValue(result, "file"))
var filename = strip(getFieldValue(result, "file"))
if filename != "":
path = findFile(filename)
var path = findFile(filename)
if path == "": rstMessage(p, errCannotOpenFile, filename)
n = newRstNode(rnLiteralBlock)
var n = newRstNode(rnLiteralBlock)
addSon(n, newRstNode(rnLeaf, readFile(path)))
result.sons[2] = n
result.kind = rnCodeBlock
@@ -1567,28 +1476,23 @@ proc dirRaw(p: var TRstParser): PRstNode =
# The text encoding of the external raw data (file or URL).
# Defaults to the document's encoding (if specified).
#
var filename, path, f: string
result = parseDirective(p, {hasOptions}, parseSectionWrapper)
result.kind = rnRaw
filename = getFieldValue(result, "file")
var filename = getFieldValue(result, "file")
if filename != "":
path = findFile(filename)
var path = findFile(filename)
if path == "":
rstMessage(p, errCannotOpenFile, filename)
else:
f = readFile(path)
var f = readFile(path)
result = newRstNode(rnRaw)
addSon(result, newRstNode(rnLeaf, f))
proc parseDotDot(p: var TRstParser): PRstNode =
var
d: string
col: int
a, b: PRstNode
result = nil
col = p.tok[p.idx].col
var col = p.tok[p.idx].col
inc(p.idx)
d = getDirective(p)
var d = getDirective(p)
if d != "":
pushInd(p, col)
case getDirKind(d)
@@ -1606,14 +1510,15 @@ proc parseDotDot(p: var TRstParser): PRstNode =
elif match(p, p.idx, " _"):
# hyperlink target:
inc(p.idx, 2)
a = getReferenceName(p, ":")
var a = getReferenceName(p, ":")
if p.tok[p.idx].kind == tkWhite: inc(p.idx)
b = untilEol(p)
var b = untilEol(p)
setRef(p, rstnodeToRefname(a), b)
elif match(p, p.idx, " |"):
# substitution definitions:
inc(p.idx, 2)
a = getReferenceName(p, "|")
var a = getReferenceName(p, "|")
var b: PRstNode
if p.tok[p.idx].kind == tkWhite: inc(p.idx)
if cmpIgnoreStyle(p.tok[p.idx].symbol, "replace") == 0:
inc(p.idx)
@@ -1628,32 +1533,28 @@ proc parseDotDot(p: var TRstParser): PRstNode =
elif match(p, p.idx, " ["):
# footnotes, citations
inc(p.idx, 2)
a = getReferenceName(p, "]")
var a = getReferenceName(p, "]")
if p.tok[p.idx].kind == tkWhite: inc(p.idx)
b = untilEol(p)
var b = untilEol(p)
setRef(p, rstnodeToRefname(a), b)
else:
result = parseComment(p)
proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode =
var
x: int
y: PRstNode
e, key: string
result = n
if n == nil: return
case n.kind
of rnSubstitutionReferences:
x = findSub(p, n)
var x = findSub(p, n)
if x >= 0:
result = p.s.subs[x].value
else:
key = addNodes(n)
e = getEnv(key)
var key = addNodes(n)
var e = getEnv(key)
if e != "": result = newRstNode(rnLeaf, e)
else: rstMessage(p, warnUnknownSubstitutionX, key)
of rnRef:
y = findRef(p, rstnodeToRefname(n))
var y = findRef(p, rstnodeToRefname(n))
if y != nil:
result = newRstNode(rnHyperlink)
n.kind = rnInner

View File

@@ -139,18 +139,22 @@ proc fillToken*(L: var TToken)
proc isKeyword(kind: TTokType): bool =
result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
proc isNimrodIdentifier*(s: string): bool =
if s[0] in SymStartChars:
for c in items(s):
if c notin SymChars: return
result = true
proc pushInd(L: var TLexer, indent: int) =
var length: int
length = len(L.indentStack)
var length = len(L.indentStack)
setlen(L.indentStack, length + 1)
if (indent > L.indentStack[length - 1]):
L.indentstack[length] = indent
else:
InternalError("pushInd") #writeln('push indent ', indent);
InternalError("pushInd")
proc popInd(L: var TLexer) =
var length: int
length = len(L.indentStack)
var length = len(L.indentStack)
setlen(L.indentStack, length - 1)
proc findIdent(L: TLexer, indent: int): bool =
@@ -161,12 +165,9 @@ proc findIdent(L: TLexer, indent: int): bool =
proc tokToStr(tok: PToken): string =
case tok.tokType
of tkIntLit..tkInt64Lit:
result = $(tok.iNumber)
of tkFloatLit..tkFloat64Lit:
result = $(tok.fNumber)
of tkInvalid, tkStrLit..tkCharLit, tkComment:
result = tok.literal
of tkIntLit..tkInt64Lit: result = $tok.iNumber
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
of tkParLe..tkColon, tkEof, tkInd, tkSad, tkDed, tkAccent:
result = tokTypeToStr[tok.tokType]
else:
@@ -194,7 +195,7 @@ proc fillToken(L: var TToken) =
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream)
lex.indentStack = @ [0]
lex.indentStack = @[0]
lex.filename = filename
lex.indentAhead = - 1

View File

@@ -51,7 +51,9 @@ type
wLinksys, wDeprecated, wVarargs, wByref, wCallconv, wBreakpoint, wDebugger,
wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wW,
wBoundchecks, wOverflowchecks, wNilchecks,
wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wWarnings, wW,
wHints, wOptimization, wSpeed, wSize, wNone, wPath, wP, wD, wU, wDebuginfo,
wCompileonly, wNolinking, wForcebuild, wF, wDeadCodeElim, wSafecode,
wCompileTime, wGc, wRefc, wBoehm, wA, wOpt, wO, wApp, wConsole, wGui,
@@ -100,7 +102,10 @@ const
"byref", "callconv", "breakpoint", "debugger", "nimcall", "stdcall",
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure",
"noconv", "on", "off", "checks", "rangechecks", "boundchecks",
"overflowchecks", "nilchecks", "assertions", "warnings", "w", "hints",
"overflowchecks", "nilchecks",
"floatchecks", "nanchecks", "infchecks",
"assertions", "warnings", "w", "hints",
"optimization", "speed", "size", "none", "path", "p", "d", "u", "debuginfo",
"compileonly", "nolinking", "forcebuild", "f", "deadcodeelim", "safecode",
"compiletime", "gc", "refc", "boehm", "a", "opt", "o", "app", "console",

5
start.bat Executable file
View File

@@ -0,0 +1,5 @@
@echo off
REM COLOR 0A
SET NIMRODPATH=.
SET PATH=%NIMRODPATH%\bin;%NIMRODPATH%\dist\mingw\bin;%PATH%
cmd

1
tests/99bottles.nim Executable file
View File

@@ -0,0 +1 @@
# Test if the compiler detects invalid module names

8
tests/tfloat1.nim Executable file
View File

@@ -0,0 +1,8 @@
# Test new floating point exceptions
{.floatChecks: on.}
var x = 0.8
var y = 0.0
echo x / y #OUT Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]

8
tests/tfloat2.nim Executable file
View File

@@ -0,0 +1,8 @@
# Test new floating point exceptions
{.floatChecks: on.}
var x = 0.0
var y = 0.0
echo x / y #OUT Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]