preparations for making 'closure' the default calling convention for proc types

This commit is contained in:
Araq 2012-07-16 23:00:57 +02:00
commit 8d99753d63
36 changed files with 117 additions and 102 deletions

View file

@ -35,9 +35,10 @@ proc ObjectSetContainsOrIncl*(t: var TObjectSet, obj: PObject): bool
proc TablePut*(t: var TTable, key, val: PObject) proc TablePut*(t: var TTable, key, val: PObject)
proc TableGet*(t: TTable, key: PObject): PObject proc TableGet*(t: TTable, key: PObject): PObject
type type
TCmpProc* = proc (key, closure: PObject): bool # should return true if found TCmpProc* = proc (key, closure: PObject): bool {.nimcall.} # true if found
proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObject proc TableSearch*(t: TTable, key, closure: PObject,
comparator: TCmpProc): PObject
# return val as soon as comparator returns true; if this never happens, # return val as soon as comparator returns true; if this never happens,
# nil is returned # nil is returned

View file

@ -22,7 +22,7 @@ type
head*, tail*: PListEntry head*, tail*: PListEntry
Counter*: int Counter*: int
TCompareProc* = proc (entry: PListEntry, closure: Pointer): bool TCompareProc* = proc (entry: PListEntry, closure: Pointer): bool {.nimcall.}
proc InitLinkedList*(list: var TLinkedList) = proc InitLinkedList*(list: var TLinkedList) =
list.Counter = 0 list.Counter = 0

View file

@ -102,7 +102,7 @@ type
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored, warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored,
warnXisPassedToProcVar, warnAnalysisLoophole, warnXisPassedToProcVar, warnAnalysisLoophole,
warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitNarrowing, warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure,
warnUser, warnUser,
hintSuccess, hintSuccessX, hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
@ -345,7 +345,7 @@ const
warnAnalysisLoophole: "thread analysis incomplete due to unkown call '$1' [AnalysisLoophole]", warnAnalysisLoophole: "thread analysis incomplete due to unkown call '$1' [AnalysisLoophole]",
warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]", warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]",
warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]", warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]",
warnImplicitNarrowing: "implicit narrowing conversion: '$1' [ImplicitNarrowing]", warnImplicitClosure: "implicit closure convention: '$1' [ImplicitClosure]",
warnUser: "$1 [User]", warnUser: "$1 [User]",
hintSuccess: "operation successful [Success]", hintSuccess: "operation successful [Success]",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#) [SuccessX]", hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#) [SuccessX]",
@ -370,7 +370,7 @@ const
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
"CommentXIgnored", "XisPassedToProcVar", "CommentXIgnored", "XisPassedToProcVar",
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
"ImplicitNarrowing,", "User"] "ImplicitClosure,", "User"]
HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",

View file

@ -1164,7 +1164,7 @@ proc newCommentStmt(p: var TParser): PNode =
result.info.line = result.info.line - int16(1) result.info.line = result.info.line - int16(1)
type type
TDefParser = proc (p: var TParser): PNode TDefParser = proc (p: var TParser): PNode {.nimcall.}
proc parseSection(p: var TParser, kind: TNodeKind, proc parseSection(p: var TParser, kind: TNodeKind,
defparser: TDefParser): PNode = defparser: TDefParser): PNode =

View file

@ -26,11 +26,11 @@ type
PPassContext* = ref TPassContext PPassContext* = ref TPassContext
TPass* = tuple[ TPass* = tuple[
open: proc (module: PSym, filename: string): PPassContext, open: proc (module: PSym, filename: string): PPassContext {.nimcall.},
openCached: proc (module: PSym, filename: string, openCached: proc (module: PSym, filename: string,
rd: PRodReader): PPassContext, rd: PRodReader): PPassContext {.nimcall.},
close: proc (p: PPassContext, n: PNode): PNode, close: proc (p: PPassContext, n: PNode): PNode {.nimcall.},
process: proc (p: PPassContext, topLevelStmt: PNode): PNode] process: proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}]
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional # a pass is a tuple of procedure vars ``TPass.close`` may produce additional
# nodes. These are passed to the other close procedures. # nodes. These are passed to the other close procedures.
@ -47,8 +47,8 @@ proc processModule*(module: PSym, filename: string, stream: PLLStream,
# the semantic checker needs these: # the semantic checker needs these:
var var
gImportModule*: proc (filename: string): PSym gImportModule*: proc (filename: string): PSym {.nimcall.}
gIncludeFile*: proc (filename: string): PNode gIncludeFile*: proc (filename: string): PNode {.nimcall.}
# implementation # implementation

View file

@ -66,9 +66,9 @@ type
converters*: TSymSeq # sequence of converters converters*: TSymSeq # sequence of converters
optionStack*: TLinkedList optionStack*: TLinkedList
libs*: TLinkedList # all libs used by this module libs*: TLinkedList # all libs used by this module
semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode # XXX bite the bullet semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
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 userPragmas*: TStrTable

View file

@ -566,7 +566,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
block addImplicitGeneric: block addImplicitGeneric:
# is this a bindOnce type class already present in the param list? # is this a bindOnce type class already present in the param list?
for i in countup(0, genericParams.len - 1): for i in countup(0, genericParams.len - 1):
if genericParams.sons[i].sym.name == paramTypId: if genericParams.sons[i].sym.name.id == paramTypId.id:
result = genericParams.sons[i].typ result = genericParams.sons[i].typ
break addImplicitGeneric break addImplicitGeneric
@ -808,7 +808,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
# dummy symbol for `pragma`: # dummy symbol for `pragma`:
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c) var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
s.typ = result s.typ = result
pragma(c, s, n.sons[1], procTypePragmas) if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
if result.callConv == ccDefault:
#result.callConv = ccClosure
Message(n.info, warnImplicitClosure, renderTree(n))
else:
pragma(c, s, n.sons[1], procTypePragmas)
closeScope(c.tab) closeScope(c.tab)
of nkEnumTy: result = semEnum(c, n, prev) of nkEnumTy: result = semEnum(c, n, prev)
of nkType: result = n.typ of nkType: result = n.typ

View file

@ -457,7 +457,9 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
case a.kind case a.kind
of tyPointer: result = isEqual of tyPointer: result = isEqual
of tyNil: result = isSubtype of tyNil: result = isSubtype
of tyPtr, tyProc, tyCString: result = isConvertible of tyProc:
if a.callConv != ccClosure: result = isConvertible
of tyPtr, tyCString: result = isConvertible
else: nil else: nil
of tyString: of tyString:
case a.kind case a.kind

View file

@ -640,14 +640,6 @@ proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
cnst.len != 0 cnst.len != 0
proc warnNarrowingConversion(n: PNode) =
if n.kind == nkHiddenStdConv:
var dest = skipTypes(n.typ, abstractVarRange)
var source = skipTypes(n.sons[1].typ, abstractVarRange)
if source.kind == tyInt and
source.size > dest.size and n.sons[1].kind != nkIntLit:
Message(n.info, warnImplicitNarrowing, renderTree(n.sons[1]))
proc transform(c: PTransf, n: PNode): PTransNode = proc transform(c: PTransf, n: PNode): PTransNode =
case n.kind case n.kind
of nkSym: of nkSym:

View file

@ -24,9 +24,9 @@ proc getProcHeader*(sym: PSym): string
proc base*(t: PType): PType proc base*(t: PType): PType
# ------------------- type iterator: ---------------------------------------- # ------------------- type iterator: ----------------------------------------
type type
TTypeIter* = proc (t: PType, closure: PObject): bool # should return true if the iteration should stop TTypeIter* = proc (t: PType, closure: PObject): bool {.nimcall.} # true if iteration should stop
TTypeMutator* = proc (t: PType, closure: PObject): PType # copy t and mutate it TTypeMutator* = proc (t: PType, closure: PObject): PType {.nimcall.} # copy t and mutate it
TTypePredicate* = proc (t: PType): bool TTypePredicate* = proc (t: PType): bool {.nimcall.}
proc IterOverType*(t: PType, iter: TTypeIter, closure: PObject): bool proc IterOverType*(t: PType, iter: TTypeIter, closure: PObject): bool
# Returns result of `iter`. # Returns result of `iter`.

View file

@ -1177,6 +1177,17 @@ that expects a proc of the calling convention ``closure``.
Nimrod supports these `calling conventions`:idx:\: Nimrod supports these `calling conventions`:idx:\:
`nimcall`:idx:
is the default convention used for a Nimrod **proc**. It is the
same as ``fastcall``, but only for C compilers that support ``fastcall``.
`closure`:idx:
is the default calling convention for a **procedural type** that lacks
any pragma annotations. It indicates that the procedure has a hidden
implicit parameter (an *environment*). Proc vars that have the calling
convention ``closure`` take up two machine words: One for the proc pointer
and another one for the pointer to implicitely passed environment.
`stdcall`:idx: `stdcall`:idx:
This the stdcall convention as specified by Microsoft. The generated C This the stdcall convention as specified by Microsoft. The generated C
procedure is declared with the ``__stdcall`` keyword. procedure is declared with the ``__stdcall`` keyword.
@ -1203,16 +1214,6 @@ Nimrod supports these `calling conventions`:idx:\:
Fastcall means different things to different C compilers. One gets whatever Fastcall means different things to different C compilers. One gets whatever
the C ``__fastcall`` means. the C ``__fastcall`` means.
`nimcall`:idx:
Nimcall is the default convention used for Nimrod procedures. It is the
same as ``fastcall``, but only for C compilers that support ``fastcall``.
`closure`:idx:
indicates that the procedure has a hidden implicit parameter
(an *environment*). Proc vars that have the calling convention ``closure``
take up two machine words: One for the proc pointer and another one for
the pointer to implicitely passed environment.
`syscall`:idx: `syscall`:idx:
The syscall convention is the same as ``__syscall`` in C. It is used for The syscall convention is the same as ``__syscall`` in C. It is used for
interrupts. interrupts.

View file

@ -56,7 +56,7 @@ const
onlySafeCode = true onlySafeCode = true
proc merge[T](a, b: var openArray[T], lo, m, hi: int, proc merge[T](a, b: var openArray[T], lo, m, hi: int,
cmp: proc (x, y: T): int, order: TSortOrder) = cmp: proc (x, y: T): int {.closure.}, order: TSortOrder) =
template `<-` (a, b: expr) = template `<-` (a, b: expr) =
when false: when false:
a = b a = b
@ -102,7 +102,7 @@ proc merge[T](a, b: var openArray[T], lo, m, hi: int,
if k < j: copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k)) if k < j: copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k))
proc sort*[T](a: var openArray[T], proc sort*[T](a: var openArray[T],
cmp: proc (x, y: T): int, cmp: proc (x, y: T): int {.closure.},
order = TSortOrder.Ascending) = order = TSortOrder.Ascending) =
## Default Nimrod sort. The sorting is guaranteed to be stable and ## Default Nimrod sort. The sorting is guaranteed to be stable and
## the worst case is guaranteed to be O(n log n). ## the worst case is guaranteed to be O(n log n).

View file

@ -33,14 +33,14 @@ type
TDelegate = object TDelegate = object
deleVal*: PObject deleVal*: PObject
handleRead*: proc (h: PObject) handleRead*: proc (h: PObject) {.nimcall.}
handleWrite*: proc (h: PObject) handleWrite*: proc (h: PObject) {.nimcall.}
handleConnect*: proc (h: PObject) handleConnect*: proc (h: PObject) {.nimcall.}
handleAccept*: proc (h: PObject) handleAccept*: proc (h: PObject) {.nimcall.}
getSocket*: proc (h: PObject): tuple[info: TInfo, sock: TSocket] getSocket*: proc (h: PObject): tuple[info: TInfo, sock: TSocket] {.nimcall.}
task*: proc (h: PObject) task*: proc (h: PObject) {.nimcall.}
mode*: TMode mode*: TMode
PDelegate* = ref TDelegate PDelegate* = ref TDelegate
@ -56,10 +56,10 @@ type
userArg: PObject userArg: PObject
handleRead*: proc (s: PAsyncSocket, arg: PObject) handleRead*: proc (s: PAsyncSocket, arg: PObject) {.nimcall.}
handleConnect*: proc (s: PAsyncSocket, arg: PObject) handleConnect*: proc (s: PAsyncSocket, arg: PObject) {.nimcall.}
handleAccept*: proc (s: PAsyncSocket, arg: PObject) handleAccept*: proc (s: PAsyncSocket, arg: PObject) {.nimcall.}
lineBuffer: TaintedString ## Temporary storage for ``recvLine`` lineBuffer: TaintedString ## Temporary storage for ``recvLine``

View file

@ -39,14 +39,14 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
newSeq(result, m) newSeq(result, m)
for i in 0 .. m-1: result[i] = (seq1[i], seq2[i]) for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool): T = iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
## Iterates through a sequence and yields every item that fulfills the ## Iterates through a sequence and yields every item that fulfills the
## predicate. ## predicate.
for i in countup(0, len(seq1) -1): for i in countup(0, len(seq1) -1):
var item = seq1[i] var item = seq1[i]
if pred(item): yield seq1[i] if pred(item): yield seq1[i]
proc filter*[T](seq1: seq[T], pred: proc(item: T): bool): seq[T] = proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] =
## Returns all items in a sequence that fulfilled the predicate. ## Returns all items in a sequence that fulfilled the predicate.
accumulateResult(filter(seq1, pred)) accumulateResult(filter(seq1, pred))

View file

@ -11,7 +11,8 @@
## ##
## This module implements an event system that is not dependant on external ## This module implements an event system that is not dependant on external
## graphical toolkits. It was originally called ``NimEE`` because ## graphical toolkits. It was originally called ``NimEE`` because
## it was inspired by Python's PyEE module. There are two ways you can use events: one is a python-inspired way; the other is more of a C-style way. ## it was inspired by Python's PyEE module. There are two ways you can use
## events: one is a python-inspired way; the other is more of a C-style way.
## ##
## .. code-block:: Nimrod ## .. code-block:: Nimrod
## var ee = initEventEmitter() ## var ee = initEventEmitter()
@ -44,22 +45,21 @@ type
proc initEventHandler*(name: string): TEventHandler = proc initEventHandler*(name: string): TEventHandler =
## Initializes an EventHandler with the specified name and returns it. ## Initializes an EventHandler with the specified name and returns it.
#new(result)
result.handlers = @[] result.handlers = @[]
result.name = name result.name = name
proc addHandler*(handler: var TEventHandler, func: proc(e: TEventArgs)) = proc addHandler*(handler: var TEventHandler, func: proc(e: TEventArgs) {.closure.}) =
## Adds the callback to the specified event handler. ## Adds the callback to the specified event handler.
handler.handlers.add(func) handler.handlers.add(func)
proc removeHandler*(handler: var TEventHandler, func: proc(e: TEventArgs)) = proc removeHandler*(handler: var TEventHandler, func: proc(e: TEventArgs) {.closure.}) =
## Removes the callback from the specified event handler. ## Removes the callback from the specified event handler.
for i in countup(0, len(handler.handlers) -1): for i in countup(0, len(handler.handlers) -1):
if func == handler.handlers[i]: if func == handler.handlers[i]:
handler.handlers.del(i) handler.handlers.del(i)
break break
proc containsHandler*(handler: var TEventHandler, func: proc(e: TEventArgs)): bool = proc containsHandler*(handler: var TEventHandler, func: proc(e: TEventArgs) {.closure.}): bool =
## Checks if a callback is registered to this event handler. ## Checks if a callback is registered to this event handler.
return handler.handlers.contains(func) return handler.handlers.contains(func)
@ -73,7 +73,7 @@ proc getEventhandler(emitter: var TEventEmitter, event: string): int =
if emitter.s[k].name == event: return k if emitter.s[k].name == event: return k
return -1 return -1
proc on*(emitter: var TEventEmitter, event: string, func: proc(e: TEventArgs)) = proc on*(emitter: var TEventEmitter, event: string, func: proc(e: TEventArgs) {.closure.}) =
## Assigns a event handler with the specified callback. If the event ## Assigns a event handler with the specified callback. If the event
## doesn't exist, it will be created. ## doesn't exist, it will be created.
var i = getEventHandler(emitter, event) var i = getEventHandler(emitter, event)
@ -99,5 +99,4 @@ proc emit*(emitter: var TEventEmitter, event: string, args: TEventArgs) =
proc initEventEmitter*(): TEventEmitter = proc initEventEmitter*(): TEventEmitter =
## Creates and returns a new EventEmitter. ## Creates and returns a new EventEmitter.
#new(result)
result.s = @[] result.s = @[]

View file

@ -347,7 +347,8 @@ proc close*(s: TServer) =
## closes the server (and the socket the server uses). ## closes the server (and the socket the server uses).
close(s.socket) close(s.socket)
proc run*(handleRequest: proc (client: TSocket, path, query: string): bool, proc run*(handleRequest: proc (client: TSocket,
path, query: string): bool {.closure.},
port = TPort(80)) = port = TPort(80)) =
## encapsulates the server object and main loop ## encapsulates the server object and main loop
var s: TServer var s: TServer

View file

@ -23,13 +23,14 @@ type
## here shouldn't be used directly. They are ## here shouldn't be used directly. They are
## accessible so that a stream implementation ## accessible so that a stream implementation
## can override them. ## can override them.
closeImpl*: proc (s: PStream) closeImpl*: proc (s: PStream) {.nimcall.}
atEndImpl*: proc (s: PStream): bool atEndImpl*: proc (s: PStream): bool {.nimcall.}
setPositionImpl*: proc (s: PStream, pos: int) setPositionImpl*: proc (s: PStream, pos: int) {.nimcall.}
getPositionImpl*: proc (s: PStream): int getPositionImpl*: proc (s: PStream): int {.nimcall.}
readDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int): int readDataImpl*: proc (s: PStream, buffer: pointer,
writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) bufLen: int): int {.nimcall.}
flushImpl*: proc (s: PStream) writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall.}
flushImpl*: proc (s: PStream) {.nimcall.}
proc flush*(s: PStream) = proc flush*(s: PStream) =
## flushes the buffers that the stream `s` might use. ## flushes the buffers that the stream `s` might use.

View file

@ -111,7 +111,7 @@ proc new*[T](a: var ref T) {.magic: "New", noSideEffect.}
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
## leaked implementation detail. Do not use. ## leaked implementation detail. Do not use.
proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {. proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
magic: "NewFinalize", noSideEffect.} magic: "NewFinalize", noSideEffect.}
## creates a new object of type ``T`` and returns a safe (traced) ## creates a new object of type ``T`` and returns a safe (traced)
## reference to it in ``a``. When the garbage collector frees the object, ## reference to it in ``a``. When the garbage collector frees the object,
@ -1416,13 +1416,13 @@ proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
result = s[L] result = s[L]
setLen(s, L) setLen(s, L)
proc each*[T, S](data: openArray[T], op: proc (x: T): S): seq[S] = proc each*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] =
## The well-known ``map`` operation from functional programming. Applies ## The well-known ``map`` operation from functional programming. Applies
## `op` to every item in `data` and returns the result as a sequence. ## `op` to every item in `data` and returns the result as a sequence.
newSeq(result, data.len) newSeq(result, data.len)
for i in 0..data.len-1: result[i] = op(data[i]) for i in 0..data.len-1: result[i] = op(data[i])
proc each*[T](data: var openArray[T], op: proc (x: var T)) = proc each*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) =
## The well-known ``map`` operation from functional programming. Applies ## The well-known ``map`` operation from functional programming. Applies
## `op` to every item in `data`. ## `op` to every item in `data`.
for i in 0..data.len-1: op(data[i]) for i in 0..data.len-1: op(data[i])
@ -1567,11 +1567,11 @@ const nimrodStackTrace = compileOption("stacktrace")
# of the code # of the code
var var
dbgLineHook*: proc () dbgLineHook*: proc () {.nimcall.}
## set this variable to provide a procedure that should be called before ## set this variable to provide a procedure that should be called before
## each executed instruction. This should only be used by debuggers! ## each executed instruction. This should only be used by debuggers!
## Only code compiled with the ``debugger:on`` switch calls this hook. ## Only code compiled with the ``debugger:on`` switch calls this hook.
globalRaiseHook*: proc (e: ref E_Base): bool globalRaiseHook*: proc (e: ref E_Base): bool {.nimcall.}
## with this hook you can influence exception handling on a global level. ## with this hook you can influence exception handling on a global level.
## If not nil, every 'raise' statement ends up calling this hook. Ordinary ## If not nil, every 'raise' statement ends up calling this hook. Ordinary
## application code should never set this hook! You better know what you ## application code should never set this hook! You better know what you
@ -1579,7 +1579,7 @@ var
## exception is caught and does not propagate further through the call ## exception is caught and does not propagate further through the call
## stack. ## stack.
localRaiseHook* {.threadvar.}: proc (e: ref E_Base): bool localRaiseHook* {.threadvar.}: proc (e: ref E_Base): bool {.nimcall.}
## with this hook you can influence exception handling on a ## with this hook you can influence exception handling on a
## thread local level. ## thread local level.
## If not nil, every 'raise' statement ends up calling this hook. Ordinary ## If not nil, every 'raise' statement ends up calling this hook. Ordinary
@ -1587,7 +1587,7 @@ var
## do when setting this. If ``localRaiseHook`` returns false, the exception ## do when setting this. If ``localRaiseHook`` returns false, the exception
## is caught and does not propagate further through the call stack. ## is caught and does not propagate further through the call stack.
outOfMemHook*: proc () outOfMemHook*: proc () {.nimcall.}
## set this variable to provide a procedure that should be called ## set this variable to provide a procedure that should be called
## in case of an `out of memory`:idx: event. The standard handler ## in case of an `out of memory`:idx: event. The standard handler
## writes an error message and terminates the program. `outOfMemHook` can ## writes an error message and terminates the program. `outOfMemHook` can

View file

@ -45,7 +45,7 @@ type
TWalkOp = enum TWalkOp = enum
waZctDecRef, waPush, waCycleDecRef waZctDecRef, waPush, waCycleDecRef
TFinalizer {.compilerproc.} = proc (self: pointer) TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall.}
# A ref type can have a finalizer that is called before the object's # A ref type can have a finalizer that is called before the object's
# storage is freed. # storage is freed.

View file

@ -62,7 +62,7 @@ type # This should be he same as ast.TTypeKind
base: ptr TNimType base: ptr TNimType
node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
finalizer: pointer # the finalizer for the type finalizer: pointer # the finalizer for the type
marker: proc (p: pointer, op: int) # marker proc for GC marker: proc (p: pointer, op: int) {.nimcall.} # marker proc for GC
PNimType = ptr TNimType PNimType = ptr TNimType
# node.len may be the ``first`` element of a set # node.len may be the ``first`` element of a set

View file

@ -255,9 +255,9 @@ type
## that **must not** be part of a message! Use ## that **must not** be part of a message! Use
## a ``TThreadId`` for that. ## a ``TThreadId`` for that.
when TArg is void: when TArg is void:
dataFn: proc () dataFn: proc () {.nimcall.}
else: else:
dataFn: proc (m: TArg) dataFn: proc (m: TArg) {.nimcall.}
data: TArg data: TArg
TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses
## a pointer as a thread ID. ## a pointer as a thread ID.

View file

@ -419,7 +419,7 @@ type
pad32*: TFunction pad32*: TFunction
TEventListener* = proc (para1: PObject){.cdecl.} TEventListener* = proc (para1: PObject){.cdecl.}
TEventListenerInitProc* = proc () TEventListenerInitProc* = proc (){.cdecl.}
TEventListenerInit* = proc (para1: TEventListenerInitProc){.cdecl.} TEventListenerInit* = proc (para1: TEventListenerInitProc){.cdecl.}
PKeyEventStruct* = ptr TKeyEventStruct PKeyEventStruct* = ptr TKeyEventStruct
TKeyEventStruct*{.final, pure.} = object TKeyEventStruct*{.final, pure.} = object

View file

@ -291,7 +291,7 @@ type
PEvent* = ptr TEvent PEvent* = ptr TEvent
TEventFunc* = proc (event: PEvent, data: gpointer){.cdecl.} TEventFunc* = proc (event: PEvent, data: gpointer){.cdecl.}
PXEvent* = ptr TXEvent PXEvent* = ptr TXEvent
TXEvent* = proc () TXEvent* = proc () {.cdecl.}
PFilterReturn* = ptr TFilterReturn PFilterReturn* = ptr TFilterReturn
TFilterReturn* = enum TFilterReturn* = enum
FILTER_CONTINUE, FILTER_TRANSLATE, FILTER_REMOVE FILTER_CONTINUE, FILTER_TRANSLATE, FILTER_REMOVE
@ -775,7 +775,7 @@ type
PWindowObjectClass* = ptr TWindowObjectClass PWindowObjectClass* = ptr TWindowObjectClass
TWindowObjectClass* = object of TDrawableClass TWindowObjectClass* = object of TDrawableClass
window_invalidate_maybe_recurse_child_func* = proc (para1: PWindow, window_invalidate_maybe_recurse_child_func* = proc (para1: PWindow,
para2: gpointer): gboolean para2: gpointer): gboolean {.cdecl.}
proc TYPE_COLORMAP*(): GType proc TYPE_COLORMAP*(): GType
proc COLORMAP*(anObject: pointer): PColormap proc COLORMAP*(anObject: pointer): PColormap

View file

@ -2676,7 +2676,7 @@ when false:
proc g_critical*(format: cstring){.varargs.} proc g_critical*(format: cstring){.varargs.}
proc g_warning*(format: cstring){.varargs.} proc g_warning*(format: cstring){.varargs.}
type type
TGPrintFunc* = proc (str: cstring) TGPrintFunc* = proc (str: cstring){.cdecl, varargs.}
proc g_set_print_handler*(func: TGPrintFunc): TGPrintFunc{.cdecl, proc g_set_print_handler*(func: TGPrintFunc): TGPrintFunc{.cdecl,
dynlib: gliblib, importc: "g_set_print_handler".} dynlib: gliblib, importc: "g_set_print_handler".}

View file

@ -104,7 +104,7 @@ type
Tfree_callback* = proc (p: pointer){.cdecl.} Tfree_callback* = proc (p: pointer){.cdecl.}
Trealloc_callback* = proc (p: pointer, size: int): pointer{.cdecl.} Trealloc_callback* = proc (p: pointer, size: int): pointer{.cdecl.}
Tstrdup_callback* = proc (str: cstring): cstring{.cdecl.} Tstrdup_callback* = proc (str: cstring): cstring{.cdecl.}
Tcalloc_callback* = proc (nmemb: int, size: int): pointer Tcalloc_callback* = proc (nmemb: int, size: int): pointer{.noconv.}
Tinfotype* = enum Tinfotype* = enum
INFO_TEXT = 0, INFO_HEADER_IN, INFO_HEADER_OUT, INFO_DATA_IN, INFO_DATA_OUT, INFO_TEXT = 0, INFO_HEADER_IN, INFO_HEADER_OUT, INFO_DATA_IN, INFO_DATA_OUT,
INFO_SSL_DATA_IN, INFO_SSL_DATA_OUT, INFO_END INFO_SSL_DATA_IN, INFO_SSL_DATA_OUT, INFO_END

View file

@ -8,6 +8,8 @@
# #
{.deadCodeElim: on.} {.deadCodeElim: on.}
{.push, callconv: cdecl.}
when defined(Unix): when defined(Unix):
const const
lib = "libmysqlclient.so.15" lib = "libmysqlclient.so.15"
@ -1071,3 +1073,5 @@ proc INTERNAL_NUM_FIELD(f: Pst_mysql_field): bool =
proc reload(mysql: PMySQL): cint = proc reload(mysql: PMySQL): cint =
result = refresh(mysql, REFRESH_GRANT) result = refresh(mysql, REFRESH_GRANT)
{.pop.}

View file

@ -11,6 +11,11 @@
import import
GL GL
when defined(windows):
{.push, callconv: stdcall.}
else:
{.push, callconv: cdecl.}
when defined(windows): when defined(windows):
const const
dllname = "glu32.dll" dllname = "glu32.dll"
@ -326,4 +331,5 @@ const # Contours types -- obsolete!
GLU_ERROR* = GLU_TESS_ERROR GLU_ERROR* = GLU_TESS_ERROR
GLU_EDGE_FLAG* = GLU_TESS_EDGE_FLAG GLU_EDGE_FLAG* = GLU_TESS_EDGE_FLAG
{.pop.}
# implementation # implementation

View file

@ -1156,7 +1156,7 @@ proc PyWeakref_NewProxy*(ob, callback: PPyObject): PPyObject{.cdecl, importc, dy
proc PyWeakref_NewRef*(ob, callback: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} proc PyWeakref_NewRef*(ob, callback: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
proc PyWrapper_New*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.} proc PyWrapper_New*(ob1, ob2: PPyObject): PPyObject{.cdecl, importc, dynlib: dllname.}
proc PyBool_FromLong*(ok: int): PPyObject{.cdecl, importc, dynlib: dllname.} #- proc PyBool_FromLong*(ok: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-
proc Py_AtExit*(prc: proc ()): int{.cdecl, importc, dynlib: dllname.} #- proc Py_AtExit*(prc: proc () {.cdecl.}): int{.cdecl, importc, dynlib: dllname.} #-
#Py_Cleanup:procedure; cdecl, importc, dynlib: dllname; #Py_Cleanup:procedure; cdecl, importc, dynlib: dllname;
#- #-
proc Py_CompileString*(s1, s2: cstring, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #- proc Py_CompileString*(s1, s2: cstring, i: int): PPyObject{.cdecl, importc, dynlib: dllname.} #-

View file

@ -1279,7 +1279,6 @@ type # This is the system-independent thread info struc
TByteArray* = array[0..32767, int8] TByteArray* = array[0..32767, int8]
PWordArray* = ptr TWordArray PWordArray* = ptr TWordArray
TWordArray* = array[0..16383, int16] # Generic procedure pointer TWordArray* = array[0..16383, int16] # Generic procedure pointer
TProcedure* = proc ()
type TEventSeq = set[TEventKind] type TEventSeq = set[TEventKind]
template evconv(procName: expr, ptrName: typeDesc, assertions: TEventSeq): stmt {.immediate.} = template evconv(procName: expr, ptrName: typeDesc, assertions: TEventSeq): stmt {.immediate.} =

View file

@ -137,7 +137,7 @@ const
XrmEnumOneLevel* = 1 XrmEnumOneLevel* = 1
type type
funcbool* = proc (): TBool funcbool* = proc (): TBool {.cdecl.}
proc XrmEnumerateDatabase*(para1: TXrmDatabase, para2: TXrmNameList, proc XrmEnumerateDatabase*(para1: TXrmDatabase, para2: TXrmNameList,
para3: TXrmClassList, para4: int32, para5: funcbool, para3: TXrmClassList, para4: int32, para5: funcbool,

View file

@ -42,8 +42,8 @@ type
mwUnsupportedLanguage mwUnsupportedLanguage
TMsgHandler* = proc (filename: string, line, col: int, msgKind: TMsgKind, TMsgHandler* = proc (filename: string, line, col: int, msgKind: TMsgKind,
arg: string) ## what to do in case of an error arg: string) {.nimcall.} ## what to do in case of an error
TFindFileHandler* = proc (filename: string): string TFindFileHandler* = proc (filename: string): string {.nimcall.}
const const
messages: array [TMsgKind, string] = [ messages: array [TMsgKind, string] = [
@ -1356,7 +1356,7 @@ type
TDirFlag = enum TDirFlag = enum
hasArg, hasOptions, argIsFile, argIsWord hasArg, hasOptions, argIsFile, argIsWord
TDirFlags = set[TDirFlag] TDirFlags = set[TDirFlag]
TSectionParser = proc (p: var TRstParser): PRstNode TSectionParser = proc (p: var TRstParser): PRstNode {.nimcall.}
proc parseDirective(p: var TRstParser, flags: TDirFlags): PRstNode = proc parseDirective(p: var TRstParser, flags: TDirFlags): PRstNode =
result = newRstNode(rnDirective) result = newRstNode(rnDirective)

View file

@ -10,7 +10,8 @@ import
osproc, osproc,
cairowin32, cairoxlib, cairowin32, cairoxlib,
gl, glut, glu, glx, glext, wingl, gl, glut, glu, glx, glext, wingl,
lua, lualib, lauxlib, mysql, sqlite3, db_mongo, md5 lua, lualib, lauxlib, mysql, sqlite3, db_mongo, md5, asyncio, mimetypes,
cookies, events, ftpclient
writeln(stdout, "test compilation of binding modules") writeln(stdout, "test compilation of binding modules")

View file

@ -6,13 +6,13 @@ discard """
proc main = proc main =
const n = 30 const n = 30
for iterations in 0..50_000: for iterations in 0..50_000:
var s: seq[proc(): int {.closure.}] = @[] var s: seq[proc(): string {.closure.}] = @[]
for i in 0 .. n-1: for i in 0 .. n-1:
let ii = i let ii = i
s.add(proc(): int = return ii*ii) s.add(proc(): string = return $(ii*ii))
for i in 0 .. n-1: for i in 0 .. n-1:
let val = s[i]() let val = s[i]()
if val != i*i: echo "bug ", val if val != $(i*i): echo "bug ", val
if getOccupiedMem() > 3000_000: quit("still a leak!") if getOccupiedMem() > 3000_000: quit("still a leak!")
echo "success" echo "success"

View file

@ -7,20 +7,22 @@ import tables, lists
type type
TEventArgs = object of TObject TEventArgs = object of TObject
TEventEmitter = object of TObject TEventEmitter = object of TObject
events*: TTable[string, TDoublyLinkedList[proc(e: TEventArgs)]] events*: TTable[string, TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]]
proc emit*(emitter: TEventEmitter, event: string, args: TEventArgs) = proc emit*(emitter: TEventEmitter, event: string, args: TEventArgs) =
for func in nodes(emitter.events[event]): for func in nodes(emitter.events[event]):
func.value(args) #call function with args. func.value(args) #call function with args.
proc on*(emitter: var TEventEmitter, event: string, func: proc(e: TEventArgs)) = proc on*(emitter: var TEventEmitter, event: string,
func: proc(e: TEventArgs) {.nimcall.}) =
if not hasKey(emitter.events, event): if not hasKey(emitter.events, event):
var list: TDoublyLinkedList[proc(e: TEventArgs)] var list: TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]
add(emitter.events, event, list) #if not, add it. add(emitter.events, event, list) #if not, add it.
append(emitter.events.mget(event), func) append(emitter.events.mget(event), func)
proc initEmitter(emitter: var TEventEmitter) = proc initEmitter(emitter: var TEventEmitter) =
emitter.events = initTable[string, TDoublyLinkedList[proc(e: TEventArgs)]]() emitter.events = initTable[string,
TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]]()
var var
ee: TEventEmitter ee: TEventEmitter

View file

@ -16,8 +16,9 @@ New pragmas:
- fix remaining closure bugs: - fix remaining closure bugs:
- make toplevel but in a scope vars local; make procs there inner procs - make toplevel but in a scope vars local; make procs there inner procs
- fix evals.nim with closures - fix evals.nim with closures
- proc types shall have closure calling convention per default
- implement "closure tuple consists of a single 'ref'" optimization - implement "closure tuple consists of a single 'ref'" optimization
- make closure default calling convention for proc types
- fix '==' for closures
- document 'do' notation - document 'do' notation
- rethink the syntax: distinction between expr and stmt is unfortunate; - rethink the syntax: distinction between expr and stmt is unfortunate;