mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-15 15:44:14 +00:00
floating point checks
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.}
|
||||
|
||||
@@ -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,
|
||||
|
||||
195
rod/ccgexprs.nim
195
rod/ccgexprs.nim
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
23
rod/expand_importc.nim
Executable 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 ""
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
13
rod/main.nim
13
rod/main.nim
@@ -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)
|
||||
|
||||
@@ -9,3 +9,4 @@
|
||||
@elif vcc:
|
||||
# cgen.speed = ""
|
||||
@end
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
325
rod/rst.nim
325
rod/rst.nim
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
5
start.bat
Executable 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
1
tests/99bottles.nim
Executable file
@@ -0,0 +1 @@
|
||||
# Test if the compiler detects invalid module names
|
||||
8
tests/tfloat1.nim
Executable file
8
tests/tfloat1.nim
Executable 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
8
tests/tfloat2.nim
Executable 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]
|
||||
Reference in New Issue
Block a user