Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq
2018-09-15 00:41:32 +02:00
9 changed files with 152 additions and 73 deletions

View File

@@ -121,7 +121,8 @@ type
notnil,
dynamicBindSym,
forLoopMacros,
caseStmtMacros
caseStmtMacros,
codeReordering,
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf

View File

@@ -231,8 +231,17 @@ proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
else: resOptions = resOptions - op
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
if isTurnedOn(c, n): incl(c.module.flags, flag)
else: excl(c.module.flags, flag)
if isTurnedOn(c, n):
incl(c.module.flags, flag)
c.features.incl codeReordering
else:
excl(c.module.flags, flag)
# c.features.excl codeReordering
# deprecated as of 0.18.1
message(c.config, n.info, warnDeprecated,
"use {.experimental: \"codeReordering.\".} instead; " &
(if flag == sfNoForward: "{.noForward.}" else: "{.reorder.}"))
proc processCallConv(c: PContext, n: PNode) =
if n.kind in nkPragmaCallKinds and n.len == 2 and n.sons[1].kind == nkIdent:
@@ -351,7 +360,13 @@ proc processExperimental(c: PContext; n: PNode) =
case n[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
c.features.incl parseEnum[Feature](n[1].strVal)
let feature = parseEnum[Feature](n[1].strVal)
c.features.incl feature
if feature == codeReordering:
if not isTopLevel(c):
localError(c.config, n.info,
"Code reordering experimental pragma only valid at toplevel")
c.module.flags.incl sfReorder
except ValueError:
localError(c.config, n[1].info, "unknown experimental feature")
else:
@@ -817,7 +832,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
incl(sym.flags, {sfThread, sfGlobal})
of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
of wNoForward: pragmaNoForward(c, it)
of wReorder: pragmaNoForward(c, it, sfReorder)
of wReorder: pragmaNoForward(c, it, flag = sfReorder)
of wMagic: processMagic(c, it, sym)
of wCompileTime:
noVal(c, it)

View File

@@ -68,6 +68,8 @@ else:
toBase64a(cast[cstring](unsafeAddr u), sizeof(u))
proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
proc `&=`(c: var MD5Context, ch: char) = md5Update(c, unsafeAddr ch, 1)
proc `&=`(c: var MD5Context, r: Rope) =
for l in leaves(r): md5Update(c, l, l.len)
proc `&=`(c: var MD5Context, i: BiggestInt) =
md5Update(c, cast[cstring](unsafeAddr i), sizeof(i))
@@ -185,11 +187,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
# Every cyclic type in Nim need to be constructed via some 't.sym', so this
# is actually safe without an infinite recursion check:
if t.sym != nil:
#if "Future:" in t.sym.name.s and t.typeInst == nil:
# writeStackTrace()
# echo "yes ", t.sym.name.s
# #quit 1
if CoOwnerSig in flags:
if {sfCompilerProc} * t.sym.flags != {}:
doAssert t.sym.loc.r != nil
# The user has set a specific name for this type
c &= t.sym.loc.r
elif CoOwnerSig in flags:
c.hashTypeSym(t.sym)
else:
c.hashSym(t.sym)

View File

@@ -6534,6 +6534,111 @@ iterator in which case the overloading resolution takes place:
var x = 4
write(stdout, x) # not ambiguous: uses the module C's x
Code reordering
~~~~~~~~~~~~~~~
**Note**: Code reordering is experimental and must be enabled via the
``{.experimental.}`` pragma.
The code reordering feature can implicitly rearrange procedure, template, and
macro definitions along with variable declarations and initializations at the top
level scope so that, to a large extent, a programmer should not have to worry
about ordering definitions correctly or be forced to use forward declarations to
preface definitions inside a module.
..
NOTE: The following was documentation for the code reordering precursor,
which was {.noForward.}.
In this mode, procedure definitions may appear out of order and the compiler
will postpone their semantic analysis and compilation until it actually needs
to generate code using the definitions. In this regard, this mode is similar
to the modus operandi of dynamic scripting languages, where the function
calls are not resolved until the code is executed. Here is the detailed
algorithm taken by the compiler:
1. When a callable symbol is first encountered, the compiler will only note
the symbol callable name and it will add it to the appropriate overload set
in the current scope. At this step, it won't try to resolve any of the type
expressions used in the signature of the symbol (so they can refer to other
not yet defined symbols).
2. When a top level call is encountered (usually at the very end of the
module), the compiler will try to determine the actual types of all of the
symbols in the matching overload set. This is a potentially recursive process
as the signatures of the symbols may include other call expressions, whose
types will be resolved at this point too.
3. Finally, after the best overload is picked, the compiler will start
compiling the body of the respective symbol. This in turn will lead the
compiler to discover more call expressions that need to be resolved and steps
2 and 3 will be repeated as necessary.
Please note that if a callable symbol is never used in this scenario, its
body will never be compiled. This is the default behavior leading to best
compilation times, but if exhaustive compilation of all definitions is
required, using ``nim check`` provides this option as well.
Example:
.. code-block:: nim
{.experimental: "codeReordering".}
proc foo(x: int) =
bar(x)
proc bar(x: int) =
echo(x)
foo(10)
Variables can also be reordered as well. Variables that are *initialized* (i.e.
variables that have their declaration and assignment combined in a single
statement) can have their entire initialization statement reordered. Be wary of
what code is executed at the top level:
.. code-block:: nim
{.experimental: "codeReordering".}
proc a() =
echo(foo)
var foo = 5
a() # outputs: "5"
..
TODO: Let's table this for now. This is an *experimental feature* and so the
specific manner in which ``declared`` operates with it can be decided in
eventuality, because right now it works a bit weirdly.
The values of expressions involving ``declared`` are decided *before* the
code reordering process, and not after. As an example, the output of this
code is the same as it would be with code reordering disabled.
.. code-block:: nim
{.experimental: "codeReordering".}
proc x() =
echo(declared(foo))
var foo = 4
x() # "false"
It is important to note that reordering *only* works for symbols at top level
scope. Therefore, the following will *fail to compile:*
.. code-block:: nim
{.experimental: "codeReordering".}
proc a() =
b()
proc b() =
echo("Hello!")
a()
Compiler Messages
=================
@@ -6943,55 +7048,6 @@ the created global variables within a module is not defined, but all of them
will be initialized after any top-level variables in their originating module
and before any variable in a module that imports it.
..
NoForward pragma
----------------
The ``noforward`` pragma can be used to turn on and off a special compilation
mode that to large extent eliminates the need for forward declarations. In this
mode, the proc definitions may appear out of order and the compiler will postpone
their semantic analysis and compilation until it actually needs to generate code
using the definitions. In this regard, this mode is similar to the modus operandi
of dynamic scripting languages, where the function calls are not resolved until
the code is executed. Here is the detailed algorithm taken by the compiler:
1. When a callable symbol is first encountered, the compiler will only note the
symbol callable name and it will add it to the appropriate overload set in the
current scope. At this step, it won't try to resolve any of the type expressions
used in the signature of the symbol (so they can refer to other not yet defined
symbols).
2. When a top level call is encountered (usually at the very end of the module),
the compiler will try to determine the actual types of all of the symbols in the
matching overload set. This is a potentially recursive process as the signatures
of the symbols may include other call expressions, whose types will be resolved
at this point too.
3. Finally, after the best overload is picked, the compiler will start
compiling the body of the respective symbol. This in turn will lead the
compiler to discover more call expressions that need to be resolved and steps
2 and 3 will be repeated as necessary.
Please note that if a callable symbol is never used in this scenario, its body
will never be compiled. This is the default behavior leading to best compilation
times, but if exhaustive compilation of all definitions is required, using
``nim check`` provides this option as well.
Example:
.. code-block:: nim
{.noforward: on.}
proc foo(x: int) =
bar x
proc bar(x: int) =
echo x
foo(10)
pragma pragma
-------------

View File

@@ -7,12 +7,6 @@
# distribution, for details about the copyright.
#
when declared(ThisIsSystem):
# we are in system module:
{.pragma: codegenType, compilerproc.}
else:
{.pragma: codegenType.}
type
# This should be the same as ast.TTypeKind
# many enum fields are not used at runtime
@@ -79,7 +73,7 @@ type
tyVoidHidden
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
TNimNode {.codegenType.} = object
TNimNode {.compilerProc.} = object
kind: TNimNodeKind
offset: int
typ: ptr TNimType
@@ -92,7 +86,7 @@ type
ntfAcyclic = 1, # type cannot form a cycle
ntfEnumHole = 2 # enum has holes and thus `$` for them needs the slow
# version
TNimType {.codegenType.} = object
TNimType {.compilerProc.} = object
size: int
kind: TNimKind
flags: set[TNimTypeFlag]
@@ -109,6 +103,6 @@ type
PNimType = ptr TNimType
when defined(nimTypeNames):
var nimTypeRoot {.codegenType.}: PNimType
var nimTypeRoot {.compilerProc.}: PNimType
# node.len may be the ``first`` element of a set

10
tests/ccgbugs/t8964.nim Normal file
View File

@@ -0,0 +1,10 @@
discard """
targets: "c cpp"
"""
from json import JsonParsingError
import marshal
const nothing = ""
doAssertRaises(JsonParsingError):
var bar = marshal.to[int](nothing)

View File

@@ -2,7 +2,8 @@ discard """
disabled: true
"""
{. noforward: on .}
# {. noforward: on .}
{.experimental: "codeReordering".}
proc foo(x: int) =
bar x

View File

@@ -6,8 +6,7 @@ defined
3'''
"""
{.reorder: on.}
{.experimental.}
{.experimental: "codeReordering".}
proc bar(x: T)

View File

@@ -6,7 +6,8 @@ output:'''0
"""
import macros
{.reorder: on .}
# {.reorder: on .}
{.experimental: "codeReordering".}
echo foo(-1)
echo callWithFoo(0)
@@ -71,4 +72,4 @@ macro make(arg: untyped): untyped =
proc first(i: int): void =
make(second)
var ss {.compileTime.}: string = ""
var ss {.compileTime.}: string = ""