bug concerning constant evaluation fixed

This commit is contained in:
Andreas Rumpf 2009-11-26 00:32:07 +01:00
commit 196ef92c86
14 changed files with 296 additions and 245 deletions

View file

@ -1,9 +1,9 @@
Advanced commands:: Advanced commands::
pas convert a Pascal file to Nimrod syntax pas convert a Pascal file to Nimrod syntax
pretty pretty print the inputfile pretty pretty print the inputfile
gen_depend generate a DOT file containing the genDepend generate a DOT file containing the
module dependency graph module dependency graph
list_def list all defined conditionals and exit listDef list all defined conditionals and exit
check checks the project for syntax and semantic check checks the project for syntax and semantic
parse parses a single file (for debugging Nimrod) parse parses a single file (for debugging Nimrod)
Advanced options: Advanced options:
@ -12,27 +12,27 @@ Advanced options:
--hints:on|off hints ON|OFF --hints:on|off hints ON|OFF
--hint[X]:on|off specific hint X ON|OFF --hint[X]:on|off specific hint X ON|OFF
--lib:PATH set the system library path --lib:PATH set the system library path
-c, --compile_only compile only; do not assemble or link -c, --compileOnly compile only; do not assemble or link
--no_linking compile but do not link --noLinking compile but do not link
--no_main do not generate a main procedure --noMain do not generate a main procedure
--gen_script generate a compile script (in the 'nimcache' --genScript generate a compile script (in the 'nimcache'
subdirectory named 'compile_$project$scriptext') subdirectory named 'compile_$project$scriptext')
--os:SYMBOL set the target operating system (cross-compilation) --os:SYMBOL set the target operating system (cross-compilation)
--cpu:SYMBOL set the target processor (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation)
--debuginfo enables debug information --debuginfo enables debug information
-t, --passc:OPTION pass an option to the C compiler -t, --passc:OPTION pass an option to the C compiler
-l, --passl:OPTION pass an option to the linker -l, --passl:OPTION pass an option to the linker
--gen_mapping generate a mapping file containing --genMapping generate a mapping file containing
(Nimrod, mangled) identifier pairs (Nimrod, mangled) identifier pairs
--line_dir:on|off generation of #line directive ON|OFF --lineDir:on|off generation of #line directive ON|OFF
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
--skip_cfg do not read the general configuration file --skipCfg do not read the general configuration file
--skip_proj_cfg do not read the project's configuration file --skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
--index:FILE use FILE to generate a documenation index file --index:FILE use FILE to generate a documenation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable
--list_cmd list the commands used to execute external programs --listCmd list the commands used to execute external programs
--parallel_build=0|1|... perform a parallel build --parallelBuild=0|1|... perform a parallel build
value = number of processors (0 for auto-detect) value = number of processors (0 for auto-detect)
--verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default) --verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default)
-v, --version show detailed version information -v, --version show detailed version information

View file

@ -2,7 +2,7 @@ Usage::
nimrod command [options] inputfile [arguments] nimrod command [options] inputfile [arguments]
Command:: Command::
compile, c compile project with default code generator (C) compile, c compile project with default code generator (C)
compile_to_c, cc compile project with C code generator compileToC, cc compile project with C code generator
doc generate the documentation for inputfile doc generate the documentation for inputfile
rst2html converts a reStructuredText file to HTML rst2html converts a reStructuredText file to HTML
rst2tex converts a reStructuredText file to TeX rst2tex converts a reStructuredText file to TeX
@ -13,19 +13,19 @@ Options:
-o, --out:FILE set the output filename -o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
-f, --force_build force rebuilding of all modules -f, --forceBuild force rebuilding of all modules
--symbol_files:on|off use symbol files to speed up compilation (buggy!) --symbolFiles:on|off use symbol files to speed up compilation (buggy!)
--stack_trace:on|off code generation for stack trace ON|OFF --stackTrace:on|off code generation for stack trace ON|OFF
--line_trace:on|off code generation for line trace ON|OFF --lineTrace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF --debugger:on|off turn Embedded Nimrod Debugger ON|OFF
-x, --checks:on|off code generation for all runtime checks ON|OFF -x, --checks:on|off code generation for all runtime checks ON|OFF
--obj_checks:on|off code generation for obj conversion checks ON|OFF --objChecks:on|off code generation for obj conversion checks ON|OFF
--field_checks:on|off code generation for case variant fields ON|OFF --fieldChecks:on|off code generation for case variant fields ON|OFF
--range_checks:on|off code generation for range checks ON|OFF --rangeChecks:on|off code generation for range checks ON|OFF
--bound_checks:on|off code generation for bound checks ON|OFF --boundChecks:on|off code generation for bound checks ON|OFF
--overflow_checks:on|off code generation for over-/underflow checks ON|OFF --overflowChecks:on|off code generation for over-/underflow checks ON|OFF
-a, --assertions:on|off code generation for assertions ON|OFF -a, --assertions:on|off code generation for assertions ON|OFF
--dead_code_elim:on|off whole program dead code elimination ON|OFF --deadCodeElim:on|off whole program dead code elimination ON|OFF
--opt:none|speed|size optimize not at all or for speed|size --opt:none|speed|size optimize not at all or for speed|size
--app:console|gui|lib generate a console|GUI application|dynamic library --app:console|gui|lib generate a console|GUI application|dynamic library
-r, --run run the compiled program with given arguments -r, --run run the compiled program with given arguments

View file

@ -29,12 +29,11 @@ Path Purpose
version version
``data`` data files that are used for generating source ``data`` data files that are used for generating source
code code
``doc`` the documentation lives here; it is a bunch of ``doc`` the documentation; it is a bunch of
reStructuredText files reStructuredText files
``dist`` additional packages for the distribution ``dist`` additional packages for the distribution
``config`` configuration files for Nimrod ``config`` configuration files for Nimrod
``lib`` the Nimrod library lives here; ``rod`` depends ``lib`` the Nimrod library; ``rod`` depends on it!
on it!
``web`` website of Nimrod; generated by ``koch.py`` ``web`` website of Nimrod; generated by ``koch.py``
from the ``*.txt`` and ``*.tmpl`` files from the ``*.txt`` and ``*.tmpl`` files
``obj`` generated ``*.obj`` files ``obj`` generated ``*.obj`` files
@ -183,7 +182,7 @@ I use the term *cell* here to refer to everything that is traced
This section describes how the new GC works. This section describes how the new GC works.
The basic algorithm is *Deferrent Reference Counting* with cycle detection. The basic algorithm is *Deferrent Reference Counting* with cycle detection.
References in the stack are not counted for better performance and easier C References on the stack are not counted for better performance and easier C
code generation. code generation.
Each cell has a header consisting of a RC and a pointer to its type Each cell has a header consisting of a RC and a pointer to its type

View file

@ -666,7 +666,7 @@ The notation ``x[i]`` can be used to access the i-th element of ``x``.
Arrays are always bounds checked (at compile-time or at runtime). These Arrays are always bounds checked (at compile-time or at runtime). These
checks can be disabled via pragmas or invoking the compiler with the checks can be disabled via pragmas or invoking the compiler with the
``--bound_checks:off`` command line switch. ``--boundChecks:off`` command line switch.
An open array is also a means to implement passing a variable number of An open array is also a means to implement passing a variable number of
arguments to a procedure. The compiler converts the list of arguments arguments to a procedure. The compiler converts the list of arguments
@ -2450,11 +2450,11 @@ pragma allowed values description
=============== =============== ============================================ =============== =============== ============================================
checks on|off Turns the code generation for all runtime checks on|off Turns the code generation for all runtime
checks on or off. checks on or off.
bound_checks on|off Turns the code generation for array bound boundChecks on|off Turns the code generation for array bound
checks on or off. checks on or off.
overflow_checks on|off Turns the code generation for over- or overflowChecks on|off Turns the code generation for over- or
underflow checks on or off. underflow checks on or off.
nil_checks on|off Turns the code generation for nil pointer nilChecks on|off Turns the code generation for nil pointer
checks on or off. checks on or off.
assertions on|off Turns the code generation for assertions assertions on|off Turns the code generation for assertions
on or off. on or off.

View file

@ -12,7 +12,7 @@ Introduction
This document describes the usage of the *Nimrod compiler* This document describes the usage of the *Nimrod compiler*
on the different supported platforms. It is not a definition of the Nimrod on the different supported platforms. It is not a definition of the Nimrod
programming language (therefore is the manual). programming language (therefore is the `manual <manual>`_).
Nimrod is free software; it is licensed under the Nimrod is free software; it is licensed under the
`GNU General Public License <gpl.html>`_. `GNU General Public License <gpl.html>`_.
@ -42,7 +42,7 @@ looks for it in the following directories (in this order):
3. ``/etc/nimrod.cfg`` (UNIX) 3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading The search stops as soon as a configuration file has been found. The reading
of ``nimrod.cfg`` can be suppressed by the ``--skip_cfg`` command line option. of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
Configuration settings can be overwritten in a project specific Configuration settings can be overwritten in a project specific
configuration file that is read automatically. This specific file has to configuration file that is read automatically. This specific file has to
be in the same directory as the project and be of the same name, except be in the same directory as the project and be of the same name, except
@ -125,24 +125,24 @@ At runtime the dynamic library is searched for (in this order)::
libtcl8.3.so.0 libtcl8.3.so.0
No_decl Pragma NoDecl Pragma
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The `no_decl`:idx: pragma can be applied to almost any symbol (variable, proc, The `noDecl`:idx: pragma can be applied to almost any symbol (variable, proc,
type, etc.) and is sometimes useful for interoperability with C: type, etc.) and is sometimes useful for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in It tells Nimrod that it should not generate a declaration for the symbol in
the C code. For example: the C code. For example:
.. code-block:: Nimrod .. code-block:: Nimrod
var var
EACCES {.importc, no_decl.}: cint # pretend EACCES was a variable, as EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
# Nimrod does not know its value # Nimrod does not know its value
However, the ``header`` pragma is often the better alternative. However, the ``header`` pragma is often the better alternative.
Header Pragma Header Pragma
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
The `header`:idx: pragma is very similar to the ``no_decl`` pragma: It can be The `header`:idx: pragma is very similar to the ``noDecl`` pragma: It can be
applied to almost any symbol and specifies that it should not be declared applied to almost any symbol and specifies that it should not be declared
and instead the generated code should contain an ``#include``: and instead the generated code should contain an ``#include``:
@ -170,22 +170,23 @@ strings automatically:
printf("hallo %s", "world") # "world" will be passed as C string printf("hallo %s", "world") # "world" will be passed as C string
Line_dir Option LineDir Option
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
The `line_dir`:idx: option can be turned on or off. If on the generated C code The `lineDir`:idx: option can be turned on or off. If turned on the
contains ``#line`` directives. This may be helpful for debugging with GDB. generated C code contains ``#line`` directives. This may be helpful for
debugging with GDB.
Stack_trace Option StackTrace Option
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
If the `stack_trace`:idx: option is turned on, the generated C contains code to If the `stackTrace`:idx: option is turned on, the generated C contains code to
ensure that proper stack traces are given if the program crashes or an ensure that proper stack traces are given if the program crashes or an
uncaught exception is raised. uncaught exception is raised.
Line_trace Option LineTrace Option
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
The `line_trace`:idx: option implies the ``stack_trace`` option. If turned on, The `lineTrace`:idx: option implies the ``stackTrace`` option. If turned on,
the generated C contains code to ensure that proper stack traces with line the generated C contains code to ensure that proper stack traces with line
number information are given if the program crashes or an uncaught exception number information are given if the program crashes or an uncaught exception
is raised. is raised.
@ -239,21 +240,21 @@ information that this cannot happen to the GC. If the programmer uses the
memory, but nothing worse happens. memory, but nothing worse happens.
Dead_code_elim Pragma DeadCodeElim Pragma
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
The `dead_code_elim`:idx: pragma only applies to whole modules: It tells the The `deadCodeElim`:idx: pragma only applies to whole modules: It tells the
compiler to activate (or deactivate) dead code elimination for the module the compiler to activate (or deactivate) dead code elimination for the module the
pragma appers in. pragma appers in.
The ``--dead_code_elim:on`` command line switch has the same effect as marking The ``--deadCodeElim:on`` command line switch has the same effect as marking
every module with ``{.dead_code_elim:on}``. However, for some modules such as every module with ``{.deadCodeElim:on}``. However, for some modules such as
the GTK wrapper it makes sense to *always* turn on dead code elimination - the GTK wrapper it makes sense to *always* turn on dead code elimination -
no matter if it is globally active or not. no matter if it is globally active or not.
Example: Example:
.. code-block:: nimrod .. code-block:: nimrod
{.dead_code_elim: on.} {.deadCodeElim: on.}
Disabling certain messages Disabling certain messages

View file

@ -4,11 +4,20 @@
import strutils, postgres import strutils, postgres
type type
TDbHandle* = PGconn TDbConn* = PPGconn ## encapsulates a database connection
TRow* = seq[string] TRow* = seq[string] ## a row of a dataset
EDb* = object of EIO EDb* = object of EIO ## exception that is raised if a database error occurs
proc dbError(db: TDbHandle) {.noreturn.} = TSqlQuery* = distinct string ## an SQL query string
proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
## constructs a TSqlQuery from the string `query`: If assertions are turned
## off, it does nothing. If assertions are turned on, the string is checked
## for SQL security holes. This is supposed to be used as a
## raw-string-literal modifier: ``sql"update user set counter = counter + 1"``
result = TSqlQuery(query)
proc dbError(db: TDbConn) {.noreturn.} =
## raises an EDb exception. ## raises an EDb exception.
var e: ref EDb var e: ref EDb
new(e) new(e)
@ -23,13 +32,13 @@ proc dbError*(msg: string) {.noreturn.} =
raise e raise e
when false: when false:
proc dbQueryOpt*(db: TDbHandle, query: string, args: openarray[string]) = proc dbQueryOpt*(db: TDbConn, query: string, args: openarray[string]) =
var stmt = mysql_stmt_init(db) var stmt = mysql_stmt_init(db)
if stmt == nil: dbError(db) if stmt == nil: dbError(db)
if mysql_stmt_prepare(stmt, query, len(query)) != 0: if mysql_stmt_prepare(stmt, query, len(query)) != 0:
dbError(db) dbError(db)
var var
bind: seq[MYSQL_BIND] bindings: seq[MYSQL_BIND]
discard mysql_stmt_close(stmt) discard mysql_stmt_close(stmt)
proc dbQuote(s: string): string = proc dbQuote(s: string): string =
@ -39,91 +48,123 @@ proc dbQuote(s: string): string =
else: add(result, c) else: add(result, c)
add(result, '\'') add(result, '\'')
proc dbFormat(formatstr: string, args: openarray[string]): string = proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
result = "" result = ""
var a = 0 var a = 0
for c in items(formatstr): for c in items(string(formatstr)):
if c == '?': if c == '?':
add(result, dbQuote(args[a])) add(result, dbQuote(args[a]))
inc(a) inc(a)
else: else:
add(result, c) add(result, c)
proc dbTryQuery*(db: TDbHandle, query: string, args: openarray[string]): bool = proc dbTryQuery*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): bool =
## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
var res = PQExec(db, q) var res = PQExec(db, q)
result = PQresultStatus(res) == PGRES_COMMAND_OK result = PQresultStatus(res) == PGRES_COMMAND_OK
PQclear(res) PQclear(res)
proc dbQuery*(db: TDbHandle, query: string, args: openarray[string]) = proc dbQuery*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
var res = PQExec(db, q) var res = PQExec(db, q)
if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db) if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
PQclear(res) PQclear(res)
proc dbTryInsertID*(db: TDbHandle, query: string,
args: openarray[string]): int64 =
var q = dbFormat(query, args)
if mysqlRealQuery(db, q, q.len) != 0'i32:
result = -1'i64
else:
result = mysql_insert_id(db)
LAST_INSERT_ID()
proc dbInsertID*(db: TDbHandle, query: string, args: openArray[string]): int64 =
result = dbTryInsertID(db, query, args)
if result < 0: dbError(db)
proc dbQueryAffectedRows*(db: TDbHandle, query: string,
args: openArray[string]): int64 =
## runs the query (typically "UPDATE") and returns the
## number of affected rows
var q = dbFormat(query, args)
var res = PQExec(db, q)
if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
result = parseBiggestInt($PQcmdTuples(res))
PQclear(res)
proc newRow(L: int): TRow = proc newRow(L: int): TRow =
newSeq(result, L) newSeq(result, L)
for i in 0..L-1: result[i] = "" for i in 0..L-1: result[i] = ""
iterator dbFastRows*(db: TDbHandle, query: string, proc setupQuery(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow = args: openarray[string]): PPGresult =
var q = dbFormat(query, args) var q = dbFormat(query, args)
var res = PQExec(db, q) result = PQExec(db, q)
if PQresultStatus(res) != PGRES_TUPLES_OK: dbError(db) if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
proc setRow(res: PPGresult, r: var TRow, line, cols: int) =
for col in 0..cols-1:
setLen(r[col], 0)
add(r[col], PQgetvalue(res, line, cols))
iterator dbFastRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow =
## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though.
var res = setupQuery(db, query, args)
var L = int(PQnfields(res)) var L = int(PQnfields(res))
var result = newRow(L) var result = newRow(L)
for i in 0..PQntuples(res)-1: for i in 0..PQntuples(res)-1:
for j in 0..L-1: setRow(res, result, i, L)
setLen(result[j], 0)
add(result[j], PQgetvalue(res, i, j))
yield result yield result
PQclear(res) PQclear(res)
proc dbGetAllRows*(db: TDbHandle, query: string, proc dbGetAllRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): seq[TRow] = args: openarray[string]): seq[TRow] =
## executes the query and returns the whole result dataset.
result = @[] result = @[]
for r in dbFastRows(db, query, args): for r in dbFastRows(db, query, args):
result.add(r) result.add(r)
iterator dbRows*(db: TDbHandle, query: string, iterator dbRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow = args: openarray[string]): TRow =
## same as `dbFastRows`, but slower and safe.
for r in items(dbGetAllRows(db, query, args)): yield r for r in items(dbGetAllRows(db, query, args)): yield r
proc dbGetValue*(db: TDbHandle, query: string, proc dbGetValue*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): string = args: openarray[string]): string =
## executes the query and returns the result dataset's the first column
## of the first row. Returns "" if the dataset contains no rows. This uses
## `dbFastRows`, so it inherits its fragile behaviour.
result = "" result = ""
for row in dbFastRows(db, query, args): for row in dbFastRows(db, query, args):
result = row[0] result = row[0]
break break
proc dbTryInsertID*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): int64 =
## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error. For Postgre this adds
## ``RETURNING id`` to the query, so it only works if your primary key is
## named ``id``.
var val = dbGetValue(db, TSqlQuery(string(query) & " RETURNING id"), args)
if val.len > 0:
result = ParseBiggestInt(val)
else:
result = -1
#if mysqlRealQuery(db, q, q.len) != 0'i32:
# result = -1'i64
#else:
# result = mysql_insert_id(db)
#LAST_INSERT_ID()
proc dbClose*(db: TDbHandle) = proc dbInsertID*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 =
## executes the query (typically "INSERT") and returns the
## generated ID for the row. For Postgre this adds
## ``RETURNING id`` to the query, so it only works if your primary key is
## named ``id``.
result = dbTryInsertID(db, query, args)
if result < 0: dbError(db)
proc dbQueryAffectedRows*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 =
## executes the query (typically "UPDATE") and returns the
## number of affected rows.
var q = dbFormat(query, args)
var res = PQExec(db, q)
if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
result = parseBiggestInt($PQcmdTuples(res))
PQclear(res)
proc dbClose*(db: TDbConn) =
## closes the database connection.
if db != nil: PQfinish(db) if db != nil: PQfinish(db)
proc dbOpen*(connection, user, password, database: string): TDbHandle = proc dbOpen*(connection, user, password, database: string): TDbConn =
## opens a database connection. Returns nil in case of an error.
result = PQsetdbLogin(nil, nil, nil, nil, database, user, password) result = PQsetdbLogin(nil, nil, nil, nil, database, user, password)
if PQStatus(result) != CONNECTION_OK: result = nil if PQStatus(result) != CONNECTION_OK: dbError(result) # result = nil

View file

@ -43,7 +43,7 @@ proc close*(z: var TZipArchive) =
zip_close(z.w) zip_close(z.w)
proc createDir*(z: var TZipArchive, dir: string) = proc createDir*(z: var TZipArchive, dir: string) =
## Creates a directory within the `z` archive. This does not fails if the ## Creates a directory within the `z` archive. This does not fail if the
## directory already exists. Note that for adding a file like ## directory already exists. Note that for adding a file like
## ``"path1/path2/filename"`` it is not necessary ## ``"path1/path2/filename"`` it is not necessary
## to create the ``"path/path2"`` subdirectories - it will be done ## to create the ``"path/path2"`` subdirectories - it will be done

View file

@ -148,7 +148,7 @@ proc sequence*(a: openArray[TPeg]): TPeg =
multipleOp(pkSequence, addSequence) multipleOp(pkSequence, addSequence)
proc `?`*(a: TPeg): TPeg = proc `?`*(a: TPeg): TPeg =
## constructs an optional piece with the PEG `a` ## constructs an optional for the PEG `a`
if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar, if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
pkGreedyRepSet}: pkGreedyRepSet}:
# a* ? --> a* # a* ? --> a*
@ -159,7 +159,7 @@ proc `?`*(a: TPeg): TPeg =
result.sons = @[a] result.sons = @[a]
proc `*`*(a: TPeg): TPeg = proc `*`*(a: TPeg): TPeg =
## constructs a "greedy repetition" piece the PEG `a` ## constructs a "greedy repetition" for the PEG `a`
case a.kind case a.kind
of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption: of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption:
assert false assert false

View file

@ -224,7 +224,7 @@ proc replace*(s: string, sub: TRegEx, by: string): string =
## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples: ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
## ##
## .. code-block:: nimrod ## .. code-block:: nimrod
## "var1=key; var2=key2".replace(p"{\ident}'='{\ident}", "$1<-$2$2") ## "var1=key; var2=key2".replace(re"{\ident}'='{\ident}", "$1<-$2$2")
## ##
## Results in: ## Results in:
## ##

View file

@ -41,10 +41,10 @@ proc writeProfile() {.noconv.} =
var i = 0 var i = 0
var f: TFile var f: TFile
var j = 1 var j = 1
while openFile(f, filename & $j & ".txt"): while open(f, filename & $j & ".txt"):
closeFile(f) close(f)
inc(j) inc(j)
if openFile(f, filename & $j & ".txt", fmWrite): if open(f, filename & $j & ".txt", fmWrite):
var N = 0 var N = 0
# we have to compute the actual length of the array: # we have to compute the actual length of the array:
while profileData[N].procname != nil: inc(N) while profileData[N].procname != nil: inc(N)
@ -56,6 +56,6 @@ proc writeProfile() {.noconv.} =
write(f, ": ") write(f, ": ")
writeln(f, profileData[i].total) writeln(f, profileData[i].total)
inc(i) inc(i)
closeFile(f) close(f)
addQuitProc(writeProfile) addQuitProc(writeProfile)

View file

@ -11,7 +11,7 @@ when defined(windows):
elif defined(macosx): elif defined(macosx):
const dllName = "libpq.dylib" const dllName = "libpq.dylib"
else: else:
const dllName = "libpq.so" const dllName = "libpq.so(.5|)"
type type
POid* = ptr Oid POid* = ptr Oid

View file

@ -60,7 +60,7 @@ const
+{&} ' nimrod command [options] inputfile [arguments]' +{&} nl +{&} ' nimrod command [options] inputfile [arguments]' +{&} nl
+{&} 'Command::' +{&} nl +{&} 'Command::' +{&} nl
+{&} ' compile, c compile project with default code generator (C)' +{&} nl +{&} ' compile, c compile project with default code generator (C)' +{&} nl
+{&} ' compile_to_c, cc compile project with C code generator' +{&} nl +{&} ' compileToC, cc compile project with C code generator' +{&} nl
+{&} ' doc generate the documentation for inputfile' +{&} nl +{&} ' doc generate the documentation for inputfile' +{&} nl
+{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl +{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl
+{&} ' rst2tex converts a reStructuredText file to TeX' +{&} nl +{&} ' rst2tex converts a reStructuredText file to TeX' +{&} nl
@ -71,19 +71,19 @@ const
+{&} ' -o, --out:FILE set the output filename' +{&} nl +{&} ' -o, --out:FILE set the output filename' +{&} nl
+{&} ' -d, --define:SYMBOL define a conditional symbol' +{&} nl +{&} ' -d, --define:SYMBOL define a conditional symbol' +{&} nl
+{&} ' -u, --undef:SYMBOL undefine a conditional symbol' +{&} nl +{&} ' -u, --undef:SYMBOL undefine a conditional symbol' +{&} nl
+{&} ' -f, --force_build force rebuilding of all modules' +{&} nl +{&} ' -f, --forceBuild force rebuilding of all modules' +{&} nl
+{&} ' --symbol_files:on|off use symbol files to speed up compilation (buggy!)' +{&} nl +{&} ' --symbolFiles:on|off use symbol files to speed up compilation (buggy!)' +{&} nl
+{&} ' --stack_trace:on|off code generation for stack trace ON|OFF' +{&} nl +{&} ' --stackTrace:on|off code generation for stack trace ON|OFF' +{&} nl
+{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl +{&} ' --lineTrace:on|off code generation for line trace ON|OFF' +{&} nl
+{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl +{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl
+{&} ' -x, --checks:on|off code generation for all runtime checks ON|OFF' +{&} nl +{&} ' -x, --checks:on|off code generation for all runtime checks ON|OFF' +{&} nl
+{&} ' --obj_checks:on|off code generation for obj conversion checks ON|OFF' +{&} nl +{&} ' --objChecks:on|off code generation for obj conversion checks ON|OFF' +{&} nl
+{&} ' --field_checks:on|off code generation for case variant fields ON|OFF' +{&} nl +{&} ' --fieldChecks:on|off code generation for case variant fields ON|OFF' +{&} nl
+{&} ' --range_checks:on|off code generation for range checks ON|OFF' +{&} nl +{&} ' --rangeChecks:on|off code generation for range checks ON|OFF' +{&} nl
+{&} ' --bound_checks:on|off code generation for bound checks ON|OFF' +{&} nl +{&} ' --boundChecks:on|off code generation for bound checks ON|OFF' +{&} nl
+{&} ' --overflow_checks:on|off code generation for over-/underflow checks ON|OFF' +{&} nl +{&} ' --overflowChecks:on|off code generation for over-/underflow checks ON|OFF' +{&} nl
+{&} ' -a, --assertions:on|off code generation for assertions ON|OFF' +{&} nl +{&} ' -a, --assertions:on|off code generation for assertions ON|OFF' +{&} nl
+{&} ' --dead_code_elim:on|off whole program dead code elimination ON|OFF' +{&} nl +{&} ' --deadCodeElim:on|off whole program dead code elimination ON|OFF' +{&} nl
+{&} ' --opt:none|speed|size optimize not at all or for speed|size' +{&} nl +{&} ' --opt:none|speed|size optimize not at all or for speed|size' +{&} nl
+{&} ' --app:console|gui|lib generate a console|GUI application|dynamic library' +{&} nl +{&} ' --app:console|gui|lib generate a console|GUI application|dynamic library' +{&} nl
+{&} ' -r, --run run the compiled program with given arguments' +{&} nl +{&} ' -r, --run run the compiled program with given arguments' +{&} nl
@ -100,9 +100,9 @@ const
+{&} 'Advanced commands::' +{&} nl +{&} 'Advanced commands::' +{&} nl
+{&} ' pas convert a Pascal file to Nimrod syntax' +{&} nl +{&} ' pas convert a Pascal file to Nimrod syntax' +{&} nl
+{&} ' pretty pretty print the inputfile' +{&} nl +{&} ' pretty pretty print the inputfile' +{&} nl
+{&} ' gen_depend generate a DOT file containing the' +{&} nl +{&} ' genDepend generate a DOT file containing the' +{&} nl
+{&} ' module dependency graph' +{&} nl +{&} ' module dependency graph' +{&} nl
+{&} ' list_def list all defined conditionals and exit' +{&} nl +{&} ' listDef list all defined conditionals and exit' +{&} nl
+{&} ' check checks the project for syntax and semantic' +{&} nl +{&} ' check checks the project for syntax and semantic' +{&} nl
+{&} ' parse parses a single file (for debugging Nimrod)' +{&} nl +{&} ' parse parses a single file (for debugging Nimrod)' +{&} nl
+{&} 'Advanced options:' +{&} nl +{&} 'Advanced options:' +{&} nl
@ -111,27 +111,27 @@ const
+{&} ' --hints:on|off hints ON|OFF' +{&} nl +{&} ' --hints:on|off hints ON|OFF' +{&} nl
+{&} ' --hint[X]:on|off specific hint X ON|OFF' +{&} nl +{&} ' --hint[X]:on|off specific hint X ON|OFF' +{&} nl
+{&} ' --lib:PATH set the system library path' +{&} nl +{&} ' --lib:PATH set the system library path' +{&} nl
+{&} ' -c, --compile_only compile only; do not assemble or link' +{&} nl +{&} ' -c, --compileOnly compile only; do not assemble or link' +{&} nl
+{&} ' --no_linking compile but do not link' +{&} nl +{&} ' --noLinking compile but do not link' +{&} nl
+{&} ' --no_main do not generate a main procedure' +{&} nl +{&} ' --noMain do not generate a main procedure' +{&} nl
+{&} ' --gen_script generate a compile script (in the ''nimcache''' +{&} nl +{&} ' --genScript generate a compile script (in the ''nimcache''' +{&} nl
+{&} ' subdirectory named ''compile_$project$scriptext'')' +{&} nl +{&} ' subdirectory named ''compile_$project$scriptext'')' +{&} nl
+{&} ' --os:SYMBOL set the target operating system (cross-compilation)' +{&} nl +{&} ' --os:SYMBOL set the target operating system (cross-compilation)' +{&} nl
+{&} ' --cpu:SYMBOL set the target processor (cross-compilation)' +{&} nl +{&} ' --cpu:SYMBOL set the target processor (cross-compilation)' +{&} nl
+{&} ' --debuginfo enables debug information' +{&} nl +{&} ' --debuginfo enables debug information' +{&} nl
+{&} ' -t, --passc:OPTION pass an option to the C compiler' +{&} nl +{&} ' -t, --passc:OPTION pass an option to the C compiler' +{&} nl
+{&} ' -l, --passl:OPTION pass an option to the linker' +{&} nl +{&} ' -l, --passl:OPTION pass an option to the linker' +{&} nl
+{&} ' --gen_mapping generate a mapping file containing' +{&} nl +{&} ' --genMapping generate a mapping file containing' +{&} nl
+{&} ' (Nimrod, mangled) identifier pairs' +{&} nl +{&} ' (Nimrod, mangled) identifier pairs' +{&} nl
+{&} ' --line_dir:on|off generation of #line directive ON|OFF' +{&} nl +{&} ' --lineDir:on|off generation of #line directive ON|OFF' +{&} nl
+{&} ' --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod' +{&} nl +{&} ' --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod' +{&} nl
+{&} ' --skip_cfg do not read the general configuration file' +{&} nl +{&} ' --skipCfg do not read the general configuration file' +{&} nl
+{&} ' --skip_proj_cfg do not read the project''s configuration file' +{&} nl +{&} ' --skipProjCfg do not read the project''s configuration file' +{&} nl
+{&} ' --gc:refc|boehm|none use Nimrod''s native GC|Boehm GC|no GC' +{&} nl +{&} ' --gc:refc|boehm|none use Nimrod''s native GC|Boehm GC|no GC' +{&} nl
+{&} ' --index:FILE use FILE to generate a documenation index file' +{&} nl +{&} ' --index:FILE use FILE to generate a documenation index file' +{&} nl
+{&} ' --putenv:key=value set an environment variable' +{&} nl +{&} ' --putenv:key=value set an environment variable' +{&} nl
+{&} ' --list_cmd list the commands used to execute external programs' +{&} nl +{&} ' --listCmd list the commands used to execute external programs' +{&} nl
+{&} ' --parallel_build=0|1|... perform a parallel build' +{&} nl +{&} ' --parallelBuild=0|1|... perform a parallel build' +{&} nl
+{&} ' value = number of processors (0 for auto-detect)' +{&} nl +{&} ' value = number of processors (0 for auto-detect)' +{&} nl
+{&} ' --verbosity:0|1|2|3 set Nimrod''s verbosity level (0 is default)' +{&} nl +{&} ' --verbosity:0|1|2|3 set Nimrod''s verbosity level (0 is default)' +{&} nl
+{&} ' -v, --version show detailed version information' +{&} nl +{&} ' -v, --version show detailed version information' +{&} nl
@ -180,7 +180,8 @@ begin
helpWritten := true; helpWritten := true;
messageOut(format(HelpMessage, [VersionAsString, messageOut(format(HelpMessage, [VersionAsString,
platform.os[platform.hostOS].name, platform.os[platform.hostOS].name,
cpu[platform.hostCPU].name])) cpu[platform.hostCPU].name]));
halt(0);
end end
end; end;

View file

@ -117,6 +117,11 @@ begin
liMessage(n.info, msg, arg); liMessage(n.info, msg, arg);
end; end;
function isSpecial(n: PNode): bool;
begin
result := (n.kind = nkExceptBranch) or (n.kind = nkEmpty)
end;
function evalIf(c: PEvalContext; n: PNode): PNode; function evalIf(c: PEvalContext; n: PNode): PNode;
var var
i, len: int; i, len: int;
@ -125,7 +130,7 @@ begin
len := sonsLen(n); len := sonsLen(n);
while (i < len) and (sonsLen(n.sons[i]) >= 2) do begin while (i < len) and (sonsLen(n.sons[i]) >= 2) do begin
result := evalAux(c, n.sons[i].sons[0]); result := evalAux(c, n.sons[i].sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if (result.kind = nkIntLit) and (result.intVal <> 0) then begin if (result.kind = nkIntLit) and (result.intVal <> 0) then begin
result := evalAux(c, n.sons[i].sons[1]); result := evalAux(c, n.sons[i].sons[1]);
exit exit
@ -144,7 +149,7 @@ var
res: PNode; res: PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
res := result; res := result;
result := emptyNode; result := emptyNode;
for i := 1 to sonsLen(n)-1 do begin for i := 1 to sonsLen(n)-1 do begin
@ -173,7 +178,7 @@ function evalWhile(c: PEvalContext; n: PNode): PNode;
begin begin
while true do begin while true do begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if getOrdValue(result) = 0 then break; if getOrdValue(result) = 0 then break;
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
case result.kind of case result.kind of
@ -183,7 +188,7 @@ begin
break break
end end
end; end;
nkExceptBranch, nkReturnToken: break; nkExceptBranch, nkReturnToken, nkEmpty: break;
else begin end else begin end
end; end;
dec(gWhileCounter); dec(gWhileCounter);
@ -314,7 +319,7 @@ begin
v := a.sons[0].sym; v := a.sons[0].sym;
if a.sons[2] <> nil then begin if a.sons[2] <> nil then begin
result := evalAux(c, a.sons[2]); result := evalAux(c, a.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
end end
else else
result := getNullValue(a.sons[0].typ, a.sons[0].info); result := getNullValue(a.sons[0].typ, a.sons[0].info);
@ -330,7 +335,7 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
prc := result; prc := result;
// bind the actual params to the local parameter // bind the actual params to the local parameter
// of a new binding // of a new binding
@ -344,13 +349,13 @@ begin
setLength(d.params, sonsLen(n)); setLength(d.params, sonsLen(n));
for i := 1 to sonsLen(n)-1 do begin for i := 1 to sonsLen(n)-1 do begin
result := evalAux(c, n.sons[i]); result := evalAux(c, n.sons[i]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
d.params[i] := result; d.params[i] := result;
end; end;
if n.typ <> nil then d.params[0] := getNullValue(n.typ, n.info); if n.typ <> nil then d.params[0] := getNullValue(n.typ, n.info);
pushStackFrame(c, d); pushStackFrame(c, d);
result := evalAux(c, prc); result := evalAux(c, prc);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if n.typ <> nil then result := d.params[0]; if n.typ <> nil then result := d.params[0];
popStackFrame(c); popStackFrame(c);
end; end;
@ -380,10 +385,10 @@ var
idx: biggestInt; idx: biggestInt;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x := result; x := result;
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
idx := getOrdValue(result); idx := getOrdValue(result);
result := emptyNode; result := emptyNode;
case x.kind of case x.kind of
@ -416,7 +421,7 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x := result; x := result;
if x.kind <> nkPar then InternalError(n.info, 'evalFieldAccess'); if x.kind <> nkPar then InternalError(n.info, 'evalFieldAccess');
field := n.sons[1].sym; field := n.sons[1].sym;
@ -437,10 +442,10 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x := result; x := result;
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x.kind := result.kind; x.kind := result.kind;
x.typ := result.typ; x.typ := result.typ;
case x.kind of case x.kind of
@ -469,10 +474,10 @@ var
tmpn: PNode; tmpn: PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x := result; x := result;
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if (x.kind <> result.kind) then if (x.kind <> result.kind) then
stackTrace(c, n, errCannotInterpretNodeX, nodeKindToStr[n.kind]) stackTrace(c, n, errCannotInterpretNodeX, nodeKindToStr[n.kind])
else begin else begin
@ -527,10 +532,10 @@ var
a, b: PNode; a, b: PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
case a.kind of case a.kind of
nkCharLit..nkInt64Lit: a.intval := a.intVal + sign * getOrdValue(b); nkCharLit..nkInt64Lit: a.intval := a.intVal + sign * getOrdValue(b);
@ -553,7 +558,7 @@ var
begin begin
for i := 1 to sonsLen(n)-1 do begin for i := 1 to sonsLen(n)-1 do begin
result := evalAux(c, n.sons[i]); result := evalAux(c, n.sons[i]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
Write(output, getStrValue(result)); Write(output, getStrValue(result));
end; end;
writeln(output, ''); writeln(output, '');
@ -563,7 +568,7 @@ end;
function evalExit(c: PEvalContext; n: PNode): PNode; function evalExit(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
liMessage(n.info, hintQuitCalled); liMessage(n.info, hintQuitCalled);
halt(int(getOrdValue(result))); halt(int(getOrdValue(result)));
end; end;
@ -571,7 +576,7 @@ end;
function evalOr(c: PEvalContext; n: PNode): PNode; function evalOr(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if result.kind <> nkIntLit then InternalError(n.info, 'evalOr'); if result.kind <> nkIntLit then InternalError(n.info, 'evalOr');
if result.intVal = 0 then result := evalAux(c, n.sons[2]) if result.intVal = 0 then result := evalAux(c, n.sons[2])
end; end;
@ -579,7 +584,7 @@ end;
function evalAnd(c: PEvalContext; n: PNode): PNode; function evalAnd(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if result.kind <> nkIntLit then InternalError(n.info, 'evalAnd'); if result.kind <> nkIntLit then InternalError(n.info, 'evalAnd');
if result.intVal <> 0 then result := evalAux(c, n.sons[2]) if result.intVal <> 0 then result := evalAux(c, n.sons[2])
end; end;
@ -607,9 +612,8 @@ end;
function evalDeref(c: PEvalContext; n: PNode): PNode; function evalDeref(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
case result.kind of case result.kind of
nkExceptBranch: exit;
nkNilLit: stackTrace(c, n, errNilAccess); nkNilLit: stackTrace(c, n, errNilAccess);
nkRefTy: result := result.sons[0]; nkRefTy: result := result.sons[0];
else InternalError(n.info, 'evalDeref ' + nodeKindToStr[result.kind]); else InternalError(n.info, 'evalDeref ' + nodeKindToStr[result.kind]);
@ -622,7 +626,7 @@ var
t: PType; t: PType;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
t := newType(tyPtr, c.module); t := newType(tyPtr, c.module);
addSon(t, a.typ); addSon(t, a.typ);
@ -647,7 +651,7 @@ var
dest, src: PType; dest, src: PType;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
dest := skipTypes(n.typ, abstractPtrs); dest := skipTypes(n.typ, abstractPtrs);
src := skipTypes(result.typ, abstractPtrs); src := skipTypes(result.typ, abstractPtrs);
if inheritanceDiff(src, dest) > 0 then if inheritanceDiff(src, dest) > 0 then
@ -659,13 +663,13 @@ var
x, a, b: PNode; x, a, b: PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
x := result; x := result;
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
if leValueConv(a, x) and leValueConv(x, b) then begin if leValueConv(a, x) and leValueConv(x, b) then begin
@ -681,14 +685,14 @@ end;
function evalConvStrToCStr(c: PEvalContext; n: PNode): PNode; function evalConvStrToCStr(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result.typ := n.typ; result.typ := n.typ;
end; end;
function evalConvCStrToStr(c: PEvalContext; n: PNode): PNode; function evalConvCStrToStr(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result.typ := n.typ; result.typ := n.typ;
end; end;
@ -698,7 +702,7 @@ var
begin begin
if n.sons[0] <> nil then begin if n.sons[0] <> nil then begin
result := evalAux(c, n.sons[0]); result := evalAux(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkExceptBranch, n.info, a.typ); result := newNodeIT(nkExceptBranch, n.info, a.typ);
addSon(result, a); addSon(result, a);
@ -717,7 +721,7 @@ function evalReturn(c: PEvalContext; n: PNode): PNode;
begin begin
if n.sons[0] <> nil then begin if n.sons[0] <> nil then begin
result := evalAsgn(c, n.sons[0]); result := evalAsgn(c, n.sons[0]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
end; end;
result := newNodeIT(nkReturnToken, n.info, nil); result := newNodeIT(nkReturnToken, n.info, nil);
end; end;
@ -743,7 +747,7 @@ end;
function evalHigh(c: PEvalContext; n: PNode): PNode; function evalHigh(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
case skipTypes(n.sons[1].typ, abstractVar).kind of case skipTypes(n.sons[1].typ, abstractVar).kind of
tyOpenArray, tySequence: tyOpenArray, tySequence:
result := newIntNodeT(sonsLen(result), n); result := newIntNodeT(sonsLen(result), n);
@ -756,7 +760,7 @@ end;
function evalIs(c: PEvalContext; n: PNode): PNode; function evalIs(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result := newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n) result := newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n)
end; end;
@ -766,10 +770,10 @@ var
oldLen, newLen: int; oldLen, newLen: int;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
case a.kind of case a.kind of
nkStrLit..nkTripleStrLit: begin nkStrLit..nkTripleStrLit: begin
@ -793,10 +797,10 @@ var
newLen, oldLen, i: int; newLen, oldLen, i: int;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
if a.kind <> nkBracket then InternalError(n.info, 'evalSetLengthSeq'); if a.kind <> nkBracket then InternalError(n.info, 'evalSetLengthSeq');
newLen := int(getOrdValue(b)); newLen := int(getOrdValue(b));
@ -814,10 +818,10 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
t := skipTypes(n.sons[1].typ, abstractVar); t := skipTypes(n.sons[1].typ, abstractVar);
@ -833,7 +837,7 @@ end;
function evalAssert(c: PEvalContext; n: PNode): PNode; function evalAssert(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if getOrdValue(result) <> 0 then if getOrdValue(result) <> 0 then
result := emptyNode result := emptyNode
else else
@ -845,10 +849,10 @@ var
a, b: PNode; a, b: PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
if not inSet(a, b) then addSon(a, copyTree(b)); if not inSet(a, b) then addSon(a, copyTree(b));
result := emptyNode; result := emptyNode;
@ -860,10 +864,10 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := newNodeIT(nkCurly, n.info, n.sons[1].typ); b := newNodeIT(nkCurly, n.info, n.sons[1].typ);
addSon(b, result); addSon(b, result);
r := diffSets(a, b); r := diffSets(a, b);
@ -877,10 +881,10 @@ var
a, b: PNode; a, b: PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
case a.kind of case a.kind of
nkStrLit..nkTripleStrLit: addChar(a.strVal, chr(int(getOrdValue(b)))); nkStrLit..nkTripleStrLit: addChar(a.strVal, chr(int(getOrdValue(b))));
@ -896,11 +900,11 @@ var
i: int; i: int;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
for i := 2 to sonsLen(n)-1 do begin for i := 2 to sonsLen(n)-1 do begin
result := evalAux(c, n.sons[i]); result := evalAux(c, n.sons[i]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.strVal := getStrValue(a) +{&} getStrValue(result); a.strVal := getStrValue(a) +{&} getStrValue(result);
end; end;
result := a; result := a;
@ -911,10 +915,10 @@ var
a, b: PNode; a, b: PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
case a.kind of case a.kind of
nkStrLit..nkTripleStrLit: a.strVal := a.strVal +{&} getStrValue(b); nkStrLit..nkTripleStrLit: a.strVal := a.strVal +{&} getStrValue(b);
@ -928,10 +932,10 @@ var
a, b: PNode; a, b: PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
if a.kind = nkBracket then addSon(a, copyTree(b)) if a.kind = nkBracket then addSon(a, copyTree(b))
else InternalError(n.info, 'evalAppendSeqElem'); else InternalError(n.info, 'evalAppendSeqElem');
@ -941,10 +945,15 @@ end;
function evalRepr(c: PEvalContext; n: PNode): PNode; function evalRepr(c: PEvalContext; n: PNode): PNode;
begin begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result := newStrNodeT(renderTree(result, {@set}[renderNoComments]), n); result := newStrNodeT(renderTree(result, {@set}[renderNoComments]), n);
end; end;
function isEmpty(n: PNode): bool;
begin
result := (n <> nil) and (n.kind = nkEmpty)
end;
function evalMagicOrCall(c: PEvalContext; n: PNode): PNode; function evalMagicOrCall(c: PEvalContext; n: PNode): PNode;
var var
m: TMagic; m: TMagic;
@ -979,7 +988,7 @@ begin
mNLen: begin mNLen: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkIntLit, n.info, n.typ); result := newNodeIT(nkIntLit, n.info, n.typ);
case a.kind of case a.kind of
@ -989,10 +998,10 @@ begin
end; end;
mNChild: begin mNChild: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
k := getOrdValue(result); k := getOrdValue(result);
if not (a.kind in [nkEmpty..nkNilLit]) and (k >= 0) if not (a.kind in [nkEmpty..nkNilLit]) and (k >= 0)
and (k < sonsLen(a)) then begin and (k < sonsLen(a)) then begin
@ -1006,13 +1015,13 @@ begin
end; end;
mNSetChild: begin mNSetChild: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
result := evalAux(c, n.sons[3]); result := evalAux(c, n.sons[3]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
k := getOrdValue(b); k := getOrdValue(b);
if (k >= 0) and (k < sonsLen(a)) if (k >= 0) and (k < sonsLen(a))
and not (a.kind in [nkEmpty..nkNilLit]) then begin and not (a.kind in [nkEmpty..nkNilLit]) then begin
@ -1025,45 +1034,45 @@ begin
end; end;
mNAdd: begin mNAdd: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
addSon(a, result); addSon(a, result);
result := emptyNode result := emptyNode
end; end;
mNAddMultiple: begin mNAddMultiple: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
for i := 0 to sonsLen(result)-1 do addSon(a, result.sons[i]); for i := 0 to sonsLen(result)-1 do addSon(a, result.sons[i]);
result := emptyNode result := emptyNode
end; end;
mNDel: begin mNDel: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
result := evalAux(c, n.sons[3]); result := evalAux(c, n.sons[3]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
for i := 0 to int(getOrdValue(result))-1 do for i := 0 to int(getOrdValue(result))-1 do
delSon(a, int(getOrdValue(b))); delSon(a, int(getOrdValue(b)));
result := emptyNode; result := emptyNode;
end; end;
mNKind: begin mNKind: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkIntLit, n.info, n.typ); result := newNodeIT(nkIntLit, n.info, n.typ);
result.intVal := ord(a.kind); result.intVal := ord(a.kind);
end; end;
mNIntVal: begin mNIntVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkIntLit, n.info, n.typ); result := newNodeIT(nkIntLit, n.info, n.typ);
case a.kind of case a.kind of
@ -1073,7 +1082,7 @@ begin
end; end;
mNFloatVal: begin mNFloatVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkFloatLit, n.info, n.typ); result := newNodeIT(nkFloatLit, n.info, n.typ);
case a.kind of case a.kind of
@ -1083,18 +1092,18 @@ begin
end; end;
mNSymbol: begin mNSymbol: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if result.kind <> nkSym then InternalError(n.info, 'no symbol') if result.kind <> nkSym then InternalError(n.info, 'no symbol')
end; end;
mNIdent: begin mNIdent: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if result.kind <> nkIdent then InternalError(n.info, 'no symbol') if result.kind <> nkIdent then InternalError(n.info, 'no symbol')
end; end;
mNGetType: result := evalAux(c, n.sons[1]); mNGetType: result := evalAux(c, n.sons[1]);
mNStrVal: begin mNStrVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkStrLit, n.info, n.typ); result := newNodeIT(nkStrLit, n.info, n.typ);
case a.kind of case a.kind of
@ -1104,64 +1113,64 @@ begin
end; end;
mNSetIntVal: begin mNSetIntVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.intVal := result.intVal; // XXX: exception handling? a.intVal := result.intVal; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNSetFloatVal: begin mNSetFloatVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.floatVal := result.floatVal; // XXX: exception handling? a.floatVal := result.floatVal; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNSetSymbol: begin mNSetSymbol: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.sym := result.sym; // XXX: exception handling? a.sym := result.sym; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNSetIdent: begin mNSetIdent: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.ident := result.ident; // XXX: exception handling? a.ident := result.ident; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNSetType: begin mNSetType: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.typ := result.typ; // XXX: exception handling? a.typ := result.typ; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNSetStrVal: begin mNSetStrVal: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.strVal := result.strVal; // XXX: exception handling? a.strVal := result.strVal; // XXX: exception handling?
result := emptyNode result := emptyNode
end; end;
mNNewNimNode: begin mNNewNimNode: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
k := getOrdValue(result); k := getOrdValue(result);
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
if (k < 0) or (k > ord(high(TNodeKind))) then if (k < 0) or (k > ord(high(TNodeKind))) then
internalError(n.info, 'request to create a NimNode with invalid kind'); internalError(n.info, 'request to create a NimNode with invalid kind');
@ -1172,17 +1181,17 @@ begin
end; end;
mNCopyNimNode: begin mNCopyNimNode: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result := copyNode(result); result := copyNode(result);
end; end;
mNCopyNimTree: begin mNCopyNimTree: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
result := copyTree(result); result := copyTree(result);
end; end;
mStrToIdent: begin mStrToIdent: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if not (result.kind in [nkStrLit..nkTripleStrLit]) then if not (result.kind in [nkStrLit..nkTripleStrLit]) then
InternalError(n.info, 'no string node'); InternalError(n.info, 'no string node');
a := result; a := result;
@ -1191,7 +1200,7 @@ begin
end; end;
mIdentToStr: begin mIdentToStr: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
if result.kind <> nkIdent then if result.kind <> nkIdent then
InternalError(n.info, 'no ident node'); InternalError(n.info, 'no ident node');
a := result; a := result;
@ -1200,10 +1209,10 @@ begin
end; end;
mEqIdent: begin mEqIdent: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
result := newNodeIT(nkIntLit, n.info, n.typ); result := newNodeIT(nkIntLit, n.info, n.typ);
if (a.kind = nkIdent) and (b.kind = nkIdent) then if (a.kind = nkIdent) and (b.kind = nkIdent) then
@ -1211,10 +1220,10 @@ begin
end; end;
mEqNimrodNode: begin mEqNimrodNode: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
result := newNodeIT(nkIntLit, n.info, n.typ); result := newNodeIT(nkIntLit, n.info, n.typ);
if (a = b) if (a = b)
@ -1224,19 +1233,19 @@ begin
end; end;
mNHint: begin mNHint: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
liMessage(n.info, hintUser, getStrValue(result)); liMessage(n.info, hintUser, getStrValue(result));
result := emptyNode result := emptyNode
end; end;
mNWarning: begin mNWarning: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
liMessage(n.info, warnUser, getStrValue(result)); liMessage(n.info, warnUser, getStrValue(result));
result := emptyNode result := emptyNode
end; end;
mNError: begin mNError: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
stackTrace(c, n, errUser, getStrValue(result)); stackTrace(c, n, errUser, getStrValue(result));
result := emptyNode result := emptyNode
end; end;
@ -1244,28 +1253,31 @@ begin
mRepr: result := evalRepr(c, n); mRepr: result := evalRepr(c, n);
mNewString: begin mNewString: begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
result := newNodeIT(nkStrLit, n.info, n.typ); result := newNodeIT(nkStrLit, n.info, n.typ);
result.strVal := newString(int(getOrdValue(a))); result.strVal := newString(int(getOrdValue(a)));
end; end;
else begin else begin
result := evalAux(c, n.sons[1]); result := evalAux(c, n.sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a := result; a := result;
b := nil; b := nil;
cc := nil; cc := nil;
if sonsLen(n) > 2 then begin if sonsLen(n) > 2 then begin
result := evalAux(c, n.sons[2]); result := evalAux(c, n.sons[2]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
b := result; b := result;
if sonsLen(n) > 3 then begin if sonsLen(n) > 3 then begin
result := evalAux(c, n.sons[3]); result := evalAux(c, n.sons[3]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
cc := result; cc := result;
end end
end; end;
result := evalOp(m, n, a, b, cc); if isEmpty(a) or isEmpty(b) or isEmpty(cc) then
result := emptyNode
else
result := evalOp(m, n, a, b, cc);
end end
end end
end; end;
@ -1290,7 +1302,7 @@ begin
a := copyNode(n); a := copyNode(n);
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
result := evalAux(c, n.sons[i]); result := evalAux(c, n.sons[i]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
addSon(a, result); addSon(a, result);
end; end;
result := a result := a
@ -1299,7 +1311,7 @@ begin
a := copyTree(n); a := copyTree(n);
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
result := evalAux(c, n.sons[i].sons[1]); result := evalAux(c, n.sons[i].sons[1]);
if result.kind = nkExceptBranch then exit; if isSpecial(result) then exit;
a.sons[i].sons[1] := result; a.sons[i].sons[1] := result;
end; end;
result := a result := a
@ -1397,9 +1409,5 @@ begin
end; end;
initialization initialization
new(emptyNode); emptyNode := newNode(nkEmpty);
{@ignore}
fillChar(emptyNode^, sizeof(emptyNode^), 0);
{@emit}
emptyNode.kind := nkEmpty;
end. end.

View file

@ -35,6 +35,7 @@ Files: "configure;makefile"
Files: "*.html" Files: "*.html"
Files: "*.py" Files: "*.py"
Files: "*.ini" Files: "*.ini"
Files: "*.nim"
Files: "rod/readme.txt" Files: "rod/readme.txt"
Files: "rod/nimrod.ini" Files: "rod/nimrod.ini"