implemented user-defined pragmas

This commit is contained in:
Andreas Rumpf 2010-07-23 20:17:12 +02:00
commit 804e2ac89d
11 changed files with 237 additions and 151 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View 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);

View file

@ -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)

View file

@ -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):

View file

@ -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)

View file

@ -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)

View file

@ -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"]

View file

@ -0,0 +1,7 @@
{.pragma: rtl, cdecl, exportc.}
proc myproc(x, y: int): int {.rtl} =
nil

View file

@ -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