Merge branch 'devel' into faster-nimsuggest
This commit is contained in:
commit
ac3b312cc6
13 changed files with 135 additions and 25 deletions
10
.travis.yml
10
.travis.yml
|
|
@ -2,14 +2,24 @@ sudo: false
|
||||||
language: c
|
language: c
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
- osx
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- os: osx
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- libcurl4-openssl-dev
|
- libcurl4-openssl-dev
|
||||||
- libsdl1.2-dev
|
- libsdl1.2-dev
|
||||||
- libgc-dev
|
- libgc-dev
|
||||||
|
brew:
|
||||||
|
packages:
|
||||||
|
- boehmgc
|
||||||
|
- node
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- set -e
|
- set -e
|
||||||
- curl --out fasm-1.71.39.tgz https://nim-lang.org/download/fasm-1.71.39.tgz
|
- curl --out fasm-1.71.39.tgz https://nim-lang.org/download/fasm-1.71.39.tgz
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,13 @@ proc isKeyword(w: PIdent): bool =
|
||||||
|
|
||||||
proc mangleField(m: BModule; name: PIdent): string =
|
proc mangleField(m: BModule; name: PIdent): string =
|
||||||
result = mangle(name.s)
|
result = mangle(name.s)
|
||||||
if isKeyword(name) or m.g.config.cppDefines.contains(result):
|
# fields are tricky to get right and thanks to generic types producing
|
||||||
|
# duplicates we can end up mangling the same field multiple times. However
|
||||||
|
# if we do so, the 'cppDefines' table might be modified in the meantime
|
||||||
|
# meaning we produce inconsistent field names (see bug #5404).
|
||||||
|
# Hence we do not check for ``m.g.config.cppDefines.contains(result)`` here
|
||||||
|
# anymore:
|
||||||
|
if isKeyword(name):
|
||||||
result.add "_0"
|
result.add "_0"
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
|
||||||
|
|
@ -25,19 +25,19 @@ const
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||||
wOverride, wConstructor, wExportNims}
|
wOverride, wConstructor, wExportNims, wUsed}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
|
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
|
||||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
|
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
|
||||||
wDelegator, wExportNims}
|
wDelegator, wExportNims, wUsed}
|
||||||
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
||||||
wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
|
wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
|
||||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
|
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
|
||||||
wExportNims}
|
wExportNims, wUsed}
|
||||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
|
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
|
||||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
||||||
wTags, wLocks, wGcSafe, wExportNims}
|
wTags, wLocks, wGcSafe, wExportNims, wUsed}
|
||||||
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
|
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
|
||||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||||
|
|
@ -55,16 +55,16 @@ const
|
||||||
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
|
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
|
||||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
||||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||||
wBorrow, wGcSafe, wExportNims, wPartial}
|
wBorrow, wGcSafe, wExportNims, wPartial, wUsed}
|
||||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||||
wImportCpp, wImportObjC, wError, wGuard, wBitsize}
|
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
|
||||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||||
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
|
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
|
||||||
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
||||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims}
|
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed}
|
||||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||||
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
||||||
wIntDefine, wStrDefine}
|
wIntDefine, wStrDefine, wUsed}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
|
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
|
||||||
wThread, wRaises, wLocks, wTags, wGcSafe}
|
wThread, wRaises, wLocks, wTags, wGcSafe}
|
||||||
|
|
@ -582,7 +582,13 @@ proc pragmaLocks(c: PContext, it: PNode): TLockLevel =
|
||||||
if it.kind != nkExprColonExpr:
|
if it.kind != nkExprColonExpr:
|
||||||
invalidPragma(it)
|
invalidPragma(it)
|
||||||
else:
|
else:
|
||||||
if it[1].kind != nkNilLit:
|
case it[1].kind
|
||||||
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
|
if it[1].strVal == "unknown":
|
||||||
|
result = UnknownLockLevel
|
||||||
|
else:
|
||||||
|
localError(it[1].info, "invalid string literal for locks pragma (only allowed string is \"unknown\")")
|
||||||
|
else:
|
||||||
let x = expectIntLit(c, it)
|
let x = expectIntLit(c, it)
|
||||||
if x < 0 or x > MaxLockLevel:
|
if x < 0 or x > MaxLockLevel:
|
||||||
localError(it[1].info, "integer must be within 0.." & $MaxLockLevel)
|
localError(it[1].info, "integer must be within 0.." & $MaxLockLevel)
|
||||||
|
|
@ -961,6 +967,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
sym.magic = mIntDefine
|
sym.magic = mIntDefine
|
||||||
of wStrDefine:
|
of wStrDefine:
|
||||||
sym.magic = mStrDefine
|
sym.magic = mStrDefine
|
||||||
|
of wUsed:
|
||||||
|
noVal(it)
|
||||||
|
if sym == nil: invalidPragma(it)
|
||||||
|
else: sym.flags.incl sfUsed
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ proc sameTree*(a, b: PNode): bool =
|
||||||
# don't go nuts here: same symbol as string is enough:
|
# don't go nuts here: same symbol as string is enough:
|
||||||
result = a.sym.name.id == b.sym.name.id
|
result = a.sym.name.id == b.sym.name.id
|
||||||
of nkIdent: result = a.ident.id == b.ident.id
|
of nkIdent: result = a.ident.id == b.ident.id
|
||||||
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
|
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
|
||||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||||
of nkEmpty, nkNilLit, nkType: result = true
|
of nkEmpty, nkNilLit, nkType: result = true
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ type
|
||||||
wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
|
wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
|
||||||
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
||||||
wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
|
wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
|
||||||
wCompilerproc, wProcVar, wBase,
|
wCompilerproc, wProcVar, wBase, wUsed,
|
||||||
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
|
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
|
||||||
wLinedir, wStacktrace, wLinetrace, wLink, wCompile,
|
wLinedir, wStacktrace, wLinetrace, wLink, wCompile,
|
||||||
wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger,
|
wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger,
|
||||||
|
|
@ -131,7 +131,7 @@ const
|
||||||
"incompletestruct",
|
"incompletestruct",
|
||||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
||||||
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
|
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
|
||||||
"compilerproc", "procvar", "base",
|
"compilerproc", "procvar", "base", "used",
|
||||||
"fatal", "error", "warning", "hint", "line",
|
"fatal", "error", "warning", "hint", "line",
|
||||||
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
|
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
|
||||||
"link", "compile", "linksys", "deprecated", "varargs",
|
"link", "compile", "linksys", "deprecated", "varargs",
|
||||||
|
|
|
||||||
|
|
@ -198,3 +198,22 @@ This is essential so that procs can be called within a ``locks`` section:
|
||||||
As usual ``locks`` is an inferred effect and there is a subtype
|
As usual ``locks`` is an inferred effect and there is a subtype
|
||||||
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
|
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
|
||||||
iff (M <= N).
|
iff (M <= N).
|
||||||
|
|
||||||
|
The ``locks`` pragma can also take the special value ``"unknown"``. This
|
||||||
|
is useful in the context of dynamic method dispatching. In the following
|
||||||
|
example, the compiler can infer a lock level of 0 for the ``base`` case.
|
||||||
|
However, one of the overloaded methods calls a procvar which is
|
||||||
|
potentially locking. Thus, the lock level of calling ``g.testMethod``
|
||||||
|
cannot be inferred statically, leading to compiler warnings. By using
|
||||||
|
``{.locks: "unknown".}``, the base method can be marked explicitly as
|
||||||
|
having unknown lock level as well:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
type SomeBase* = ref object of RootObj
|
||||||
|
type SomeDerived* = ref object of SomeBase
|
||||||
|
memberProc*: proc ()
|
||||||
|
|
||||||
|
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
|
||||||
|
method testMethod(g: SomeDerived) =
|
||||||
|
if g.memberProc != nil:
|
||||||
|
g.memberProc()
|
||||||
|
|
|
||||||
|
|
@ -503,6 +503,26 @@ identifier that can be used to enable or disable it:
|
||||||
This is often better than disabling all warnings at once.
|
This is often better than disabling all warnings at once.
|
||||||
|
|
||||||
|
|
||||||
|
used pragma
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Nim produces a warning for symbols that are not exported and not used either.
|
||||||
|
The ``used`` pragma can be attached to a symbol to suppress this warning. This
|
||||||
|
is particularly useful when the symbol was generated by a macro:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
template implementArithOps(T) =
|
||||||
|
proc echoAdd(a, b: T) {.used.} =
|
||||||
|
echo a + b
|
||||||
|
proc echoSub(a, b: T) {.used.} =
|
||||||
|
echo a - b
|
||||||
|
|
||||||
|
# no warning produced for the unused 'echoSub'
|
||||||
|
implementArithOps(int)
|
||||||
|
echoAdd 3, 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
experimental pragma
|
experimental pragma
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
@ -1018,12 +1038,12 @@ the -d/--define option at compile time.
|
||||||
The implementation currently provides the following possible options (various
|
The implementation currently provides the following possible options (various
|
||||||
others may be added later).
|
others may be added later).
|
||||||
|
|
||||||
=============== ============================================
|
================= ============================================
|
||||||
pragma description
|
pragma description
|
||||||
=============== ============================================
|
================= ============================================
|
||||||
intdefine Reads in a build-time define as an integer
|
`intdefine`:idx: Reads in a build-time define as an integer
|
||||||
strdefine Reads in a build-time define as a string
|
`strdefine`:idx: Reads in a build-time define as a string
|
||||||
=============== ============================================
|
================= ============================================
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
const FooBar {.intdefine.}: int = 5
|
const FooBar {.intdefine.}: int = 5
|
||||||
|
|
|
||||||
|
|
@ -952,7 +952,7 @@ proc newIndent(curr, indent: int, ml: bool): int =
|
||||||
else: return indent
|
else: return indent
|
||||||
|
|
||||||
proc nl(s: var string, ml: bool) =
|
proc nl(s: var string, ml: bool) =
|
||||||
if ml: s.add("\n")
|
s.add(if ml: "\n" else: " ")
|
||||||
|
|
||||||
proc escapeJson*(s: string; result: var string) =
|
proc escapeJson*(s: string; result: var string) =
|
||||||
## Converts a string `s` to its JSON representation.
|
## Converts a string `s` to its JSON representation.
|
||||||
|
|
@ -986,15 +986,14 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
|
||||||
lstArr = false, currIndent = 0) =
|
lstArr = false, currIndent = 0) =
|
||||||
case node.kind
|
case node.kind
|
||||||
of JObject:
|
of JObject:
|
||||||
if currIndent != 0 and not lstArr: result.nl(ml)
|
if lstArr: result.indent(currIndent) # Indentation
|
||||||
result.indent(currIndent) # Indentation
|
|
||||||
if node.fields.len > 0:
|
if node.fields.len > 0:
|
||||||
result.add("{")
|
result.add("{")
|
||||||
result.nl(ml) # New line
|
result.nl(ml) # New line
|
||||||
var i = 0
|
var i = 0
|
||||||
for key, val in pairs(node.fields):
|
for key, val in pairs(node.fields):
|
||||||
if i > 0:
|
if i > 0:
|
||||||
result.add(", ")
|
result.add(",")
|
||||||
result.nl(ml) # New Line
|
result.nl(ml) # New Line
|
||||||
inc i
|
inc i
|
||||||
# Need to indent more than {
|
# Need to indent more than {
|
||||||
|
|
@ -1030,7 +1029,7 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
|
||||||
result.nl(ml)
|
result.nl(ml)
|
||||||
for i in 0..len(node.elems)-1:
|
for i in 0..len(node.elems)-1:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
result.add(", ")
|
result.add(",")
|
||||||
result.nl(ml) # New Line
|
result.nl(ml) # New Line
|
||||||
toPretty(result, node.elems[i], indent, ml,
|
toPretty(result, node.elems[i], indent, ml,
|
||||||
true, newIndent(currIndent, indent, ml))
|
true, newIndent(currIndent, indent, ml))
|
||||||
|
|
|
||||||
|
|
@ -1185,7 +1185,7 @@ proc createHardlink*(src, dest: string) =
|
||||||
|
|
||||||
proc parseCmdLine*(c: string): seq[string] {.
|
proc parseCmdLine*(c: string): seq[string] {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Splits a command line into several components;
|
## Splits a `command line`:idx: into several components;
|
||||||
## This proc is only occasionally useful, better use the `parseopt` module.
|
## This proc is only occasionally useful, better use the `parseopt` module.
|
||||||
##
|
##
|
||||||
## On Windows, it uses the following parsing rules
|
## On Windows, it uses the following parsing rules
|
||||||
|
|
|
||||||
16
tests/ccgbugs/tmangle_field.nim
Normal file
16
tests/ccgbugs/tmangle_field.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #5404
|
||||||
|
|
||||||
|
import parseopt2
|
||||||
|
|
||||||
|
{.emit: """typedef struct {
|
||||||
|
int key;
|
||||||
|
} foo;""".}
|
||||||
|
|
||||||
|
type foo* {.importc: "foo", nodecl.} = object
|
||||||
|
key* {.importc: "key".}: cint
|
||||||
|
|
||||||
|
for kind, key, value in parseopt2.getopt():
|
||||||
|
discard
|
||||||
13
tests/pragmas/tlocks.nim
Normal file
13
tests/pragmas/tlocks.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
type SomeBase* = ref object of RootObj
|
||||||
|
type SomeDerived* = ref object of SomeBase
|
||||||
|
memberProc*: proc ()
|
||||||
|
|
||||||
|
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
|
||||||
|
method testMethod(g: SomeDerived) =
|
||||||
|
if g.memberProc != nil:
|
||||||
|
g.memberProc()
|
||||||
|
|
||||||
|
# ensure int literals still work
|
||||||
|
proc plain*() {.locks: 0.} =
|
||||||
|
discard
|
||||||
13
tests/pragmas/tused.nim
Normal file
13
tests/pragmas/tused.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
output: '''8'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
template implementArithOps(T) =
|
||||||
|
proc echoAdd(a, b: T) {.used.} =
|
||||||
|
echo a + b
|
||||||
|
proc echoSub(a, b: T) {.used.} =
|
||||||
|
echo a - b
|
||||||
|
|
||||||
|
# no warning produced for the unused 'echoSub'
|
||||||
|
implementArithOps(int)
|
||||||
|
echoAdd 3, 5
|
||||||
|
|
@ -66,6 +66,10 @@ these procedures.
|
||||||
In the near future we will be converting all exception types to refs to
|
In the near future we will be converting all exception types to refs to
|
||||||
remove the need for the ``newException`` template.
|
remove the need for the ``newException`` template.
|
||||||
|
|
||||||
|
- A new pragma ``.used`` can be used for symbols to prevent
|
||||||
|
the "declared but not used" warning. More details can be found `here <http://nim-lang.org/docs/manual.html#pragmas-used-pragma>`_.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue