made large parts of the stdlib gcsafe
This commit is contained in:
parent
be6474af63
commit
e6d17e6273
21 changed files with 138 additions and 113 deletions
|
|
@ -118,7 +118,7 @@ type
|
||||||
warnNilStatement, warnAnalysisLoophole,
|
warnNilStatement, warnAnalysisLoophole,
|
||||||
warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure,
|
warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure,
|
||||||
warnEachIdentIsTuple, warnShadowIdent,
|
warnEachIdentIsTuple, warnShadowIdent,
|
||||||
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe,
|
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
|
||||||
warnUninit, warnGcMem, warnUser,
|
warnUninit, warnGcMem, warnUser,
|
||||||
hintSuccess, hintSuccessX,
|
hintSuccess, hintSuccessX,
|
||||||
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
|
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
|
||||||
|
|
@ -387,6 +387,7 @@ const
|
||||||
warnProveField: "cannot prove that field '$1' is accessible [ProveField]",
|
warnProveField: "cannot prove that field '$1' is accessible [ProveField]",
|
||||||
warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]",
|
warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]",
|
||||||
warnGcUnsafe: "not GC-safe: '$1' [GcUnsafe]",
|
warnGcUnsafe: "not GC-safe: '$1' [GcUnsafe]",
|
||||||
|
warnGcUnsafe2: "cannot prove '$1' is GC-safe. This will become a compile time error in the future.",
|
||||||
warnUninit: "'$1' might not have been initialized [Uninit]",
|
warnUninit: "'$1' might not have been initialized [Uninit]",
|
||||||
warnGcMem: "'$1' uses GC'ed memory [GcMem]",
|
warnGcMem: "'$1' uses GC'ed memory [GcMem]",
|
||||||
warnUser: "$1 [User]",
|
warnUser: "$1 [User]",
|
||||||
|
|
@ -408,7 +409,7 @@ const
|
||||||
hintUser: "$1 [User]"]
|
hintUser: "$1 [User]"]
|
||||||
|
|
||||||
const
|
const
|
||||||
WarningsToStr*: array[0..25, string] = ["CannotOpenFile", "OctalEscape",
|
WarningsToStr*: array[0..26, string] = ["CannotOpenFile", "OctalEscape",
|
||||||
"XIsNeverRead", "XmightNotBeenInit",
|
"XIsNeverRead", "XmightNotBeenInit",
|
||||||
"Deprecated", "ConfigDeprecated",
|
"Deprecated", "ConfigDeprecated",
|
||||||
"SmallLshouldNotBeUsed", "UnknownMagic",
|
"SmallLshouldNotBeUsed", "UnknownMagic",
|
||||||
|
|
@ -416,7 +417,7 @@ const
|
||||||
"CommentXIgnored", "NilStmt",
|
"CommentXIgnored", "NilStmt",
|
||||||
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
|
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
|
||||||
"ImplicitClosure", "EachIdentIsTuple", "ShadowIdent",
|
"ImplicitClosure", "EachIdentIsTuple", "ShadowIdent",
|
||||||
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "Uninit",
|
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
|
||||||
"GcMem", "User"]
|
"GcMem", "User"]
|
||||||
|
|
||||||
HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong",
|
HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong",
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ 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}
|
wBorrow, wGcSafe}
|
||||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||||
wImportCpp, wImportObjC, wError}
|
wImportCpp, wImportObjC, wError}
|
||||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||||
|
|
@ -690,7 +690,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
if sym.typ != nil: incl(sym.typ.flags, tfThread)
|
if sym.typ != nil: incl(sym.typ.flags, tfThread)
|
||||||
of wGcSafe:
|
of wGcSafe:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
incl(sym.flags, sfThread)
|
if sym.kind != skType: incl(sym.flags, sfThread)
|
||||||
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
|
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
of wPacked:
|
of wPacked:
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,8 @@ proc useVar(a: PEffects, n: PNode) =
|
||||||
if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind == skVar:
|
if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind == skVar:
|
||||||
when trackGlobals:
|
when trackGlobals:
|
||||||
a.addUse(copyNode(n))
|
a.addUse(copyNode(n))
|
||||||
if tfHasGCedMem in s.typ.flags or s.typ.isGCedMem:
|
if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and
|
||||||
|
tfGcSafe notin s.typ.flags:
|
||||||
message(n.info, warnGcUnsafe, renderTree(n))
|
message(n.info, warnGcUnsafe, renderTree(n))
|
||||||
a.gcUnsafe = true
|
a.gcUnsafe = true
|
||||||
|
|
||||||
|
|
@ -517,6 +518,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
addEffect(tracked, createRaise(n))
|
addEffect(tracked, createRaise(n))
|
||||||
addTag(tracked, createTag(n))
|
addTag(tracked, createTag(n))
|
||||||
when trackGlobals: addUse(tracked, createAnyGlobal(n))
|
when trackGlobals: addUse(tracked, createAnyGlobal(n))
|
||||||
|
# XXX handle 'gcsafe' properly for callbacks!
|
||||||
else:
|
else:
|
||||||
mergeEffects(tracked, effectList.sons[exceptionEffects], n)
|
mergeEffects(tracked, effectList.sons[exceptionEffects], n)
|
||||||
mergeTags(tracked, effectList.sons[tagEffects], n)
|
mergeTags(tracked, effectList.sons[tagEffects], n)
|
||||||
|
|
@ -704,7 +706,8 @@ proc trackProc*(s: PSym, body: PNode) =
|
||||||
"uses an unlisted global variable: ", hints=on, symbolPredicate)
|
"uses an unlisted global variable: ", hints=on, symbolPredicate)
|
||||||
effects.sons[usesEffects] = usesSpec
|
effects.sons[usesEffects] = usesSpec
|
||||||
if sfThread in s.flags and t.gcUnsafe:
|
if sfThread in s.flags and t.gcUnsafe:
|
||||||
localError(s.info, "'$1' is not GC-safe" % s.name.s)
|
localError(s.info, warnGcUnsafe2, s.name.s)
|
||||||
|
#localError(s.info, "'$1' is not GC-safe" % s.name.s)
|
||||||
if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
|
if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
|
||||||
|
|
||||||
proc trackTopLevelStmt*(module: PSym; n: PNode) =
|
proc trackTopLevelStmt*(module: PSym; n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
## This module contains the interface to the compiler's abstract syntax
|
## This module contains the interface to the compiler's abstract syntax
|
||||||
## tree (`AST`:idx:). Macros operate on this tree.
|
## tree (`AST`:idx:). Macros operate on this tree.
|
||||||
|
|
@ -109,19 +110,20 @@ const
|
||||||
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
|
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
|
||||||
nnkCallStrLit}
|
nnkCallStrLit}
|
||||||
|
|
||||||
proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
|
proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.}
|
||||||
## get `n`'s `i`'th child.
|
## get `n`'s `i`'th child.
|
||||||
|
|
||||||
proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild",
|
||||||
|
noSideEffect.}
|
||||||
## set `n`'s `i`'th child to `child`.
|
## set `n`'s `i`'th child to `child`.
|
||||||
|
|
||||||
proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent", noSideEffect.}
|
||||||
## constructs an identifier from the string `s`
|
## constructs an identifier from the string `s`
|
||||||
|
|
||||||
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr", noSideEffect.}
|
||||||
## converts a Nimrod identifier to a string
|
## converts a Nimrod identifier to a string
|
||||||
|
|
||||||
proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr".}
|
proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr", noSideEffect.}
|
||||||
## converts a Nimrod symbol to a string
|
## converts a Nimrod symbol to a string
|
||||||
|
|
||||||
proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
||||||
|
|
@ -130,35 +132,36 @@ proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
||||||
proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
|
proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
|
||||||
## compares two Nimrod nodes
|
## compares two Nimrod nodes
|
||||||
|
|
||||||
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
proc len*(n: PNimrodNode): int {.magic: "NLen", noSideEffect.}
|
||||||
## returns the number of children of `n`.
|
## returns the number of children of `n`.
|
||||||
|
|
||||||
proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable.}
|
proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable,
|
||||||
|
noSideEffect.}
|
||||||
## Adds the `child` to the `father` node. Returns the
|
## Adds the `child` to the `father` node. Returns the
|
||||||
## father node so that calls can be nested.
|
## father node so that calls can be nested.
|
||||||
|
|
||||||
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
|
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
|
||||||
magic: "NAddMultiple", discardable.}
|
magic: "NAddMultiple", discardable, noSideEffect.}
|
||||||
## Adds each child of `children` to the `father` node.
|
## Adds each child of `children` to the `father` node.
|
||||||
## Returns the `father` node so that calls can be nested.
|
## Returns the `father` node so that calls can be nested.
|
||||||
|
|
||||||
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
|
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
|
||||||
## deletes `n` children of `father` starting at index `idx`.
|
## deletes `n` children of `father` starting at index `idx`.
|
||||||
|
|
||||||
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
|
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind", noSideEffect.}
|
||||||
## returns the `kind` of the node `n`.
|
## returns the `kind` of the node `n`.
|
||||||
|
|
||||||
proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal".}
|
proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
|
||||||
proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal".}
|
proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
|
||||||
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".}
|
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol", noSideEffect.}
|
||||||
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".}
|
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent", noSideEffect.}
|
||||||
proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType".}
|
proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType", noSideEffect.}
|
||||||
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".}
|
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal", noSideEffect.}
|
||||||
|
|
||||||
proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal".}
|
proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
|
||||||
proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal".}
|
proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
|
||||||
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
|
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol", noSideEffect.}
|
||||||
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
|
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent", noSideEffect.}
|
||||||
#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
|
#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
|
||||||
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
|
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
|
||||||
# can easily do:
|
# can easily do:
|
||||||
|
|
@ -166,24 +169,24 @@ proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
|
||||||
# let fake = semCheck(2.0)
|
# let fake = semCheck(2.0)
|
||||||
# bracket[0] = fake # constructs a mixed array with ints and floats!
|
# bracket[0] = fake # constructs a mixed array with ints and floats!
|
||||||
|
|
||||||
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
|
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
|
||||||
|
|
||||||
proc newNimNode*(kind: TNimrodNodeKind,
|
proc newNimNode*(kind: TNimrodNodeKind,
|
||||||
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode", noSideEffect.}
|
||||||
|
|
||||||
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
|
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode", noSideEffect.}
|
||||||
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
|
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree", noSideEffect.}
|
||||||
|
|
||||||
proc error*(msg: string) {.magic: "NError".}
|
proc error*(msg: string) {.magic: "NError", gcsafe.}
|
||||||
## writes an error message at compile time
|
## writes an error message at compile time
|
||||||
|
|
||||||
proc warning*(msg: string) {.magic: "NWarning".}
|
proc warning*(msg: string) {.magic: "NWarning", gcsafe.}
|
||||||
## writes a warning message at compile time
|
## writes a warning message at compile time
|
||||||
|
|
||||||
proc hint*(msg: string) {.magic: "NHint".}
|
proc hint*(msg: string) {.magic: "NHint", gcsafe.}
|
||||||
## writes a hint message at compile time
|
## writes a hint message at compile time
|
||||||
|
|
||||||
proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =
|
proc newStrLitNode*(s: string): PNimrodNode {.compileTime, noSideEffect.} =
|
||||||
## creates a string literal node from `s`
|
## creates a string literal node from `s`
|
||||||
result = newNimNode(nnkStrLit)
|
result = newNimNode(nnkStrLit)
|
||||||
result.strVal = s
|
result.strVal = s
|
||||||
|
|
@ -219,7 +222,7 @@ type
|
||||||
## any other means in the language currently)
|
## any other means in the language currently)
|
||||||
|
|
||||||
proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
|
proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
|
||||||
magic: "NBindSym".}
|
magic: "NBindSym", noSideEffect.}
|
||||||
## creates a node that binds `ident` to a symbol node. The bound symbol
|
## creates a node that binds `ident` to a symbol node. The bound symbol
|
||||||
## may be an overloaded symbol.
|
## may be an overloaded symbol.
|
||||||
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
|
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
|
||||||
|
|
@ -230,11 +233,11 @@ proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
|
||||||
## returned even if the symbol is not ambiguous.
|
## returned even if the symbol is not ambiguous.
|
||||||
|
|
||||||
proc genSym*(kind: TNimrodSymKind = nskLet; ident = ""): PNimrodNode {.
|
proc genSym*(kind: TNimrodSymKind = nskLet; ident = ""): PNimrodNode {.
|
||||||
magic: "NGenSym".}
|
magic: "NGenSym", noSideEffect.}
|
||||||
## generates a fresh symbol that is guaranteed to be unique. The symbol
|
## generates a fresh symbol that is guaranteed to be unique. The symbol
|
||||||
## needs to occur in a declaration context.
|
## needs to occur in a declaration context.
|
||||||
|
|
||||||
proc callsite*(): PNimrodNode {.magic: "NCallSite".}
|
proc callsite*(): PNimrodNode {.magic: "NCallSite", gcsafe.}
|
||||||
## returns the AST if the invokation expression that invoked this macro.
|
## returns the AST if the invokation expression that invoked this macro.
|
||||||
|
|
||||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
|
|
@ -242,19 +245,19 @@ proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## in a string literal node
|
## in a string literal node
|
||||||
return newStrLitNode(repr(n))
|
return newStrLitNode(repr(n))
|
||||||
|
|
||||||
proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo".}
|
proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo", noSideEffect.}
|
||||||
## returns the position the node appears in the original source file
|
## returns the position the node appears in the original source file
|
||||||
## in the form filename(line, col)
|
## in the form filename(line, col)
|
||||||
|
|
||||||
proc parseExpr*(s: string): PNimrodNode {.magic: "ParseExprToAst".}
|
proc parseExpr*(s: string): PNimrodNode {.magic: "ParseExprToAst", noSideEffect.}
|
||||||
## Compiles the passed string to its AST representation.
|
## Compiles the passed string to its AST representation.
|
||||||
## Expects a single expression.
|
## Expects a single expression.
|
||||||
|
|
||||||
proc parseStmt*(s: string): PNimrodNode {.magic: "ParseStmtToAst".}
|
proc parseStmt*(s: string): PNimrodNode {.magic: "ParseStmtToAst", noSideEffect.}
|
||||||
## Compiles the passed string to its AST representation.
|
## Compiles the passed string to its AST representation.
|
||||||
## Expects one or more statements.
|
## Expects one or more statements.
|
||||||
|
|
||||||
proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst".}
|
proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideEffect.}
|
||||||
## Obtains the AST nodes returned from a macro or template invocation.
|
## Obtains the AST nodes returned from a macro or template invocation.
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
|
|
@ -263,7 +266,7 @@ proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst".}
|
||||||
## macro FooMacro() =
|
## macro FooMacro() =
|
||||||
## var ast = getAst(BarTemplate())
|
## var ast = getAst(BarTemplate())
|
||||||
|
|
||||||
proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
|
proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.}
|
||||||
## Quasi-quoting operator.
|
## Quasi-quoting operator.
|
||||||
## Accepts an expression or a block and returns the AST that represents it.
|
## Accepts an expression or a block and returns the AST that represents it.
|
||||||
## Within the quoted AST, you are able to interpolate PNimrodNode expressions
|
## Within the quoted AST, you are able to interpolate PNimrodNode expressions
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
import os, oids, tables, strutils, macros
|
import os, oids, tables, strutils, macros
|
||||||
|
|
||||||
import rawsockets
|
import rawsockets
|
||||||
|
|
@ -31,7 +33,7 @@ export TPort
|
||||||
|
|
||||||
type
|
type
|
||||||
PFutureBase* = ref object of PObject
|
PFutureBase* = ref object of PObject
|
||||||
cb: proc () {.closure.}
|
cb: proc () {.closure,gcsafe.}
|
||||||
finished: bool
|
finished: bool
|
||||||
|
|
||||||
PFuture*[T] = ref object of PFutureBase
|
PFuture*[T] = ref object of PFutureBase
|
||||||
|
|
@ -68,7 +70,7 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
|
||||||
if future.cb != nil:
|
if future.cb != nil:
|
||||||
future.cb()
|
future.cb()
|
||||||
|
|
||||||
proc `callback=`*(future: PFutureBase, cb: proc () {.closure.}) =
|
proc `callback=`*(future: PFutureBase, cb: proc () {.closure,gcsafe.}) =
|
||||||
## Sets the callback proc to be called when the future completes.
|
## Sets the callback proc to be called when the future completes.
|
||||||
##
|
##
|
||||||
## If future has already completed then ``cb`` will be called immediately.
|
## If future has already completed then ``cb`` will be called immediately.
|
||||||
|
|
@ -80,7 +82,7 @@ proc `callback=`*(future: PFutureBase, cb: proc () {.closure.}) =
|
||||||
future.cb()
|
future.cb()
|
||||||
|
|
||||||
proc `callback=`*[T](future: PFuture[T],
|
proc `callback=`*[T](future: PFuture[T],
|
||||||
cb: proc (future: PFuture[T]) {.closure.}) =
|
cb: proc (future: PFuture[T]) {.closure,gcsafe.}) =
|
||||||
## Sets the callback proc to be called when the future completes.
|
## Sets the callback proc to be called when the future completes.
|
||||||
##
|
##
|
||||||
## If future has already completed then ``cb`` will be called immediately.
|
## If future has already completed then ``cb`` will be called immediately.
|
||||||
|
|
@ -122,7 +124,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
TCompletionData* = object
|
TCompletionData* = object
|
||||||
sock: TAsyncFD
|
sock: TAsyncFD
|
||||||
cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
|
cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
|
||||||
errcode: TOSErrorCode) {.closure.}
|
errcode: TOSErrorCode) {.closure,gcsafe.}
|
||||||
|
|
||||||
PDispatcher* = ref object
|
PDispatcher* = ref object
|
||||||
ioPort: THandle
|
ioPort: THandle
|
||||||
|
|
@ -237,7 +239,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
let func =
|
let func =
|
||||||
cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint,
|
cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint,
|
||||||
lpSendBuffer: pointer, dwSendDataLength: dword,
|
lpSendBuffer: pointer, dwSendDataLength: dword,
|
||||||
lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall.}](connectExPtr)
|
lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall,gcsafe.}](connectExPtr)
|
||||||
|
|
||||||
result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent,
|
result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent,
|
||||||
lpOverlapped)
|
lpOverlapped)
|
||||||
|
|
@ -251,7 +253,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer,
|
cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer,
|
||||||
dwReceiveDataLength, dwLocalAddressLength,
|
dwReceiveDataLength, dwLocalAddressLength,
|
||||||
dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD,
|
dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD,
|
||||||
lpOverlapped: POverlapped): bool {.stdcall.}](acceptExPtr)
|
lpOverlapped: POverlapped): bool {.stdcall,gcsafe.}](acceptExPtr)
|
||||||
result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength,
|
result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength,
|
||||||
dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
|
dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
|
||||||
lpOverlapped)
|
lpOverlapped)
|
||||||
|
|
@ -268,7 +270,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
dwReceiveDataLength, dwLocalAddressLength,
|
dwReceiveDataLength, dwLocalAddressLength,
|
||||||
dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr,
|
dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr,
|
||||||
LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr,
|
LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr,
|
||||||
RemoteSockaddrLength: lpint) {.stdcall.}](getAcceptExSockAddrsPtr)
|
RemoteSockaddrLength: lpint) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
|
||||||
|
|
||||||
func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
|
func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
|
||||||
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
|
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
|
||||||
|
|
@ -537,7 +539,7 @@ else:
|
||||||
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK
|
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK
|
||||||
type
|
type
|
||||||
TAsyncFD* = distinct cint
|
TAsyncFD* = distinct cint
|
||||||
TCallback = proc (sock: TAsyncFD): bool {.closure.}
|
TCallback = proc (sock: TAsyncFD): bool {.closure,gcsafe.}
|
||||||
|
|
||||||
PData* = ref object of PObject
|
PData* = ref object of PObject
|
||||||
sock: TAsyncFD
|
sock: TAsyncFD
|
||||||
|
|
@ -757,7 +759,7 @@ proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
|
||||||
|
|
||||||
template createCb*(retFutureSym, iteratorNameSym: expr): stmt {.immediate.} =
|
template createCb*(retFutureSym, iteratorNameSym: expr): stmt {.immediate.} =
|
||||||
var nameIterVar = iteratorNameSym
|
var nameIterVar = iteratorNameSym
|
||||||
proc cb {.closure.} =
|
proc cb {.closure,gcsafe.} =
|
||||||
if not nameIterVar.finished:
|
if not nameIterVar.finished:
|
||||||
var next = nameIterVar()
|
var next = nameIterVar()
|
||||||
if next == nil:
|
if next == nil:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
import sockets, os
|
import sockets, os
|
||||||
|
|
||||||
## This module implements an asynchronous event loop together with asynchronous sockets
|
## This module implements an asynchronous event loop together with asynchronous sockets
|
||||||
|
|
@ -98,13 +100,13 @@ type
|
||||||
fd*: TSocketHandle
|
fd*: TSocketHandle
|
||||||
deleVal*: PObject
|
deleVal*: PObject
|
||||||
|
|
||||||
handleRead*: proc (h: PObject) {.nimcall.}
|
handleRead*: proc (h: PObject) {.nimcall, gcsafe.}
|
||||||
handleWrite*: proc (h: PObject) {.nimcall.}
|
handleWrite*: proc (h: PObject) {.nimcall, gcsafe.}
|
||||||
handleError*: proc (h: PObject) {.nimcall.}
|
handleError*: proc (h: PObject) {.nimcall, gcsafe.}
|
||||||
hasDataBuffered*: proc (h: PObject): bool {.nimcall.}
|
hasDataBuffered*: proc (h: PObject): bool {.nimcall, gcsafe.}
|
||||||
|
|
||||||
open*: bool
|
open*: bool
|
||||||
task*: proc (h: PObject) {.nimcall.}
|
task*: proc (h: PObject) {.nimcall, gcsafe.}
|
||||||
mode*: TFileMode
|
mode*: TFileMode
|
||||||
|
|
||||||
PDelegate* = ref TDelegate
|
PDelegate* = ref TDelegate
|
||||||
|
|
@ -118,13 +120,13 @@ type
|
||||||
socket: TSocket
|
socket: TSocket
|
||||||
info: TInfo
|
info: TInfo
|
||||||
|
|
||||||
handleRead*: proc (s: PAsyncSocket) {.closure.}
|
handleRead*: proc (s: PAsyncSocket) {.closure, gcsafe.}
|
||||||
handleWrite: proc (s: PAsyncSocket) {.closure.}
|
handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.}
|
||||||
handleConnect*: proc (s: PAsyncSocket) {.closure.}
|
handleConnect*: proc (s: PAsyncSocket) {.closure, gcsafe.}
|
||||||
|
|
||||||
handleAccept*: proc (s: PAsyncSocket) {.closure.}
|
handleAccept*: proc (s: PAsyncSocket) {.closure, gcsafe.}
|
||||||
|
|
||||||
handleTask*: proc (s: PAsyncSocket) {.closure.}
|
handleTask*: proc (s: PAsyncSocket) {.closure, gcsafe.}
|
||||||
|
|
||||||
lineBuffer: TaintedString ## Temporary storage for ``readLine``
|
lineBuffer: TaintedString ## Temporary storage for ``readLine``
|
||||||
sendBuffer: string ## Temporary storage for ``send``
|
sendBuffer: string ## Temporary storage for ``send``
|
||||||
|
|
@ -213,7 +215,7 @@ proc asyncSockHandleRead(h: PObject) =
|
||||||
else:
|
else:
|
||||||
PAsyncSocket(h).handleAccept(PAsyncSocket(h))
|
PAsyncSocket(h).handleAccept(PAsyncSocket(h))
|
||||||
|
|
||||||
proc close*(sock: PAsyncSocket)
|
proc close*(sock: PAsyncSocket) {.gcsafe.}
|
||||||
proc asyncSockHandleWrite(h: PObject) =
|
proc asyncSockHandleWrite(h: PObject) =
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
if PAsyncSocket(h).socket.isSSL and not
|
if PAsyncSocket(h).socket.isSSL and not
|
||||||
|
|
@ -254,7 +256,7 @@ proc asyncSockHandleWrite(h: PObject) =
|
||||||
PAsyncSocket(h).deleg.mode = fmRead
|
PAsyncSocket(h).deleg.mode = fmRead
|
||||||
|
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
proc asyncSockDoHandshake(h: PObject) =
|
proc asyncSockDoHandshake(h: PObject) {.gcsafe.} =
|
||||||
if PAsyncSocket(h).socket.isSSL and not
|
if PAsyncSocket(h).socket.isSSL and not
|
||||||
PAsyncSocket(h).socket.gotHandshake:
|
PAsyncSocket(h).socket.gotHandshake:
|
||||||
if PAsyncSocket(h).sslNeedAccept:
|
if PAsyncSocket(h).sslNeedAccept:
|
||||||
|
|
@ -437,7 +439,7 @@ proc isSendDataBuffered*(s: PAsyncSocket): bool =
|
||||||
return s.sendBuffer.len != 0
|
return s.sendBuffer.len != 0
|
||||||
|
|
||||||
proc setHandleWrite*(s: PAsyncSocket,
|
proc setHandleWrite*(s: PAsyncSocket,
|
||||||
handleWrite: proc (s: PAsyncSocket) {.closure.}) =
|
handleWrite: proc (s: PAsyncSocket) {.closure, gcsafe.}) =
|
||||||
## Setter for the ``handleWrite`` event.
|
## Setter for the ``handleWrite`` event.
|
||||||
##
|
##
|
||||||
## To remove this event you should use the ``delHandleWrite`` function.
|
## To remove this event you should use the ``delHandleWrite`` function.
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ proc setCookie*(name, value: string) =
|
||||||
write(stdout, "Set-Cookie: ", name, "=", value, "\n")
|
write(stdout, "Set-Cookie: ", name, "=", value, "\n")
|
||||||
|
|
||||||
var
|
var
|
||||||
gcookies: PStringTable = nil
|
gcookies {.threadvar.}: PStringTable
|
||||||
|
|
||||||
proc getCookie*(name: string): TaintedString =
|
proc getCookie*(name: string): TaintedString =
|
||||||
## Gets a cookie. If no cookie of `name` exists, "" is returned.
|
## Gets a cookie. If no cookie of `name` exists, "" is returned.
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
import sockets, strutils, parseutils, times, os, asyncio
|
import sockets, strutils, parseutils, times, os, asyncio
|
||||||
|
|
||||||
## This module **partially** implements an FTP client as specified
|
## This module **partially** implements an FTP client as specified
|
||||||
|
|
@ -41,7 +43,7 @@ type
|
||||||
dummyA, dummyB: pointer # workaround a Nimrod API issue
|
dummyA, dummyB: pointer # workaround a Nimrod API issue
|
||||||
asyncCSock: PAsyncSocket
|
asyncCSock: PAsyncSocket
|
||||||
asyncDSock: PAsyncSocket
|
asyncDSock: PAsyncSocket
|
||||||
handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.}
|
handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.}
|
||||||
disp: PDispatcher
|
disp: PDispatcher
|
||||||
asyncDSockID: PDelegate
|
asyncDSockID: PDelegate
|
||||||
user, pass: string
|
user, pass: string
|
||||||
|
|
@ -59,7 +61,7 @@ type
|
||||||
JRetrText, JRetr, JStore
|
JRetrText, JRetr, JStore
|
||||||
|
|
||||||
TFTPJob = object
|
TFTPJob = object
|
||||||
prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall.}
|
prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.}
|
||||||
case typ*: FTPJobType
|
case typ*: FTPJobType
|
||||||
of JRetrText:
|
of JRetrText:
|
||||||
lines: string
|
lines: string
|
||||||
|
|
@ -148,7 +150,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
|
||||||
[expected.join("' or '"), received.string])
|
[expected.join("' or '"), received.string])
|
||||||
|
|
||||||
proc createJob(ftp: PFTPClient,
|
proc createJob(ftp: PFTPClient,
|
||||||
prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall.},
|
prc: proc (ftp: PFTPClient, async: bool): bool {.
|
||||||
|
nimcall,gcsafe.},
|
||||||
cmd: FTPJobType) =
|
cmd: FTPJobType) =
|
||||||
if ftp.jobInProgress:
|
if ftp.jobInProgress:
|
||||||
raise newException(EFTP, "Unable to do two jobs at once.")
|
raise newException(EFTP, "Unable to do two jobs at once.")
|
||||||
|
|
@ -558,7 +561,7 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
|
||||||
|
|
||||||
proc asyncFTPClient*(address: string, port = TPort(21),
|
proc asyncFTPClient*(address: string, port = TPort(21),
|
||||||
user, pass = "",
|
user, pass = "",
|
||||||
handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.} =
|
handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure,gcsafe.} =
|
||||||
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient =
|
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient =
|
||||||
## Create a ``PAsyncFTPClient`` object.
|
## Create a ``PAsyncFTPClient`` object.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,7 @@ proc nextAsync(s: PAsyncHTTPServer) =
|
||||||
s.path = data.substr(i, last-1)
|
s.path = data.substr(i, last-1)
|
||||||
|
|
||||||
proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: TSocket,
|
proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: TSocket,
|
||||||
path, query: string): bool {.closure.},
|
path, query: string): bool {.closure, gcsafe.},
|
||||||
port = TPort(80), address = "",
|
port = TPort(80), address = "",
|
||||||
reuseAddr = false): PAsyncHTTPServer =
|
reuseAddr = false): PAsyncHTTPServer =
|
||||||
## Creates an Asynchronous HTTP server at ``port``.
|
## Creates an Asynchronous HTTP server at ``port``.
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@
|
||||||
## **Warning:** The API of this module is unstable, and therefore is subject
|
## **Warning:** The API of this module is unstable, and therefore is subject
|
||||||
## to change.
|
## to change.
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
import sockets, strutils, parseutils, times, asyncio, os
|
import sockets, strutils, parseutils, times, asyncio, os
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -41,7 +43,7 @@ type
|
||||||
nick, user, realname, serverPass: string
|
nick, user, realname, serverPass: string
|
||||||
case isAsync: bool
|
case isAsync: bool
|
||||||
of true:
|
of true:
|
||||||
handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure.}
|
handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.}
|
||||||
asyncSock: PAsyncSocket
|
asyncSock: PAsyncSocket
|
||||||
myDispatcher: PDispatcher
|
myDispatcher: PDispatcher
|
||||||
of false:
|
of false:
|
||||||
|
|
@ -445,7 +447,7 @@ proc asyncIRC*(address: string, port: TPort = 6667.TPort,
|
||||||
realname = "NimrodBot", serverPass = "",
|
realname = "NimrodBot", serverPass = "",
|
||||||
joinChans: seq[string] = @[],
|
joinChans: seq[string] = @[],
|
||||||
msgLimit: bool = true,
|
msgLimit: bool = true,
|
||||||
ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure.}
|
ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.}
|
||||||
): PAsyncIRC =
|
): PAsyncIRC =
|
||||||
## Use this function if you want to use asyncio's dispatcher.
|
## Use this function if you want to use asyncio's dispatcher.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
## Basic math routines for Nimrod.
|
## Basic math routines for Nimrod.
|
||||||
## This module is available for the JavaScript target.
|
## This module is available for the JavaScript target.
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
{.push debugger:off .} # the user does not want to trace a part
|
{.push debugger:off .} # the user does not want to trace a part
|
||||||
# of the standard library!
|
# of the standard library!
|
||||||
|
|
||||||
|
|
@ -127,25 +129,25 @@ proc variance*(x: openArray[float]): float {.noSideEffect.} =
|
||||||
result = result + diff*diff
|
result = result + diff*diff
|
||||||
result = result / toFloat(len(x))
|
result = result / toFloat(len(x))
|
||||||
|
|
||||||
proc random*(max: int): int
|
proc random*(max: int): int {.gcsafe.}
|
||||||
## returns a random number in the range 0..max-1. The sequence of
|
## returns a random number in the range 0..max-1. The sequence of
|
||||||
## random number is always the same, unless `randomize` is called
|
## random number is always the same, unless `randomize` is called
|
||||||
## which initializes the random number generator with a "random"
|
## which initializes the random number generator with a "random"
|
||||||
## number, i.e. a tickcount.
|
## number, i.e. a tickcount.
|
||||||
|
|
||||||
when not defined(windows):
|
when not defined(windows):
|
||||||
proc random*(max: float): float
|
proc random*(max: float): float {.gcsafe.}
|
||||||
## returns a random number in the range 0..<max. The sequence of
|
## returns a random number in the range 0..<max. The sequence of
|
||||||
## random number is always the same, unless `randomize` is called
|
## random number is always the same, unless `randomize` is called
|
||||||
## which initializes the random number generator with a "random"
|
## which initializes the random number generator with a "random"
|
||||||
## number, i.e. a tickcount. This is currently not supported for windows.
|
## number, i.e. a tickcount. This is currently not supported for windows.
|
||||||
|
|
||||||
proc randomize*()
|
proc randomize*() {.gcsafe.}
|
||||||
## initializes the random number generator with a "random"
|
## initializes the random number generator with a "random"
|
||||||
## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
|
## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
|
||||||
## as JavaScript does not support this.
|
## as JavaScript does not support this.
|
||||||
|
|
||||||
proc randomize*(seed: int)
|
proc randomize*(seed: int) {.gcsafe.}
|
||||||
## initializes the random number generator with a specific seed.
|
## initializes the random number generator with a specific seed.
|
||||||
## Note: Does nothing for the JavaScript target,
|
## Note: Does nothing for the JavaScript target,
|
||||||
## as JavaScript does not support this.
|
## as JavaScript does not support this.
|
||||||
|
|
@ -227,8 +229,8 @@ else:
|
||||||
result = int(floor(mathrandom() * float(max)))
|
result = int(floor(mathrandom() * float(max)))
|
||||||
proc random(max: float): float =
|
proc random(max: float): float =
|
||||||
result = float(mathrandom() * float(max))
|
result = float(mathrandom() * float(max))
|
||||||
proc randomize() = nil
|
proc randomize() = discard
|
||||||
proc randomize(seed: int) = nil
|
proc randomize(seed: int) = discard
|
||||||
|
|
||||||
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
|
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
|
||||||
proc ln*(x: float): float {.importc: "Math.log", nodecl.}
|
proc ln*(x: float): float {.importc: "Math.log", nodecl.}
|
||||||
|
|
|
||||||
|
|
@ -1564,7 +1564,7 @@ when defined(windows):
|
||||||
# ourselves. This has the additional benefit that the program's behaviour
|
# ourselves. This has the additional benefit that the program's behaviour
|
||||||
# is always the same -- independent of the used C compiler.
|
# is always the same -- independent of the used C compiler.
|
||||||
var
|
var
|
||||||
ownArgv: seq[string]
|
ownArgv {.threadvar.}: seq[string]
|
||||||
|
|
||||||
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
|
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
|
||||||
## Returns the number of `command line arguments`:idx: given to the
|
## Returns the number of `command line arguments`:idx: given to the
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ const
|
||||||
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.',
|
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.',
|
||||||
'/', '\\'}
|
'/', '\\'}
|
||||||
|
|
||||||
proc rawGetTok(c: var TCfgParser, tok: var TToken)
|
proc rawGetTok(c: var TCfgParser, tok: var TToken) {.gcsafe.}
|
||||||
|
|
||||||
proc open*(c: var TCfgParser, input: PStream, filename: string,
|
proc open*(c: var TCfgParser, input: PStream, filename: string,
|
||||||
lineOffset = 0) {.
|
lineOffset = 0) {.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
## **Warning:** The API of this module is unstable, and therefore is subject
|
## **Warning:** The API of this module is unstable, and therefore is subject
|
||||||
## to change.
|
## to change.
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
import sockets, strutils, os, strtabs, asyncio
|
import sockets, strutils, os, strtabs, asyncio
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -82,7 +84,7 @@ type
|
||||||
|
|
||||||
TAsyncScgiState = object
|
TAsyncScgiState = object
|
||||||
handleRequest: proc (client: PAsyncSocket,
|
handleRequest: proc (client: PAsyncSocket,
|
||||||
input: string, headers: PStringTable) {.closure.}
|
input: string, headers: PStringTable) {.closure,gcsafe.}
|
||||||
asyncServer: PAsyncSocket
|
asyncServer: PAsyncSocket
|
||||||
disp: PDispatcher
|
disp: PDispatcher
|
||||||
PAsyncScgiState* = ref TAsyncScgiState
|
PAsyncScgiState* = ref TAsyncScgiState
|
||||||
|
|
@ -150,7 +152,7 @@ proc writeStatusOkTextContent*(c: TSocket, contentType = "text/html") =
|
||||||
"Content-Type: $1\r\L\r\L" % contentType)
|
"Content-Type: $1\r\L\r\L" % contentType)
|
||||||
|
|
||||||
proc run*(handleRequest: proc (client: TSocket, input: string,
|
proc run*(handleRequest: proc (client: TSocket, input: string,
|
||||||
headers: PStringTable): bool {.nimcall.},
|
headers: PStringTable): bool {.nimcall,gcsafe.},
|
||||||
port = TPort(4000)) =
|
port = TPort(4000)) =
|
||||||
## encapsulates the SCGI object and main loop.
|
## encapsulates the SCGI object and main loop.
|
||||||
var s: TScgiState
|
var s: TScgiState
|
||||||
|
|
@ -246,7 +248,8 @@ proc handleAccept(sock: PAsyncSocket, s: PAsyncScgiState) =
|
||||||
s.disp.register(client)
|
s.disp.register(client)
|
||||||
|
|
||||||
proc open*(handleRequest: proc (client: PAsyncSocket,
|
proc open*(handleRequest: proc (client: PAsyncSocket,
|
||||||
input: string, headers: PStringTable) {.closure.},
|
input: string, headers: PStringTable) {.
|
||||||
|
closure, gcsafe.},
|
||||||
port = TPort(4000), address = "127.0.0.1",
|
port = TPort(4000), address = "127.0.0.1",
|
||||||
reuseAddr = false): PAsyncScgiState =
|
reuseAddr = false): PAsyncScgiState =
|
||||||
## Creates an ``PAsyncScgiState`` object which serves as a SCGI server.
|
## Creates an ``PAsyncScgiState`` object which serves as a SCGI server.
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
## Asynchronous sockets are supported, however a better alternative is to use
|
## Asynchronous sockets are supported, however a better alternative is to use
|
||||||
## the `asyncio <asyncio.html>`_ module.
|
## the `asyncio <asyncio.html>`_ module.
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
||||||
when hostOS == "solaris":
|
when hostOS == "solaris":
|
||||||
|
|
@ -544,7 +546,7 @@ proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) {.
|
||||||
else:
|
else:
|
||||||
SSLError("Unknown error")
|
SSLError("Unknown error")
|
||||||
|
|
||||||
proc setBlocking*(s: TSocket, blocking: bool) {.tags: [].}
|
proc setBlocking*(s: TSocket, blocking: bool) {.tags: [], gcsafe.}
|
||||||
## Sets blocking mode on socket
|
## Sets blocking mode on socket
|
||||||
|
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
## interface for Nimrod file objects (`TFile`) and strings. Other modules
|
## interface for Nimrod file objects (`TFile`) and strings. Other modules
|
||||||
## may provide other implementations for this standard stream interface.
|
## may provide other implementations for this standard stream interface.
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
proc newEIO(msg: string): ref EIO =
|
proc newEIO(msg: string): ref EIO =
|
||||||
new(result)
|
new(result)
|
||||||
result.msg = msg
|
result.msg = msg
|
||||||
|
|
@ -23,15 +25,15 @@ 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) {.nimcall, tags: [].}
|
closeImpl*: proc (s: PStream) {.nimcall, tags: [], gcsafe.}
|
||||||
atEndImpl*: proc (s: PStream): bool {.nimcall, tags: [].}
|
atEndImpl*: proc (s: PStream): bool {.nimcall, tags: [], gcsafe.}
|
||||||
setPositionImpl*: proc (s: PStream, pos: int) {.nimcall, tags: [].}
|
setPositionImpl*: proc (s: PStream, pos: int) {.nimcall, tags: [], gcsafe.}
|
||||||
getPositionImpl*: proc (s: PStream): int {.nimcall, tags: [].}
|
getPositionImpl*: proc (s: PStream): int {.nimcall, tags: [], gcsafe.}
|
||||||
readDataImpl*: proc (s: PStream, buffer: pointer,
|
readDataImpl*: proc (s: PStream, buffer: pointer,
|
||||||
bufLen: int): int {.nimcall, tags: [FReadIO].}
|
bufLen: int): int {.nimcall, tags: [FReadIO], gcsafe.}
|
||||||
writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall,
|
writeDataImpl*: proc (s: PStream, buffer: pointer, bufLen: int) {.nimcall,
|
||||||
tags: [FWriteIO].}
|
tags: [FWriteIO], gcsafe.}
|
||||||
flushImpl*: proc (s: PStream) {.nimcall, tags: [FWriteIO].}
|
flushImpl*: proc (s: PStream) {.nimcall, tags: [FWriteIO], gcsafe.}
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
||||||
|
|
@ -135,38 +135,38 @@ type
|
||||||
months*: int ## The number of months
|
months*: int ## The number of months
|
||||||
years*: int ## The number of years
|
years*: int ## The number of years
|
||||||
|
|
||||||
proc getTime*(): TTime {.tags: [FTime].}
|
proc getTime*(): TTime {.tags: [FTime], gcsafe.}
|
||||||
## gets the current calendar time as a UNIX epoch value (number of seconds
|
## gets the current calendar time as a UNIX epoch value (number of seconds
|
||||||
## elapsed since 1970) with integer precission. Use epochTime for higher
|
## elapsed since 1970) with integer precission. Use epochTime for higher
|
||||||
## resolution.
|
## resolution.
|
||||||
proc getLocalTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].}
|
proc getLocalTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [], gcsafe.}
|
||||||
## converts the calendar time `t` to broken-time representation,
|
## converts the calendar time `t` to broken-time representation,
|
||||||
## expressed relative to the user's specified time zone.
|
## expressed relative to the user's specified time zone.
|
||||||
proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].}
|
proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [], gcsafe.}
|
||||||
## converts the calendar time `t` to broken-down time representation,
|
## converts the calendar time `t` to broken-down time representation,
|
||||||
## expressed in Coordinated Universal Time (UTC).
|
## expressed in Coordinated Universal Time (UTC).
|
||||||
|
|
||||||
proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].}
|
proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [], gcsafe.}
|
||||||
## converts a broken-down time structure to
|
## converts a broken-down time structure to
|
||||||
## calendar time representation. The function ignores the specified
|
## calendar time representation. The function ignores the specified
|
||||||
## contents of the structure members `weekday` and `yearday` and recomputes
|
## contents of the structure members `weekday` and `yearday` and recomputes
|
||||||
## them from the other information in the broken-down time structure.
|
## them from the other information in the broken-down time structure.
|
||||||
|
|
||||||
proc fromSeconds*(since1970: float): TTime {.tags: [], raises: [].}
|
proc fromSeconds*(since1970: float): TTime {.tags: [], raises: [], gcsafe.}
|
||||||
## Takes a float which contains the number of seconds since the unix epoch and
|
## Takes a float which contains the number of seconds since the unix epoch and
|
||||||
## returns a time object.
|
## returns a time object.
|
||||||
|
|
||||||
proc fromSeconds*(since1970: int64): TTime {.tags: [], raises: [].} =
|
proc fromSeconds*(since1970: int64): TTime {.tags: [], raises: [], gcsafe.} =
|
||||||
## Takes an int which contains the number of seconds since the unix epoch and
|
## Takes an int which contains the number of seconds since the unix epoch and
|
||||||
## returns a time object.
|
## returns a time object.
|
||||||
fromSeconds(float(since1970))
|
fromSeconds(float(since1970))
|
||||||
|
|
||||||
proc toSeconds*(time: TTime): float {.tags: [], raises: [].}
|
proc toSeconds*(time: TTime): float {.tags: [], raises: [], gcsafe.}
|
||||||
## Returns the time in seconds since the unix epoch.
|
## Returns the time in seconds since the unix epoch.
|
||||||
|
|
||||||
proc `$` *(timeInfo: TTimeInfo): string {.tags: [], raises: [].}
|
proc `$` *(timeInfo: TTimeInfo): string {.tags: [], raises: [], gcsafe.}
|
||||||
## converts a `TTimeInfo` object to a string representation.
|
## converts a `TTimeInfo` object to a string representation.
|
||||||
proc `$` *(time: TTime): string {.tags: [], raises: [].}
|
proc `$` *(time: TTime): string {.tags: [], raises: [], gcsafe.}
|
||||||
## converts a calendar time to a string representation.
|
## converts a calendar time to a string representation.
|
||||||
|
|
||||||
proc `-`*(a, b: TTime): int64 {.
|
proc `-`*(a, b: TTime): int64 {.
|
||||||
|
|
@ -189,14 +189,15 @@ proc `==`*(a, b: TTime): bool {.
|
||||||
result = a - b == 0
|
result = a - b == 0
|
||||||
|
|
||||||
when not defined(JS):
|
when not defined(JS):
|
||||||
proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime], raises: [].}
|
proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime], raises: [],
|
||||||
|
gcsafe.}
|
||||||
## returns the local timezone; ``nonDST`` is the name of the local non-DST
|
## returns the local timezone; ``nonDST`` is the name of the local non-DST
|
||||||
## timezone, ``DST`` is the name of the local DST timezone.
|
## timezone, ``DST`` is the name of the local DST timezone.
|
||||||
|
|
||||||
proc getTimezone*(): int {.tags: [FTime], raises: [].}
|
proc getTimezone*(): int {.tags: [FTime], raises: [], gcsafe.}
|
||||||
## returns the offset of the local (non-DST) timezone in seconds west of UTC.
|
## returns the offset of the local (non-DST) timezone in seconds west of UTC.
|
||||||
|
|
||||||
proc getStartMilsecs*(): int {.deprecated, tags: [FTime].}
|
proc getStartMilsecs*(): int {.deprecated, tags: [FTime], gcsafe.}
|
||||||
## get the miliseconds from the start of the program. **Deprecated since
|
## get the miliseconds from the start of the program. **Deprecated since
|
||||||
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
|
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,9 +192,6 @@ when defined(nimNewShared):
|
||||||
type
|
type
|
||||||
`shared`* {.magic: "Shared".}
|
`shared`* {.magic: "Shared".}
|
||||||
guarded* {.magic: "Guarded".}
|
guarded* {.magic: "Guarded".}
|
||||||
else:
|
|
||||||
{.pragma: gcsafe.}
|
|
||||||
#{.pragma: gcsafe.}
|
|
||||||
|
|
||||||
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
|
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
|
||||||
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ type
|
||||||
region: TMemRegion
|
region: TMemRegion
|
||||||
PRawChannel = ptr TRawChannel
|
PRawChannel = ptr TRawChannel
|
||||||
TLoadStoreMode = enum mStore, mLoad
|
TLoadStoreMode = enum mStore, mLoad
|
||||||
TChannel*[TMsg] = TRawChannel ## a channel for thread communication
|
TChannel* {.gcsafe.}[TMsg] = TRawChannel ## a channel for thread communication
|
||||||
|
|
||||||
const ChannelDeadMask = -2
|
const ChannelDeadMask = -2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
# -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl)
|
# -> defined(useNimRtl) or appType == "lib" and not defined(createNimRtl)
|
||||||
# 3) Exported into nimrtl.
|
# 3) Exported into nimrtl.
|
||||||
# -> appType == "lib" and defined(createNimRtl)
|
# -> appType == "lib" and defined(createNimRtl)
|
||||||
|
when not defined(nimNewShared):
|
||||||
|
{.pragma: gcsafe.}
|
||||||
|
|
||||||
when defined(createNimRtl):
|
when defined(createNimRtl):
|
||||||
when defined(useNimRtl):
|
when defined(useNimRtl):
|
||||||
|
|
@ -24,7 +26,7 @@ when defined(createNimRtl):
|
||||||
{.error: "nimrtl must be built as a library!".}
|
{.error: "nimrtl must be built as a library!".}
|
||||||
|
|
||||||
when defined(createNimRtl):
|
when defined(createNimRtl):
|
||||||
{.pragma: rtl, exportc: "nimrtl_$1", dynlib.}
|
{.pragma: rtl, exportc: "nimrtl_$1", dynlib, gcsafe.}
|
||||||
{.pragma: inl.}
|
{.pragma: inl.}
|
||||||
{.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
|
{.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
|
||||||
elif defined(useNimRtl):
|
elif defined(useNimRtl):
|
||||||
|
|
@ -34,11 +36,11 @@ elif defined(useNimRtl):
|
||||||
const nimrtl* = "nimrtl.dylib"
|
const nimrtl* = "nimrtl.dylib"
|
||||||
else:
|
else:
|
||||||
const nimrtl* = "libnimrtl.so"
|
const nimrtl* = "libnimrtl.so"
|
||||||
{.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl.}
|
{.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl, gcsafe.}
|
||||||
{.pragma: inl.}
|
{.pragma: inl.}
|
||||||
{.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.}
|
{.pragma: compilerRtl, compilerproc, importc: "nimrtl_$1", dynlib: nimrtl.}
|
||||||
else:
|
else:
|
||||||
{.pragma: rtl.}
|
{.pragma: rtl, gcsafe.}
|
||||||
{.pragma: inl, inline.}
|
{.pragma: inl, inline.}
|
||||||
{.pragma: compilerRtl, compilerproc.}
|
{.pragma: compilerRtl, compilerproc.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,9 +256,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 () {.nimcall.}
|
dataFn: proc () {.nimcall, gcsafe.}
|
||||||
else:
|
else:
|
||||||
dataFn: proc (m: TArg) {.nimcall.}
|
dataFn: proc (m: TArg) {.nimcall, gcsafe.}
|
||||||
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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue