implemented user-defined pragmas
This commit is contained in:
parent
5a2163d71d
commit
804e2ac89d
11 changed files with 237 additions and 151 deletions
|
|
@ -2651,6 +2651,30 @@ Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
||||||
|
|
||||||
|
Pragma pragma
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The `pragma`:idx: pragma can be used to declare user defined pragmas. This is
|
||||||
|
useful because Nimrod's templates and macros do not affect pragmas. User
|
||||||
|
defined pragmas are in a different module-wide scope than all other symbols.
|
||||||
|
They cannot be imported from a module.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
when appType == "lib":
|
||||||
|
{.pragma: rtl, exportc, dynlib, cdecl.}
|
||||||
|
else:
|
||||||
|
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
|
||||||
|
|
||||||
|
proc p*(a, b: int): int {.rtl.} =
|
||||||
|
return a+b
|
||||||
|
|
||||||
|
In the example a new pragma named ``rtl`` is introduced that either imports
|
||||||
|
a symbol from a dynamic library or exports the symbol for dynamic library
|
||||||
|
generation.
|
||||||
|
|
||||||
|
|
||||||
Disabling certain messages
|
Disabling certain messages
|
||||||
|
|
@ -2715,8 +2739,8 @@ strings automatically:
|
||||||
printf("hallo %s", "world") # "world" will be passed as C string
|
printf("hallo %s", "world") # "world" will be passed as C string
|
||||||
|
|
||||||
|
|
||||||
Dynlib pragma
|
Dynlib pragma for import
|
||||||
-------------
|
------------------------
|
||||||
With the `dynlib`:idx: pragma a procedure can be imported from
|
With the `dynlib`:idx: pragma a procedure can be imported from
|
||||||
a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). The
|
a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). The
|
||||||
non-optional argument has to be the name of the dynamic library:
|
non-optional argument has to be the name of the dynamic library:
|
||||||
|
|
@ -2762,3 +2786,17 @@ string expressions in general:
|
||||||
|
|
||||||
**Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant
|
**Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant
|
||||||
strings, because they are precompiled.
|
strings, because they are precompiled.
|
||||||
|
|
||||||
|
Dynlib pragma for export
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
With the ``dynlib`` pragma a procedure can also be exported to
|
||||||
|
a dynamic library. The pragma then has no argument and has to be used in
|
||||||
|
conjunction with the ``exportc`` pragma:
|
||||||
|
|
||||||
|
.. code-block:: Nimrod
|
||||||
|
proc exportme(): int {.cdecl, export, dynlib.}
|
||||||
|
|
||||||
|
This is only useful if the program is compiled as a dynamic library via the
|
||||||
|
``--app:lib`` command line option.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,8 @@ type
|
||||||
skIterator, # an iterator
|
skIterator, # an iterator
|
||||||
skConverter, # a type converter
|
skConverter, # a type converter
|
||||||
skMacro, # a macro
|
skMacro, # a macro
|
||||||
skTemplate, # a template
|
skTemplate, # a template; currently also misused for user-defined
|
||||||
|
# pragmas
|
||||||
skField, # a field in a record or object
|
skField, # a field in a record or object
|
||||||
skEnumField, # an identifier in an enum
|
skEnumField, # an identifier in an enum
|
||||||
skForVar, # a for loop variable
|
skForVar, # a for loop variable
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
## It translates a C source file into a Nimrod AST. Then the renderer can be
|
## It translates a C source file into a Nimrod AST. Then the renderer can be
|
||||||
## used to convert the AST to its text representation.
|
## used to convert the AST to its text representation.
|
||||||
|
|
||||||
|
## XXX cleanup of declaration handling. Standalone enums.
|
||||||
|
|
||||||
import
|
import
|
||||||
os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
|
os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
|
||||||
options, strtabs
|
options, strtabs
|
||||||
|
|
|
||||||
17
rod/c2nim/tests/systest2.c
Normal file
17
rod/c2nim/tests/systest2.c
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifdef C2NIM
|
||||||
|
# header "iup.h"
|
||||||
|
# cdecl
|
||||||
|
# mangle "'GTK_'{.*}" "TGtk$1"
|
||||||
|
# mangle "'PGTK_'{.*}" "PGtk$1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct stupidTAG {
|
||||||
|
mytype a, b;
|
||||||
|
} GTK_MyStruct, *PGTK_MyStruct;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mytype a, b;
|
||||||
|
} GTK_MyStruct, *PGTK_MyStruct;
|
||||||
|
|
||||||
|
int IupConvertXYToPos(PIhandle ih, int x, int y);
|
||||||
|
|
||||||
|
|
@ -24,11 +24,8 @@ proc countDefinedSymbols*(): int
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc DefineSymbol(symbol: string) =
|
proc DefineSymbol(symbol: string) =
|
||||||
var
|
var i = getIdent(symbol)
|
||||||
sym: PSym
|
var sym = StrTableGet(gSymbols, i)
|
||||||
i: PIdent
|
|
||||||
i = getIdent(symbol)
|
|
||||||
sym = StrTableGet(gSymbols, i)
|
|
||||||
if sym == nil:
|
if sym == nil:
|
||||||
new(sym) # circumvent the ID mechanism
|
new(sym) # circumvent the ID mechanism
|
||||||
sym.kind = skConditional
|
sym.kind = skConditional
|
||||||
|
|
@ -37,20 +34,16 @@ proc DefineSymbol(symbol: string) =
|
||||||
sym.position = 1
|
sym.position = 1
|
||||||
|
|
||||||
proc UndefSymbol(symbol: string) =
|
proc UndefSymbol(symbol: string) =
|
||||||
var sym: PSym
|
var sym = StrTableGet(gSymbols, getIdent(symbol))
|
||||||
sym = StrTableGet(gSymbols, getIdent(symbol))
|
|
||||||
if sym != nil: sym.position = 0
|
if sym != nil: sym.position = 0
|
||||||
|
|
||||||
proc isDefined(symbol: PIdent): bool =
|
proc isDefined(symbol: PIdent): bool =
|
||||||
var sym: PSym
|
var sym = StrTableGet(gSymbols, symbol)
|
||||||
sym = StrTableGet(gSymbols, symbol)
|
|
||||||
result = (sym != nil) and (sym.position == 1)
|
result = (sym != nil) and (sym.position == 1)
|
||||||
|
|
||||||
proc ListSymbols() =
|
proc ListSymbols() =
|
||||||
var
|
var it: TTabIter
|
||||||
it: TTabIter
|
var s = InitTabIter(it, gSymbols)
|
||||||
s: PSym
|
|
||||||
s = InitTabIter(it, gSymbols)
|
|
||||||
MessageOut("-- List of currently defined symbols --")
|
MessageOut("-- List of currently defined symbols --")
|
||||||
while s != nil:
|
while s != nil:
|
||||||
if s.position == 1: MessageOut(s.name.s)
|
if s.position == 1: MessageOut(s.name.s)
|
||||||
|
|
@ -58,10 +51,8 @@ proc ListSymbols() =
|
||||||
MessageOut("-- End of list --")
|
MessageOut("-- End of list --")
|
||||||
|
|
||||||
proc countDefinedSymbols(): int =
|
proc countDefinedSymbols(): int =
|
||||||
var
|
var it: TTabIter
|
||||||
it: TTabIter
|
var s = InitTabIter(it, gSymbols)
|
||||||
s: PSym
|
|
||||||
s = InitTabIter(it, gSymbols)
|
|
||||||
result = 0
|
result = 0
|
||||||
while s != nil:
|
while s != nil:
|
||||||
if s.position == 1: inc(result)
|
if s.position == 1: inc(result)
|
||||||
|
|
|
||||||
275
rod/pragmas.nim
275
rod/pragmas.nim
|
|
@ -33,7 +33,7 @@ const
|
||||||
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
|
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
|
||||||
wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint,
|
wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint,
|
||||||
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
|
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
|
||||||
wInfChecks, wNanChecks}
|
wInfChecks, wNanChecks, wPragma}
|
||||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||||
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
|
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
|
||||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||||
|
|
@ -303,10 +303,9 @@ proc processCompile(c: PContext, n: PNode) =
|
||||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
||||||
|
|
||||||
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||||
var f, found: string
|
var f = expectStrLit(c, n)
|
||||||
f = expectStrLit(c, n)
|
|
||||||
if splitFile(f).ext == "": f = toObjFile(f)
|
if splitFile(f).ext == "": f = toObjFile(f)
|
||||||
found = findFile(f)
|
var found = findFile(f)
|
||||||
if found == "": found = f # use the default
|
if found == "": found = f # use the default
|
||||||
case feature
|
case feature
|
||||||
of linkNormal: extccomp.addFileToLink(found)
|
of linkNormal: extccomp.addFileToLink(found)
|
||||||
|
|
@ -325,137 +324,159 @@ proc PragmaCheckpoint(c: PContext, n: PNode) =
|
||||||
|
|
||||||
proc noVal(n: PNode) =
|
proc noVal(n: PNode) =
|
||||||
if n.kind == nkExprColonExpr: invalidPragma(n)
|
if n.kind == nkExprColonExpr: invalidPragma(n)
|
||||||
|
|
||||||
|
proc processPragma(c: PContext, n: PNode, i: int) =
|
||||||
|
var it = n.sons[i]
|
||||||
|
if it.kind != nkExprColonExpr: invalidPragma(n)
|
||||||
|
elif it.sons[0].kind != nkIdent: invalidPragma(n)
|
||||||
|
elif it.sons[1].kind != nkIdent: invalidPragma(n)
|
||||||
|
|
||||||
|
var userPragma = NewSym(skTemplate, it.sons[1].ident, nil)
|
||||||
|
userPragma.info = it.info
|
||||||
|
var body = newNodeI(nkPragma, n.info)
|
||||||
|
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
|
||||||
|
userPragma.ast = body
|
||||||
|
StrTableAdd(c.userPragmas, userPragma)
|
||||||
|
|
||||||
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||||
if key.kind == nkIdent:
|
if key.kind == nkIdent:
|
||||||
var k = whichKeyword(key.ident)
|
var userPragma = StrTableGet(c.userPragmas, key.ident)
|
||||||
if k in validPragmas:
|
if userPragma != nil:
|
||||||
case k
|
pragma(c, sym, userPragma.ast, validPragmas)
|
||||||
of wExportc:
|
# XXX BUG: possible infinite recursion!
|
||||||
makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
|
else:
|
||||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
var k = whichKeyword(key.ident)
|
||||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
|
if k in validPragmas:
|
||||||
of wAlign:
|
case k
|
||||||
if sym.typ == nil: invalidPragma(it)
|
of wExportc:
|
||||||
sym.typ.align = expectIntLit(c, it)
|
makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
|
||||||
if not IsPowerOfTwo(sym.typ.align) and (sym.typ.align != 0):
|
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||||
liMessage(it.info, errPowerOfTwoExpected)
|
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
|
||||||
of wSize:
|
of wAlign:
|
||||||
if sym.typ == nil: invalidPragma(it)
|
if sym.typ == nil: invalidPragma(it)
|
||||||
var size = expectIntLit(c, it)
|
sym.typ.align = expectIntLit(c, it)
|
||||||
if not IsPowerOfTwo(size) or size <= 0 or size > 8:
|
if not IsPowerOfTwo(sym.typ.align) and (sym.typ.align != 0):
|
||||||
liMessage(it.info, errPowerOfTwoExpected)
|
liMessage(it.info, errPowerOfTwoExpected)
|
||||||
else:
|
of wSize:
|
||||||
sym.typ.size = size
|
if sym.typ == nil: invalidPragma(it)
|
||||||
of wNodecl:
|
var size = expectIntLit(c, it)
|
||||||
noVal(it)
|
if not IsPowerOfTwo(size) or size <= 0 or size > 8:
|
||||||
incl(sym.loc.Flags, lfNoDecl)
|
liMessage(it.info, errPowerOfTwoExpected)
|
||||||
of wPure:
|
else:
|
||||||
noVal(it)
|
sym.typ.size = size
|
||||||
if sym != nil: incl(sym.flags, sfPure)
|
of wNodecl:
|
||||||
of wVolatile:
|
noVal(it)
|
||||||
noVal(it)
|
incl(sym.loc.Flags, lfNoDecl)
|
||||||
incl(sym.flags, sfVolatile)
|
of wPure:
|
||||||
of wRegister:
|
noVal(it)
|
||||||
noVal(it)
|
if sym != nil: incl(sym.flags, sfPure)
|
||||||
incl(sym.flags, sfRegister)
|
of wVolatile:
|
||||||
of wThreadVar:
|
noVal(it)
|
||||||
noVal(it)
|
incl(sym.flags, sfVolatile)
|
||||||
incl(sym.flags, sfThreadVar)
|
of wRegister:
|
||||||
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
|
noVal(it)
|
||||||
of wMagic: processMagic(c, it, sym)
|
incl(sym.flags, sfRegister)
|
||||||
of wCompileTime:
|
of wThreadVar:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
incl(sym.flags, sfCompileTime)
|
incl(sym.flags, sfThreadVar)
|
||||||
incl(sym.loc.Flags, lfNoDecl)
|
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
|
||||||
of wMerge:
|
of wMagic: processMagic(c, it, sym)
|
||||||
noval(it)
|
of wCompileTime:
|
||||||
incl(sym.flags, sfMerge)
|
noVal(it)
|
||||||
of wHeader:
|
incl(sym.flags, sfCompileTime)
|
||||||
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
incl(sym.loc.Flags, lfNoDecl)
|
||||||
addToLib(lib, sym)
|
of wMerge:
|
||||||
incl(sym.flags, sfImportc)
|
noval(it)
|
||||||
incl(sym.loc.flags, lfHeader)
|
incl(sym.flags, sfMerge)
|
||||||
incl(sym.loc.Flags, lfNoDecl) # implies nodecl, because
|
of wHeader:
|
||||||
# otherwise header would not make sense
|
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
||||||
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
addToLib(lib, sym)
|
||||||
of wNosideeffect:
|
incl(sym.flags, sfImportc)
|
||||||
noVal(it)
|
incl(sym.loc.flags, lfHeader)
|
||||||
incl(sym.flags, sfNoSideEffect)
|
incl(sym.loc.Flags, lfNoDecl)
|
||||||
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
|
# implies nodecl, because otherwise header would not make sense
|
||||||
of wSideEffect:
|
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
||||||
noVal(it)
|
of wNosideeffect:
|
||||||
incl(sym.flags, sfSideEffect)
|
noVal(it)
|
||||||
of wNoReturn:
|
incl(sym.flags, sfNoSideEffect)
|
||||||
noVal(it)
|
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
|
||||||
incl(sym.flags, sfNoReturn)
|
of wSideEffect:
|
||||||
of wDynLib:
|
noVal(it)
|
||||||
processDynLib(c, it, sym)
|
incl(sym.flags, sfSideEffect)
|
||||||
of wCompilerProc:
|
of wNoReturn:
|
||||||
noVal(it) # compilerproc may not get a string!
|
noVal(it)
|
||||||
makeExternExport(sym, sym.name.s)
|
incl(sym.flags, sfNoReturn)
|
||||||
incl(sym.flags, sfCompilerProc)
|
of wDynLib:
|
||||||
incl(sym.flags, sfUsed) # suppress all those stupid warnings
|
processDynLib(c, it, sym)
|
||||||
registerCompilerProc(sym)
|
of wCompilerProc:
|
||||||
of wProcvar:
|
noVal(it) # compilerproc may not get a string!
|
||||||
noVal(it)
|
makeExternExport(sym, sym.name.s)
|
||||||
incl(sym.flags, sfProcVar)
|
incl(sym.flags, sfCompilerProc)
|
||||||
of wDeprecated:
|
incl(sym.flags, sfUsed) # suppress all those stupid warnings
|
||||||
noVal(it)
|
registerCompilerProc(sym)
|
||||||
if sym != nil: incl(sym.flags, sfDeprecated)
|
of wProcvar:
|
||||||
else: incl(c.module.flags, sfDeprecated)
|
noVal(it)
|
||||||
of wVarargs:
|
incl(sym.flags, sfProcVar)
|
||||||
noVal(it)
|
of wDeprecated:
|
||||||
if sym.typ == nil: invalidPragma(it)
|
noVal(it)
|
||||||
incl(sym.typ.flags, tfVarargs)
|
if sym != nil: incl(sym.flags, sfDeprecated)
|
||||||
of wBorrow:
|
else: incl(c.module.flags, sfDeprecated)
|
||||||
noVal(it)
|
of wVarargs:
|
||||||
incl(sym.flags, sfBorrow)
|
noVal(it)
|
||||||
of wFinal:
|
if sym.typ == nil: invalidPragma(it)
|
||||||
noVal(it)
|
incl(sym.typ.flags, tfVarargs)
|
||||||
if sym.typ == nil: invalidPragma(it)
|
of wBorrow:
|
||||||
incl(sym.typ.flags, tfFinal)
|
noVal(it)
|
||||||
of wAcyclic:
|
incl(sym.flags, sfBorrow)
|
||||||
noVal(it)
|
of wFinal:
|
||||||
if sym.typ == nil: invalidPragma(it)
|
noVal(it)
|
||||||
incl(sym.typ.flags, tfAcyclic)
|
if sym.typ == nil: invalidPragma(it)
|
||||||
of wTypeCheck:
|
incl(sym.typ.flags, tfFinal)
|
||||||
noVal(it)
|
of wAcyclic:
|
||||||
incl(sym.flags, sfTypeCheck)
|
noVal(it)
|
||||||
of wHint: liMessage(it.info, hintUser, expectStrLit(c, it))
|
if sym.typ == nil: invalidPragma(it)
|
||||||
of wWarning: liMessage(it.info, warnUser, expectStrLit(c, it))
|
incl(sym.typ.flags, tfAcyclic)
|
||||||
of wError: liMessage(it.info, errUser, expectStrLit(c, it))
|
of wTypeCheck:
|
||||||
of wFatal:
|
noVal(it)
|
||||||
liMessage(it.info, errUser, expectStrLit(c, it))
|
incl(sym.flags, sfTypeCheck)
|
||||||
quit(1)
|
of wHint: liMessage(it.info, hintUser, expectStrLit(c, it))
|
||||||
of wDefine: processDefine(c, it)
|
of wWarning: liMessage(it.info, warnUser, expectStrLit(c, it))
|
||||||
of wUndef: processUndef(c, it)
|
of wError: liMessage(it.info, errUser, expectStrLit(c, it))
|
||||||
of wCompile: processCompile(c, it)
|
of wFatal:
|
||||||
of wLink: processCommonLink(c, it, linkNormal)
|
liMessage(it.info, errUser, expectStrLit(c, it))
|
||||||
of wLinkSys: processCommonLink(c, it, linkSys)
|
quit(1)
|
||||||
of wPassL: extccomp.addLinkOption(expectStrLit(c, it))
|
of wDefine: processDefine(c, it)
|
||||||
of wPassC: extccomp.addCompileOption(expectStrLit(c, it))
|
of wUndef: processUndef(c, it)
|
||||||
of wBreakpoint: PragmaBreakpoint(c, it)
|
of wCompile: processCompile(c, it)
|
||||||
of wCheckpoint: PragmaCheckpoint(c, it)
|
of wLink: processCommonLink(c, it, linkNormal)
|
||||||
of wPush:
|
of wLinkSys: processCommonLink(c, it, linkSys)
|
||||||
processPush(c, n, i + 1)
|
of wPassL: extccomp.addLinkOption(expectStrLit(c, it))
|
||||||
break
|
of wPassC: extccomp.addCompileOption(expectStrLit(c, it))
|
||||||
of wPop: processPop(c, it)
|
of wBreakpoint: PragmaBreakpoint(c, it)
|
||||||
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
of wCheckpoint: PragmaCheckpoint(c, it)
|
||||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
of wPush:
|
||||||
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef, wCallConv,
|
processPush(c, n, i + 1)
|
||||||
wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks:
|
break
|
||||||
processOption(c, it) # calling conventions (boring...):
|
of wPop: processPop(c, it)
|
||||||
of firstCallConv..lastCallConv:
|
of wPragma:
|
||||||
assert(sym != nil)
|
processPragma(c, n, i)
|
||||||
if sym.typ == nil: invalidPragma(it)
|
break
|
||||||
sym.typ.callConv = wordToCallConv(k)
|
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||||
|
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||||
|
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef,
|
||||||
|
wCallConv,
|
||||||
|
wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks:
|
||||||
|
processOption(c, it) # calling conventions (boring...):
|
||||||
|
of firstCallConv..lastCallConv:
|
||||||
|
assert(sym != nil)
|
||||||
|
if sym.typ == nil: invalidPragma(it)
|
||||||
|
sym.typ.callConv = wordToCallConv(k)
|
||||||
|
else: invalidPragma(it)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
else: invalidPragma(it)
|
|
||||||
else: processNote(c, it)
|
else: processNote(c, it)
|
||||||
if (sym != nil) and (sym.kind != skModule):
|
if (sym != nil) and (sym.kind != skModule):
|
||||||
if (lfExportLib in sym.loc.flags) and not (sfExportc in sym.flags):
|
if (lfExportLib in sym.loc.flags) and not (sfExportc in sym.flags):
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ type
|
||||||
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
|
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
|
||||||
includedFiles*: TIntSet # used to detect recursive include files
|
includedFiles*: TIntSet # used to detect recursive include files
|
||||||
filename*: string # the module's filename
|
filename*: string # the module's filename
|
||||||
|
userPragmas*: TStrTable
|
||||||
|
|
||||||
|
|
||||||
var gInstTypes*: TIdTable # map PType to PType
|
var gInstTypes*: TIdTable # map PType to PType
|
||||||
|
|
@ -124,6 +125,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
|
||||||
result.converters = @ []
|
result.converters = @ []
|
||||||
result.filename = nimfile
|
result.filename = nimfile
|
||||||
IntSetInit(result.includedFiles)
|
IntSetInit(result.includedFiles)
|
||||||
|
initStrTable(result.userPragmas)
|
||||||
|
|
||||||
proc addConverter(c: PContext, conv: PSym) =
|
proc addConverter(c: PContext, conv: PSym) =
|
||||||
var L = len(c.converters)
|
var L = len(c.converters)
|
||||||
|
|
|
||||||
|
|
@ -708,7 +708,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
pushOwner(s)
|
pushOwner(s)
|
||||||
s.options = gOptions
|
s.options = gOptions
|
||||||
if n.sons[codePos] != nil:
|
if n.sons[codePos] != nil:
|
||||||
if {sfImportc, sfBorrow} * s.flags != {}:
|
# for DLL generation, it is annoying to check for sfImportc!
|
||||||
|
if sfBorrow in s.flags:
|
||||||
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||||
if (n.sons[genericParamsPos] == nil):
|
if (n.sons[genericParamsPos] == nil):
|
||||||
c.p = newProcCon(s)
|
c.p = newProcCon(s)
|
||||||
|
|
@ -720,6 +721,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||||
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
||||||
n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos])
|
n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos])
|
||||||
|
if sfImportc in s.flags:
|
||||||
|
# so we just ignore the body after semantic checking for importc:
|
||||||
|
n.sons[codePos] = nil
|
||||||
else:
|
else:
|
||||||
if proto != nil: liMessage(n.info, errImplOfXexpected, proto.name.s)
|
if proto != nil: liMessage(n.info, errImplOfXexpected, proto.name.s)
|
||||||
if {sfImportc, sfBorrow} * s.flags == {}: incl(s.flags, sfForward)
|
if {sfImportc, sfBorrow} * s.flags == {}: incl(s.flags, sfForward)
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,11 @@ type
|
||||||
wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
|
wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
|
||||||
wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks,
|
wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks,
|
||||||
wBoundchecks, wOverflowchecks, wNilchecks,
|
wBoundchecks, wOverflowchecks, wNilchecks,
|
||||||
wFloatchecks, wNanChecks, wInfChecks,
|
wFloatchecks, wNanChecks, wInfChecks,
|
||||||
wAssertions, wWarnings, wW,
|
wAssertions, wWarnings, wW,
|
||||||
wHints, wOptimization, wSpeed, wSize, wNone, wPath, wP, wD, wU, wDebuginfo,
|
wHints, wOptimization, wSpeed, wSize, wNone, wPath, wP, wD, wU, wDebuginfo,
|
||||||
wCompileonly, wNolinking, wForcebuild, wF, wDeadCodeElim, wSafecode,
|
wCompileonly, wNolinking, wForcebuild, wF, wDeadCodeElim, wSafecode,
|
||||||
|
wPragma,
|
||||||
wCompileTime, wGc, wRefc, wBoehm, wA, wOpt, wO, wApp, wConsole, wGui,
|
wCompileTime, wGc, wRefc, wBoehm, wA, wOpt, wO, wApp, wConsole, wGui,
|
||||||
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
||||||
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||||
|
|
@ -53,7 +54,7 @@ type
|
||||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
||||||
wAcyclic, wIndex,
|
wAcyclic, wIndex,
|
||||||
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
|
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
|
||||||
wDoc, wPas, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy,
|
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy,
|
||||||
wRst2html, wRst2tex, wI,
|
wRst2html, wRst2tex, wI,
|
||||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
|
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
|
||||||
|
|
||||||
|
|
@ -91,6 +92,7 @@ const
|
||||||
"assertions", "warnings", "w", "hints",
|
"assertions", "warnings", "w", "hints",
|
||||||
"optimization", "speed", "size", "none", "path", "p", "d", "u", "debuginfo",
|
"optimization", "speed", "size", "none", "path", "p", "d", "u", "debuginfo",
|
||||||
"compileonly", "nolinking", "forcebuild", "f", "deadcodeelim", "safecode",
|
"compileonly", "nolinking", "forcebuild", "f", "deadcodeelim", "safecode",
|
||||||
|
"pragma",
|
||||||
"compiletime", "gc", "refc", "boehm", "a", "opt", "o", "app", "console",
|
"compiletime", "gc", "refc", "boehm", "a", "opt", "o", "app", "console",
|
||||||
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
||||||
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
||||||
|
|
@ -98,7 +100,7 @@ const
|
||||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints",
|
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints",
|
||||||
"nomain", "subschar", "acyclic", "index",
|
"nomain", "subschar", "acyclic", "index",
|
||||||
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
|
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
|
||||||
"pretty", "doc", "pas", "gendepend", "listdef", "check", "parse", "scan",
|
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
|
||||||
"boot", "lazy", "rst2html", "rst2tex", "i",
|
"boot", "lazy", "rst2html", "rst2tex", "i",
|
||||||
"write", "putenv", "prependenv", "appendenv", "threadvar"]
|
"write", "putenv", "prependenv", "appendenv", "threadvar"]
|
||||||
|
|
||||||
|
|
|
||||||
7
tests/accept/compile/tuserpragma.nim
Normal file
7
tests/accept/compile/tuserpragma.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
{.pragma: rtl, cdecl, exportc.}
|
||||||
|
|
||||||
|
proc myproc(x, y: int): int {.rtl} =
|
||||||
|
nil
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,6 +42,7 @@ Additions
|
||||||
- Implemented implicit type arguments for generics.
|
- Implemented implicit type arguments for generics.
|
||||||
- Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
|
- Implemented ``{.size: sizeof(cint).}`` pragma for enum types. This is useful
|
||||||
for interfacing with C.
|
for interfacing with C.
|
||||||
|
- Implemented ``{.pragma.}`` pragma for user defined pragmas.
|
||||||
|
|
||||||
|
|
||||||
2010-03-14 Version 0.8.8 released
|
2010-03-14 Version 0.8.8 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue