mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 19:33:42 +00:00
Compare commits
64 Commits
pr_move_sy
...
pr_fix_sig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aacf94d72c | ||
|
|
c1b90783eb | ||
|
|
9a50033d5b | ||
|
|
2564b5c938 | ||
|
|
e4aadcf1c1 | ||
|
|
7ae7832f76 | ||
|
|
1fefb8e92a | ||
|
|
d84f64d2e7 | ||
|
|
b0a850adbf | ||
|
|
4388636010 | ||
|
|
584cfa6af8 | ||
|
|
fd7da7da62 | ||
|
|
19923aa8b7 | ||
|
|
28bed059aa | ||
|
|
cbeefc877c | ||
|
|
b981f3eeb7 | ||
|
|
5917c2d5b7 | ||
|
|
3812d91390 | ||
|
|
c7493bbdd0 | ||
|
|
1585bfec3b | ||
|
|
07be1791ba | ||
|
|
7a18c1ef44 | ||
|
|
b59c657be3 | ||
|
|
2ebd71bfd4 | ||
|
|
f330b33e2b | ||
|
|
db56fc3bcb | ||
|
|
da3274d1b3 | ||
|
|
0cd9bdcf9f | ||
|
|
ef190f349d | ||
|
|
f8e64d879c | ||
|
|
0a1d4ba842 | ||
|
|
e669835665 | ||
|
|
696def2bf7 | ||
|
|
c5eb3fd4f0 | ||
|
|
4480fd3e93 | ||
|
|
4da3ead294 | ||
|
|
53fbb497e9 | ||
|
|
d6b485493d | ||
|
|
9ba07edb2e | ||
|
|
4ca2dcb404 | ||
|
|
1564ae650f | ||
|
|
b2c7019006 | ||
|
|
6d8cf25bd7 | ||
|
|
739e1badb6 | ||
|
|
5d469686b0 | ||
|
|
feb0481ba3 | ||
|
|
e98efdcc5e | ||
|
|
c47d5196be | ||
|
|
b83bd282dc | ||
|
|
a8090f7d65 | ||
|
|
794bcc8029 | ||
|
|
6f96c4bc96 | ||
|
|
1b5e03f975 | ||
|
|
78b387d948 | ||
|
|
5536f74992 | ||
|
|
55373e65b4 | ||
|
|
83493e4294 | ||
|
|
ece41d2605 | ||
|
|
79ec6d677c | ||
|
|
10b6e4f5b4 | ||
|
|
8266750497 | ||
|
|
a104aa4714 | ||
|
|
658b28dc57 | ||
|
|
a70d3abd37 |
5
.github/workflows/ci_packages.yml
vendored
5
.github/workflows/ci_packages.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'devel'
|
||||
- 'version-2-0'
|
||||
- 'version-1-6'
|
||||
- 'version-1-2'
|
||||
|
||||
@@ -27,12 +28,12 @@ jobs:
|
||||
NIM_TESTAMENT_BATCH: ${{ matrix.batch }}
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 'Install node.js 16.x'
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
|
||||
4
.github/workflows/ci_publish.yml
vendored
4
.github/workflows/ci_publish.yml
vendored
@@ -17,12 +17,12 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 'Install node.js 16.x'
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
|
||||
70
changelog.md
70
changelog.md
@@ -80,6 +80,11 @@
|
||||
- Removed two type pragma syntaxes deprecated since 0.20, namely
|
||||
`type Foo = object {.final.}`, and `type Foo {.final.} [T] = object`.
|
||||
|
||||
- `foo a = b` now means `foo(a = b)` rather than `foo(a) = b`. This is consistent
|
||||
with the existing behavior of `foo a, b = c` meaning `foo(a, b = c)`.
|
||||
This decision was made with the assumption that the old syntax was used rarely;
|
||||
if your code used the old syntax, please be aware of this change.
|
||||
|
||||
- [Overloadable enums](https://nim-lang.github.io/Nim/manual.html#overloadable-enum-value-names) and Unicode Operators
|
||||
are no longer experimental.
|
||||
|
||||
@@ -107,8 +112,27 @@
|
||||
|
||||
- Object fields now support default values, see https://nim-lang.github.io/Nim/manual.html#types-default-values-for-object-fields for details.
|
||||
|
||||
- Redefining templates with the same signature was previously
|
||||
allowed to support certain macro code. To do this explicitly, the
|
||||
`{.redefine.}` pragma has been added. Note that this is only for templates.
|
||||
Implicit redefinition of templates is now deprecated and will give an error in the future.
|
||||
|
||||
- Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead.
|
||||
|
||||
- Several Standard libraries are moved to nimble packages, use `nimble` to install them:
|
||||
- `std/punycode` => `punycode`
|
||||
- `std/asyncftpclient` => `asyncftpclient`
|
||||
- `std/smtp` => `smtp`
|
||||
- `std/db_common` => `db_connector/db_common`
|
||||
- `std/db_sqlite` => `db_connector/db_sqlite`
|
||||
- `std/db_mysql` => `db_connector/db_mysql`
|
||||
- `std/db_postgres` => `db_connector/db_postgres`
|
||||
- `std/db_odbc` => `db_connector/db_odbc`
|
||||
|
||||
- Previously, calls like `foo(a, b): ...` or `foo(a, b) do: ...` where the final argument of
|
||||
`foo` had type `proc ()` were assumed by the compiler to mean `foo(a, b, proc () = ...)`.
|
||||
This behavior is now deprecated. Use `foo(a, b) do (): ...` or `foo(a, b, proc () = ...)` instead.
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
@@ -145,6 +169,7 @@
|
||||
- Added new modules which were part of `std/os`:
|
||||
- Added `std/oserrors` for OS error reporting. Added `std/envvars` for environment variables handling.
|
||||
- Added `std/paths`, `std/dirs`, `std/files`, `std/symlinks` and `std/appdirs`.
|
||||
- Added `std/cmdline` for reading command line parameters.
|
||||
- Added `sep` parameter in `std/uri` to specify the query separator.
|
||||
- Added bindings to [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
|
||||
and [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
||||
@@ -181,6 +206,11 @@
|
||||
- Removed deprecated `` httpcore.`==` ``.
|
||||
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that takes wrong argument types.
|
||||
- Removed deprecated `osproc.poDemon`, symbol with typo.
|
||||
- Removed deprecated `tables.rightSize`.
|
||||
|
||||
|
||||
- Removed deprecated `posix.CLONE_STOPPED`.
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
@@ -191,9 +221,33 @@
|
||||
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
|
||||
for the right-hand side of type definitions in type sections. Previously
|
||||
they would error with "invalid indentation".
|
||||
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
|
||||
In the command line, this is defined as `-d:a.b.c`. Older versions can
|
||||
use accents as in ``defined(`a.b.c`)`` to access such defines.
|
||||
|
||||
- Compile-time define changes:
|
||||
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
|
||||
In the command line, this is defined as `-d:a.b.c`. Older versions can
|
||||
use accents as in ``defined(`a.b.c`)`` to access such defines.
|
||||
- [Define pragmas for constants](https://nim-lang.github.io/Nim/manual.html#implementation-specific-pragmas-compileminustime-define-pragmas)
|
||||
now support a string argument for qualified define names.
|
||||
|
||||
```nim
|
||||
# -d:package.FooBar=42
|
||||
const FooBar {.intdefine: "package.FooBar".}: int = 5
|
||||
echo FooBar # 42
|
||||
```
|
||||
|
||||
This was added to help disambiguate similar define names for different packages.
|
||||
In older versions, this could only be achieved with something like the following:
|
||||
|
||||
```nim
|
||||
const FooBar = block:
|
||||
const `package.FooBar` {.intdefine.}: int = 5
|
||||
`package.FooBar`
|
||||
```
|
||||
- A generic `define` pragma for constants has been added that interprets
|
||||
the value of the define based on the type of the constant value.
|
||||
See the [experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#generic-define-pragma)
|
||||
for a list of supported types.
|
||||
|
||||
- [Macro pragmas](https://nim-lang.github.io/Nim/manual.html#userminusdefined-pragmas-macro-pragmas) changes:
|
||||
- Templates now accept macro pragmas.
|
||||
- Macro pragmas for var/let/const sections have been redesigned in a way that works
|
||||
@@ -226,12 +280,6 @@
|
||||
Baz = object
|
||||
```
|
||||
|
||||
- Redefining templates with the same signature implicitly was previously
|
||||
allowed to support certain macro code. A `{.redefine.}` pragma has been
|
||||
added to make this work explicitly, and a warning is generated in the case
|
||||
where it is implicit. This behavior only applies to templates, redefinition
|
||||
is generally disallowed for other symbols.
|
||||
|
||||
- A new form of type inference called [top-down inference](https://nim-lang.github.io/Nim/manual_experimental.html#topminusdown-type-inference)
|
||||
has been implemented for a variety of basic cases. For example, code like the following now compiles:
|
||||
|
||||
@@ -268,6 +316,4 @@
|
||||
|
||||
## Tool changes
|
||||
|
||||
- Nim now supports Nimble version 0.14 which added support for lock-files. This is done by
|
||||
a simple configuration change setting that you can do yourself too. In `$nim/config/nim.cfg`
|
||||
replace `pkgs` by `pkgs2`.
|
||||
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs`).
|
||||
|
||||
@@ -712,7 +712,7 @@ type
|
||||
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
||||
mNHint, mNWarning, mNError,
|
||||
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
|
||||
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
||||
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mGenericDefine, mRunnableExamples,
|
||||
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
||||
mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault
|
||||
|
||||
@@ -2047,6 +2047,9 @@ template detailedInfo*(sym: PSym): string =
|
||||
proc isInlineIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv != ccClosure
|
||||
|
||||
proc isIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags
|
||||
|
||||
proc isClosureIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv == ccClosure
|
||||
|
||||
|
||||
@@ -1879,9 +1879,13 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
# Bug #9279, len(toOpenArray()) has to work:
|
||||
if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice:
|
||||
# magic: pass slice to openArray:
|
||||
var m: TLoc
|
||||
var b, c: TLoc
|
||||
initLocExpr(p, a[1], m)
|
||||
initLocExpr(p, a[2], b)
|
||||
initLocExpr(p, a[3], c)
|
||||
if optBoundsCheck in p.options:
|
||||
genBoundsCheck(p, m, b, c)
|
||||
if op == mHigh:
|
||||
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
|
||||
else:
|
||||
@@ -3279,6 +3283,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
if constOrNil != nil:
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if constOrNil[i][0].sym.name.id == field.name.id:
|
||||
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
|
||||
return
|
||||
|
||||
@@ -1348,7 +1348,7 @@ proc genDisplay(t: PType, depth: int): Rope =
|
||||
result.add seqs[0]
|
||||
result.add "}"
|
||||
|
||||
proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
|
||||
proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
|
||||
cgsym(m, "TNimTypeV2")
|
||||
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
|
||||
|
||||
@@ -1364,7 +1364,6 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
|
||||
let objDepth = if t.kind == tyObject: getObjDepth(t) else: -1
|
||||
|
||||
|
||||
if t.kind in {tyObject, tyDistinct} and incompleteType(t):
|
||||
localError(m.config, info, "request for RTTI generation for incomplete object: " &
|
||||
typeToString(t))
|
||||
@@ -1390,6 +1389,48 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
|
||||
proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
|
||||
cgsym(m, "TNimTypeV2")
|
||||
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
|
||||
|
||||
var flags = 0
|
||||
if not canFormAcycle(t): flags = flags or 1
|
||||
|
||||
var typeEntry = newRopeAppender()
|
||||
addf(typeEntry, "N_LIB_PRIVATE TNimTypeV2 $1 = {", [name])
|
||||
add(typeEntry, ".destructor = (void*)")
|
||||
genHook(m, t, info, attachedDestructor, typeEntry)
|
||||
|
||||
let objDepth = if t.kind == tyObject: getObjDepth(t) else: -1
|
||||
|
||||
if t.kind in {tyObject, tyDistinct} and incompleteType(t):
|
||||
localError(m.config, info, "request for RTTI generation for incomplete object: " &
|
||||
typeToString(t))
|
||||
|
||||
addf(typeEntry, ", .size = sizeof($1), .align = (NI16) NIM_ALIGNOF($1), .depth = $2",
|
||||
[getTypeDesc(m, t), rope(objDepth)])
|
||||
|
||||
if objDepth >= 0:
|
||||
let objDisplay = genDisplay(t, objDepth)
|
||||
let objDisplayStore = getTempName(m)
|
||||
m.s[cfsVars].addf("static NIM_CONST $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), skVar), objDisplayStore, rope(objDepth+1), objDisplay])
|
||||
addf(typeEntry, ", .display = $1", [rope(objDisplayStore)])
|
||||
if isDefined(m.config, "nimTypeNames"):
|
||||
var typeName: Rope
|
||||
if t.kind in {tyObject, tyDistinct}:
|
||||
typeName = genTypeInfo2Name(m, t)
|
||||
else:
|
||||
typeName = rope("NIM_NIL")
|
||||
addf(typeEntry, ", .name = $1", [typeName])
|
||||
add(typeEntry, ", .traceImpl = (void*)")
|
||||
genHook(m, t, info, attachedTrace, typeEntry)
|
||||
|
||||
addf(typeEntry, ", .flags = $1};$n", [rope(flags)])
|
||||
m.s[cfsVars].add typeEntry
|
||||
|
||||
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
|
||||
proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
let origType = t
|
||||
# distinct types can have their own destructors
|
||||
@@ -1423,7 +1464,10 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
return prefixTI.rope & result & ")".rope
|
||||
|
||||
m.g.typeInfoMarkerV2[sig] = (str: result, owner: owner)
|
||||
genTypeInfoV2Impl(m, t, origType, result, info)
|
||||
if m.compileToCpp:
|
||||
genTypeInfoV2OldImpl(m, t, origType, result, info)
|
||||
else:
|
||||
genTypeInfoV2Impl(m, t, origType, result, info)
|
||||
result = prefixTI.rope & result & ")".rope
|
||||
|
||||
proc openArrayToTuple(m: BModule; t: PType): PType =
|
||||
|
||||
@@ -149,3 +149,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasOutParams")
|
||||
defineSymbol("nimHasSystemRaisesDefect")
|
||||
defineSymbol("nimHasWarnUnnamedBreak")
|
||||
defineSymbol("nimHasGenericDefine")
|
||||
defineSymbol("nimHasDefineAliases")
|
||||
|
||||
@@ -558,7 +558,7 @@ proc runAllExamples(d: PDoc) =
|
||||
|
||||
proc quoted(a: string): string = result.addQuoted(a)
|
||||
|
||||
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): auto =
|
||||
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): (string, int, int) =
|
||||
# xxx expose in compiler/lineinfos.nim
|
||||
(conf.toMsgFilename(info), info.line.int, info.col.int + ColOffset)
|
||||
|
||||
@@ -962,7 +962,7 @@ proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
|
||||
var literal = ""
|
||||
var r: TSrcGen
|
||||
initTokRender(r, genNode, {renderNoBody, renderNoComments,
|
||||
renderNoPragmas, renderNoProcDefs})
|
||||
renderNoPragmas, renderNoProcDefs, renderExpandUsing})
|
||||
var kind = tkEof
|
||||
while true:
|
||||
getNextTok(r, kind, literal)
|
||||
@@ -995,7 +995,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
var r: TSrcGen
|
||||
# Obtain the plain rendered string for hyperlink titles.
|
||||
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments,
|
||||
renderNoPragmas, renderNoProcDefs})
|
||||
renderNoPragmas, renderNoProcDefs, renderExpandUsing})
|
||||
while true:
|
||||
getNextTok(r, kind, literal)
|
||||
if kind == tkEof:
|
||||
@@ -1028,7 +1028,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
rstLangSymbol, priority = symbolPriority(k), info = lineinfo)
|
||||
|
||||
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
|
||||
renderDocComments, renderSyms}, symbolOrIdEnc)
|
||||
renderDocComments, renderSyms, renderExpandUsing}, symbolOrIdEnc)
|
||||
|
||||
let seeSrc = genSeeSrc(d, toFullPath(d.conf, n.info), n.info.line.int)
|
||||
|
||||
@@ -1094,7 +1094,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonItem =
|
||||
name = getName(d, nameNode)
|
||||
comm = genRecComment(d, n)
|
||||
r: TSrcGen
|
||||
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments})
|
||||
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments, renderExpandUsing})
|
||||
result.json = %{ "name": %name, "type": %($k), "line": %n.info.line.int,
|
||||
"col": %n.info.col}
|
||||
if comm != nil:
|
||||
|
||||
@@ -24,7 +24,7 @@ when defined(nimPreviewSlimSystem):
|
||||
## `RodFile` represents a Rod File (versioned binary format), and the
|
||||
## associated data for common interactions such as IO and error tracking
|
||||
## (`RodFileError`). The file format broken up into sections (`RodSection`)
|
||||
## and preceeded by a header (see: `cookie`). The precise layout, section
|
||||
## and preceded by a header (see: `cookie`). The precise layout, section
|
||||
## ordering and data following the section are determined by the user. See
|
||||
## `ic.loadRodFile`.
|
||||
##
|
||||
|
||||
@@ -829,7 +829,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
if ri.kind != nkEmpty:
|
||||
result.add moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
elif ri.kind == nkEmpty and c.inLoop > 0:
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
let skipInit = v.kind == nkDotExpr and # Closure var
|
||||
sfNoInit in v[1].sym.flags
|
||||
if not skipInit:
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
else: # keep the var but transform 'ri':
|
||||
var v = copyNode(n)
|
||||
var itCopy = copyNode(it)
|
||||
|
||||
@@ -724,8 +724,9 @@ proc hasFrameInfo(p: PProc): bool =
|
||||
((p.prc == nil) or not (sfPure in p.prc.flags))
|
||||
|
||||
proc lineDir(config: ConfigRef, info: TLineInfo, line: int): Rope =
|
||||
ropes.`%`("/* line $2 \"$1\" */$n",
|
||||
[rope(toFullPath(config, info)), rope(line)])
|
||||
"/* line $2:$3 \"$1\" */$n" % [
|
||||
rope(toFullPath(config, info)), rope(line), rope(info.toColumn)
|
||||
]
|
||||
|
||||
proc genLineDir(p: PProc, n: PNode) =
|
||||
let line = toLinenumber(n.info)
|
||||
@@ -2208,7 +2209,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
|
||||
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)", true)
|
||||
of mSetLengthStr:
|
||||
binaryExpr(p, n, r, "mnewString", "($1.length = $2)")
|
||||
binaryExpr(p, n, r, "mnewString",
|
||||
"""if ($1.length < $2) { for (var i = $3.length; i < $4; ++i) $3.push(0); }
|
||||
else {$3.length = $4; }""")
|
||||
of mSetLengthSeq:
|
||||
var x, y: TCompRes
|
||||
gen(p, n[1], x)
|
||||
@@ -2885,7 +2888,8 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
# Generate an optional source map.
|
||||
if optSourcemap in m.config.globalOptions:
|
||||
var map: SourceMap
|
||||
(code, map) = genSourceMap($(code), outFile.string)
|
||||
map = genSourceMap($code, outFile.string)
|
||||
code &= "\n//# sourceMappingURL=$#.map" % [outFile.string]
|
||||
writeFile(outFile.string & ".map", $(%map))
|
||||
# Check if the generated JS code matches the output file, or else
|
||||
# write it to the file.
|
||||
|
||||
@@ -83,8 +83,9 @@ type
|
||||
warnPtrToCstringConv = "PtrToCstringConv",
|
||||
warnEffect = "Effect",
|
||||
warnCastSizes = "CastSizes"
|
||||
warnTemplateRedefinition = "TemplateRedefinition",
|
||||
warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition",
|
||||
warnUnnamedBreak = "UnnamedBreak",
|
||||
warnStmtListLambda = "StmtListLambda",
|
||||
warnUser = "User",
|
||||
# hints
|
||||
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
||||
@@ -181,8 +182,9 @@ const
|
||||
warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; this will become a compile time error in the future",
|
||||
warnEffect: "$1",
|
||||
warnCastSizes: "$1",
|
||||
warnTemplateRedefinition: "template '$1' is implicitly redefined, consider adding an explicit .redefine pragma",
|
||||
warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma",
|
||||
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
|
||||
warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
# keep in sync with `testament.isSuccess`
|
||||
|
||||
@@ -422,7 +422,7 @@ type SpellCandidate = object
|
||||
msg: string
|
||||
sym: PSym
|
||||
|
||||
template toOrderTup(a: SpellCandidate): auto =
|
||||
template toOrderTup(a: SpellCandidate): (int, int, string) =
|
||||
# `dist` is first, to favor nearby matches
|
||||
# `depth` is next, to favor nearby enclosing scopes among ties
|
||||
# `sym.name.s` is last, to make the list ordered and deterministic among ties
|
||||
|
||||
@@ -196,7 +196,6 @@ type
|
||||
ideRecompile, ideChanged, ideType, ideDeclaration
|
||||
|
||||
Feature* = enum ## experimental features; DO NOT RENAME THESE!
|
||||
implicitDeref, # deadcode; remains here for backwards compatibility
|
||||
dotOperators,
|
||||
callOperator,
|
||||
parallel,
|
||||
@@ -457,7 +456,7 @@ when false:
|
||||
fn(globalOptions)
|
||||
fn(selectedGC)
|
||||
|
||||
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
|
||||
const oldExperimentalFeatures* = {dotOperators, callOperator, parallel}
|
||||
|
||||
const
|
||||
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
|
||||
@@ -865,7 +864,8 @@ const stdlibDirs* = [
|
||||
"pure/concurrency",
|
||||
"pure/unidecode", "impure",
|
||||
"wrappers", "wrappers/linenoise",
|
||||
"windows", "posix", "js"]
|
||||
"windows", "posix", "js",
|
||||
"deprecated/pure"]
|
||||
|
||||
const
|
||||
pkgPrefix = "pkg/"
|
||||
|
||||
@@ -79,7 +79,7 @@ type
|
||||
smNormal, smAllowNil, smAfterDot
|
||||
|
||||
PrimaryMode = enum
|
||||
pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
|
||||
pmNormal, pmTypeDesc, pmTypeDef, pmTrySimple
|
||||
|
||||
proc parseAll*(p: var Parser): PNode
|
||||
proc closeParser*(p: var Parser)
|
||||
@@ -286,7 +286,8 @@ proc newIdentNodeP(ident: PIdent, p: Parser): PNode =
|
||||
|
||||
proc parseExpr(p: var Parser): PNode
|
||||
proc parseStmt(p: var Parser): PNode
|
||||
proc parseTypeDesc(p: var Parser): PNode
|
||||
proc parseTypeDesc(p: var Parser, fullExpr = false): PNode
|
||||
proc parseTypeDefValue(p: var Parser): PNode
|
||||
proc parseParamList(p: var Parser, retColon = true): PNode
|
||||
|
||||
proc isSigilLike(tok: Token): bool {.inline.} =
|
||||
@@ -406,6 +407,16 @@ proc parseSymbol(p: var Parser, mode = smNormal): PNode =
|
||||
#if not isKeyword(p.tok.tokType): getTok(p)
|
||||
result = p.emptyNode
|
||||
|
||||
proc equals(p: var Parser, a: PNode): PNode =
|
||||
if p.tok.tokType == tkEquals:
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
getTok(p)
|
||||
#optInd(p, result)
|
||||
result.add(a)
|
||||
result.add(parseExpr(p))
|
||||
else:
|
||||
result = a
|
||||
|
||||
proc colonOrEquals(p: var Parser, a: PNode): PNode =
|
||||
if p.tok.tokType == tkColon:
|
||||
result = newNodeP(nkExprColonExpr, p)
|
||||
@@ -414,14 +425,8 @@ proc colonOrEquals(p: var Parser, a: PNode): PNode =
|
||||
#optInd(p, result)
|
||||
result.add(a)
|
||||
result.add(parseExpr(p))
|
||||
elif p.tok.tokType == tkEquals:
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
getTok(p)
|
||||
#optInd(p, result)
|
||||
result.add(a)
|
||||
result.add(parseExpr(p))
|
||||
else:
|
||||
result = a
|
||||
result = equals(p, a)
|
||||
|
||||
proc exprColonEqExpr(p: var Parser): PNode =
|
||||
#| exprColonEqExpr = expr (':'|'=' expr)?
|
||||
@@ -431,6 +436,14 @@ proc exprColonEqExpr(p: var Parser): PNode =
|
||||
else:
|
||||
result = colonOrEquals(p, a)
|
||||
|
||||
proc exprEqExpr(p: var Parser): PNode =
|
||||
#| exprEqExpr = expr ('=' expr)?
|
||||
var a = parseExpr(p)
|
||||
if p.tok.tokType == tkDo:
|
||||
result = postExprBlocks(p, a)
|
||||
else:
|
||||
result = equals(p, a)
|
||||
|
||||
proc exprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||
#| exprList = expr ^+ comma
|
||||
when defined(nimpretty):
|
||||
@@ -438,6 +451,24 @@ proc exprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
# progress guaranteed
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
when defined(nimpretty):
|
||||
dec p.em.doIndentMore
|
||||
|
||||
proc optionalExprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||
#| optionalExprList = expr ^* comma
|
||||
when defined(nimpretty):
|
||||
inc p.em.doIndentMore
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
# progress guaranteed
|
||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
@@ -802,25 +833,24 @@ proc namedParams(p: var Parser, callee: PNode,
|
||||
proc commandParam(p: var Parser, isFirstParam: var bool; mode: PrimaryMode): PNode =
|
||||
if mode == pmTypeDesc:
|
||||
result = simpleExpr(p, mode)
|
||||
elif not isFirstParam:
|
||||
result = exprEqExpr(p)
|
||||
else:
|
||||
result = parseExpr(p)
|
||||
if p.tok.tokType == tkDo:
|
||||
result = postExprBlocks(p, result)
|
||||
elif p.tok.tokType == tkEquals and not isFirstParam:
|
||||
let lhs = result
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
getTok(p)
|
||||
result.add(lhs)
|
||||
result.add(parseExpr(p))
|
||||
if p.tok.tokType == tkDo:
|
||||
result = postExprBlocks(p, result)
|
||||
isFirstParam = false
|
||||
|
||||
proc commandExpr(p: var Parser; r: PNode; mode: PrimaryMode): PNode =
|
||||
result = newNodeP(nkCommand, p)
|
||||
result.add(r)
|
||||
var isFirstParam = true
|
||||
# progress NOT guaranteed
|
||||
p.hasProgress = false
|
||||
result.add commandParam(p, isFirstParam, mode)
|
||||
if mode == pmTrySimple:
|
||||
result = r
|
||||
else:
|
||||
result = newNodeP(nkCommand, p)
|
||||
result.add(r)
|
||||
var isFirstParam = true
|
||||
# progress NOT guaranteed
|
||||
p.hasProgress = false
|
||||
result.add commandParam(p, isFirstParam, mode)
|
||||
|
||||
proc isDotLike(tok: Token): bool =
|
||||
result = tok.tokType == tkOpr and tok.ident.s.len > 1 and
|
||||
@@ -833,7 +863,7 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
#| | DOTLIKEOP optInd symbol generalizedLit?
|
||||
#| | '[' optInd exprColonEqExprList optPar ']'
|
||||
#| | '{' optInd exprColonEqExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||
# XXX strong spaces need to be reflected above
|
||||
result = r
|
||||
|
||||
# progress guaranteed
|
||||
@@ -844,13 +874,6 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
# progress guaranteed
|
||||
if p.tok.strongSpaceA:
|
||||
result = commandExpr(p, result, mode)
|
||||
# type sections allow full command syntax
|
||||
if mode == pmTypeDef:
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, mode))
|
||||
break
|
||||
result = namedParams(p, result, nkCall, tkParRi)
|
||||
if result.len > 1 and result[1].kind == nkExprColonExpr:
|
||||
@@ -891,18 +914,9 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
|
||||
# solution, but pragmas.nim can't handle that
|
||||
result = commandExpr(p, result, mode)
|
||||
if mode == pmTypeDef:
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, mode))
|
||||
break
|
||||
else:
|
||||
break
|
||||
# type sections allow post-expr blocks
|
||||
if mode == pmTypeDef:
|
||||
result = postExprBlocks(p, result)
|
||||
|
||||
proc parseOperators(p: var Parser, headNode: PNode,
|
||||
limit: int, mode: PrimaryMode): PNode =
|
||||
@@ -929,7 +943,10 @@ proc parseOperators(p: var Parser, headNode: PNode,
|
||||
opPrec = getPrecedence(p.tok)
|
||||
|
||||
proc simpleExprAux(p: var Parser, limit: int, mode: PrimaryMode): PNode =
|
||||
var mode = mode
|
||||
result = primary(p, mode)
|
||||
if mode == pmTrySimple:
|
||||
mode = pmNormal
|
||||
if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)) and
|
||||
mode == pmNormal:
|
||||
var pragmaExp = newNodeP(nkPragmaExpr, p)
|
||||
@@ -1010,9 +1027,9 @@ type
|
||||
|
||||
proc parseIdentColonEquals(p: var Parser, flags: DeclaredIdentFlags): PNode =
|
||||
#| declColonEquals = identWithPragma (comma identWithPragma)* comma?
|
||||
#| (':' optInd typeDesc)? ('=' optInd expr)?
|
||||
#| (':' optInd typeDescExpr)? ('=' optInd expr)?
|
||||
#| identColonEquals = IDENT (comma IDENT)* comma?
|
||||
#| (':' optInd typeDesc)? ('=' optInd expr)?)
|
||||
#| (':' optInd typeDescExpr)? ('=' optInd expr)?)
|
||||
var a: PNode
|
||||
result = newNodeP(nkIdentDefs, p)
|
||||
# progress guaranteed
|
||||
@@ -1030,7 +1047,7 @@ proc parseIdentColonEquals(p: var Parser, flags: DeclaredIdentFlags): PNode =
|
||||
if p.tok.tokType == tkColon:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(parseTypeDesc(p))
|
||||
result.add(parseTypeDesc(p, fullExpr = true))
|
||||
else:
|
||||
result.add(newNodeP(nkEmpty, p))
|
||||
if p.tok.tokType != tkEquals and withBothOptional notin flags:
|
||||
@@ -1043,9 +1060,10 @@ proc parseIdentColonEquals(p: var Parser, flags: DeclaredIdentFlags): PNode =
|
||||
result.add(newNodeP(nkEmpty, p))
|
||||
|
||||
proc parseTuple(p: var Parser, indentAllowed = false): PNode =
|
||||
#| tupleDecl = 'tuple'
|
||||
#| '[' optInd (identColonEquals (comma/semicolon)?)* optPar ']' |
|
||||
#| COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
|
||||
#| tupleTypeBracket = '[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
|
||||
#| tupleType = 'tuple' tupleTypeBracket
|
||||
#| tupleDecl = 'tuple' (tupleTypeBracket /
|
||||
#| COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?)
|
||||
result = newNodeP(nkTupleTy, p)
|
||||
getTok(p)
|
||||
if p.tok.tokType == tkBracketLe:
|
||||
@@ -1155,6 +1173,7 @@ proc parseDoBlock(p: var Parser; info: TLineInfo): PNode =
|
||||
|
||||
proc parseProcExpr(p: var Parser; isExpr: bool; kind: TNodeKind): PNode =
|
||||
#| routineExpr = ('proc' | 'func' | 'iterator') paramListColon pragma? ('=' COMMENT? stmt)?
|
||||
#| routineType = ('proc' | 'iterator') paramListColon pragma?
|
||||
# either a proc type or a anonymous proc
|
||||
let info = parLineInfo(p)
|
||||
let hasSignature = p.tok.tokType in {tkParLe, tkColon} and p.tok.indent < 0
|
||||
@@ -1179,7 +1198,7 @@ proc isExprStart(p: Parser): bool =
|
||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkFor,
|
||||
tkProc, tkFunc, tkIterator, tkBind, tkBuiltInMagics,
|
||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCustomLit, tkVar, tkRef, tkPtr,
|
||||
tkTuple, tkObject, tkWhen, tkCase, tkOut, tkTry, tkBlock:
|
||||
tkEnum, tkTuple, tkObject, tkWhen, tkCase, tkOut, tkTry, tkBlock:
|
||||
result = true
|
||||
else: result = false
|
||||
|
||||
@@ -1199,8 +1218,12 @@ proc parseTypeDescKAux(p: var Parser, kind: TNodeKind,
|
||||
getTok(p)
|
||||
if p.tok.indent != -1 and p.tok.indent <= p.currInd: return
|
||||
optInd(p, result)
|
||||
let isTypedef = mode == pmTypeDef and p.tok.tokType in {tkObject, tkTuple}
|
||||
if not isOperator(p.tok) and isExprStart(p):
|
||||
result.add(primary(p, mode))
|
||||
if isTypedef:
|
||||
result.add(parseTypeDefValue(p))
|
||||
else:
|
||||
result.add(primary(p, mode))
|
||||
if kind == nkDistinctTy and p.tok.tokType == tkSymbol:
|
||||
# XXX document this feature!
|
||||
var nodeKind: TNodeKind
|
||||
@@ -1214,11 +1237,13 @@ proc parseTypeDescKAux(p: var Parser, kind: TNodeKind,
|
||||
let list = newNodeP(nodeKind, p)
|
||||
result.add list
|
||||
parseSymbolList(p, list)
|
||||
if mode == pmTypeDef and not isTypedef:
|
||||
result = parseOperators(p, result, -1, mode)
|
||||
|
||||
proc parseVarTuple(p: var Parser): PNode
|
||||
|
||||
proc parseFor(p: var Parser): PNode =
|
||||
#| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
|
||||
#| forStmt = 'for' ((varTuple / identWithPragma) ^+ comma) 'in' expr colcom stmt
|
||||
#| forExpr = forStmt
|
||||
getTokNoInd(p)
|
||||
result = newNodeP(nkForStmt, p)
|
||||
@@ -1283,11 +1308,18 @@ proc parseObject(p: var Parser): PNode
|
||||
proc parseTypeClass(p: var Parser): PNode
|
||||
|
||||
proc primary(p: var Parser, mode: PrimaryMode): PNode =
|
||||
#| primary = operatorB primary primarySuffix* |
|
||||
#| tupleDecl | routineExpr | enumDecl
|
||||
#| objectDecl | conceptDecl | ('bind' primary)
|
||||
#| ('var' | 'out' | 'ref' | 'ptr' | 'distinct') primary
|
||||
#| / prefixOperator* identOrLiteral primarySuffix*
|
||||
#| simplePrimary = SIGILLIKEOP? identOrLiteral primarySuffix*
|
||||
#| commandStart = &('`'|IDENT|literal|'cast'|'addr'|'type'|'var'|'out'|
|
||||
#| 'static'|'enum'|'tuple'|'object'|'proc')
|
||||
#| primary = simplePrimary (commandStart expr)
|
||||
#| / operatorB primary
|
||||
#| / routineExpr
|
||||
#| / rawTypeDesc
|
||||
#| / prefixOperator primary
|
||||
# XXX strong spaces need to be reflected in commandStart
|
||||
# command part is handled in the primarySuffix proc
|
||||
|
||||
# prefix operators:
|
||||
if isOperator(p.tok):
|
||||
# Note 'sigil like' operators are currently not reflected in the grammar
|
||||
# and should be removed for Nim 2.0, I don't think anybody uses them.
|
||||
@@ -1297,60 +1329,39 @@ proc primary(p: var Parser, mode: PrimaryMode): PNode =
|
||||
result.add(a)
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
if isSigil:
|
||||
#XXX prefix operators
|
||||
const identOrLiteralKinds = tkBuiltInMagics + {tkSymbol, tkAccent, tkNil,
|
||||
tkIntLit..tkCustomLit, tkCast, tkOut, tkParLe, tkBracketLe, tkCurlyLe}
|
||||
if isSigil and p.tok.tokType in identOrLiteralKinds:
|
||||
let baseInd = p.lex.currLineIndent
|
||||
result.add(primary(p, pmSkipSuffix))
|
||||
result.add(identOrLiteral(p, mode))
|
||||
result = primarySuffix(p, result, baseInd, mode)
|
||||
else:
|
||||
result.add(primary(p, pmNormal))
|
||||
return
|
||||
|
||||
case p.tok.tokType
|
||||
of tkTuple: result = parseTuple(p, mode == pmTypeDef)
|
||||
of tkProc:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
|
||||
result = parseProcExpr(p, mode != pmTypeDesc, nkLambda)
|
||||
of tkFunc:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef)
|
||||
result = parseProcExpr(p, mode != pmTypeDesc, nkFuncDef)
|
||||
of tkIterator:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkIteratorDef)
|
||||
of tkEnum:
|
||||
if mode == pmTypeDef:
|
||||
prettySection:
|
||||
result = parseEnum(p)
|
||||
else:
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
getTok(p)
|
||||
of tkObject:
|
||||
if mode == pmTypeDef:
|
||||
prettySection:
|
||||
result = parseObject(p)
|
||||
else:
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
getTok(p)
|
||||
of tkConcept:
|
||||
if mode == pmTypeDef:
|
||||
result = parseTypeClass(p)
|
||||
else:
|
||||
parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
|
||||
result = parseProcExpr(p, mode != pmTypeDesc, nkIteratorDef)
|
||||
of tkBind:
|
||||
# legacy syntax, no-op in current nim
|
||||
result = newNodeP(nkBind, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(primary(p, pmNormal))
|
||||
of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode)
|
||||
of tkOut: result = parseTypeDescKAux(p, nkOutTy, mode)
|
||||
of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode)
|
||||
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode)
|
||||
of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, mode)
|
||||
of tkTuple, tkEnum, tkObject, tkConcept,
|
||||
tkVar, tkOut, tkRef, tkPtr, tkDistinct:
|
||||
result = parseTypeDesc(p)
|
||||
else:
|
||||
let baseInd = p.lex.currLineIndent
|
||||
result = identOrLiteral(p, mode)
|
||||
if mode != pmSkipSuffix:
|
||||
result = primarySuffix(p, result, baseInd, mode)
|
||||
result = primarySuffix(p, result, baseInd, mode)
|
||||
|
||||
proc binaryNot(p: var Parser; a: PNode): PNode =
|
||||
if p.tok.tokType == tkNot:
|
||||
@@ -1365,16 +1376,70 @@ proc binaryNot(p: var Parser; a: PNode): PNode =
|
||||
else:
|
||||
result = a
|
||||
|
||||
proc parseTypeDesc(p: var Parser): PNode =
|
||||
#| typeDesc = simpleExpr ('not' expr)?
|
||||
proc parseTypeDesc(p: var Parser, fullExpr = false): PNode =
|
||||
#| rawTypeDesc = (tupleType | routineType | 'enum' | 'object' |
|
||||
#| ('var' | 'out' | 'ref' | 'ptr' | 'distinct') typeDesc?)
|
||||
#| ('not' expr)?
|
||||
#| typeDescExpr = (routineType / simpleExpr) ('not' expr)?
|
||||
#| typeDesc = rawTypeDesc / typeDescExpr
|
||||
newlineWasSplitting(p)
|
||||
result = simpleExpr(p, pmTypeDesc)
|
||||
if fullExpr:
|
||||
result = simpleExpr(p, pmTypeDesc)
|
||||
else:
|
||||
case p.tok.tokType
|
||||
of tkTuple:
|
||||
result = parseTuple(p, false)
|
||||
of tkProc:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, false, nkLambda)
|
||||
of tkIterator:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, false, nkIteratorDef)
|
||||
of tkEnum:
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
getTok(p)
|
||||
of tkObject:
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
getTok(p)
|
||||
of tkConcept:
|
||||
parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
|
||||
of tkVar: result = parseTypeDescKAux(p, nkVarTy, pmTypeDesc)
|
||||
of tkOut: result = parseTypeDescKAux(p, nkOutTy, pmTypeDesc)
|
||||
of tkRef: result = parseTypeDescKAux(p, nkRefTy, pmTypeDesc)
|
||||
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, pmTypeDesc)
|
||||
of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, pmTypeDesc)
|
||||
else:
|
||||
result = simpleExpr(p, pmTypeDesc)
|
||||
result = binaryNot(p, result)
|
||||
|
||||
proc parseTypeDefAux(p: var Parser): PNode =
|
||||
#| typeDefAux = simpleExpr ('not' expr
|
||||
#| | postExprBlocks)?
|
||||
result = simpleExpr(p, pmTypeDef)
|
||||
proc parseTypeDefValue(p: var Parser): PNode =
|
||||
#| typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
|
||||
#| ('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
|
||||
#| / (simpleExpr (exprEqExpr ^+ comma postExprBlocks)?))
|
||||
#| ('not' expr)?
|
||||
case p.tok.tokType
|
||||
of tkTuple: result = parseTuple(p, true)
|
||||
of tkRef: result = parseTypeDescKAux(p, nkRefTy, pmTypeDef)
|
||||
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, pmTypeDef)
|
||||
of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, pmTypeDef)
|
||||
of tkEnum:
|
||||
prettySection:
|
||||
result = parseEnum(p)
|
||||
of tkObject:
|
||||
prettySection:
|
||||
result = parseObject(p)
|
||||
of tkConcept:
|
||||
result = parseTypeClass(p)
|
||||
else:
|
||||
result = simpleExpr(p, pmTypeDef)
|
||||
if p.tok.tokType != tkNot:
|
||||
if result.kind == nkCommand:
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, pmTypeDef))
|
||||
result = postExprBlocks(p, result)
|
||||
result = binaryNot(p, result)
|
||||
|
||||
proc makeCall(n: PNode): PNode =
|
||||
@@ -1389,7 +1454,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
#| postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||
#| | IND{=} 'of' exprList ':' stmt
|
||||
#| | IND{=} 'elif' expr ':' stmt
|
||||
#| | IND{=} 'except' exprList ':' stmt
|
||||
#| | IND{=} 'except' optionalExprList ':' stmt
|
||||
#| | IND{=} 'finally' ':' stmt
|
||||
#| | IND{=} 'else' ':' stmt )*
|
||||
result = x
|
||||
@@ -1447,7 +1512,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
nextBlock.add parseExpr(p)
|
||||
of tkExcept:
|
||||
nextBlock = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, nextBlock)
|
||||
optionalExprList(p, tkColon, nextBlock)
|
||||
of tkFinally:
|
||||
nextBlock = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
@@ -1467,12 +1532,10 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
parMessage(p, "expected ':'")
|
||||
|
||||
proc parseExprStmt(p: var Parser): PNode =
|
||||
#| exprStmt = simpleExpr
|
||||
#| (( '=' optInd expr colonBody? )
|
||||
#| / ( expr ^+ comma
|
||||
#| postExprBlocks
|
||||
#| ))?
|
||||
var a = simpleExpr(p)
|
||||
#| exprStmt = simpleExpr postExprBlocks?
|
||||
#| / simplePrimary (exprEqExpr ^+ comma) postExprBlocks?
|
||||
#| / simpleExpr '=' optInd (expr postExprBlocks?)
|
||||
var a = simpleExpr(p, pmTrySimple)
|
||||
if p.tok.tokType == tkEquals:
|
||||
result = newNodeP(nkAsgn, p)
|
||||
getTok(p)
|
||||
@@ -1482,20 +1545,17 @@ proc parseExprStmt(p: var Parser): PNode =
|
||||
result.add(a)
|
||||
result.add(b)
|
||||
else:
|
||||
# simpleExpr parsed 'p a' from 'p a, b'?
|
||||
var isFirstParam = false
|
||||
if p.tok.indent < 0 and p.tok.tokType == tkComma and a.kind == nkCommand:
|
||||
result = a
|
||||
while true:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, pmNormal))
|
||||
if p.tok.tokType != tkComma: break
|
||||
elif p.tok.indent < 0 and isExprStart(p):
|
||||
# if an expression is starting here, a simplePrimary was parsed and
|
||||
# this is the start of a command
|
||||
if p.tok.indent < 0 and isExprStart(p):
|
||||
result = newTreeI(nkCommand, a.info, a)
|
||||
let baseIndent = p.currInd
|
||||
while true:
|
||||
result.add(commandParam(p, isFirstParam, pmNormal))
|
||||
if p.tok.tokType != tkComma: break
|
||||
if p.tok.tokType != tkComma or
|
||||
(p.tok.indent >= 0 and p.tok.indent < baseIndent):
|
||||
break
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
else:
|
||||
@@ -1704,10 +1764,10 @@ proc parseCase(p: var Parser): PNode =
|
||||
|
||||
proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||
#| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||
#| (IND{=}? 'except' exprList colcom stmt)*
|
||||
#| (IND{=}? 'except' optionalExprList colcom stmt)*
|
||||
#| (IND{=}? 'finally' colcom stmt)?
|
||||
#| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
||||
#| (optInd 'except' exprList colcom stmt)*
|
||||
#| (optInd 'except' optionalExprList colcom stmt)*
|
||||
#| (optInd 'finally' colcom stmt)?
|
||||
result = newNodeP(nkTryStmt, p)
|
||||
getTok(p)
|
||||
@@ -1718,7 +1778,7 @@ proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||
case p.tok.tokType
|
||||
of tkExcept:
|
||||
b = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
optionalExprList(p, tkColon, b)
|
||||
of tkFinally:
|
||||
b = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
@@ -2132,7 +2192,7 @@ proc parseTypeClass(p: var Parser): PNode =
|
||||
|
||||
proc parseTypeDef(p: var Parser): PNode =
|
||||
#|
|
||||
#| typeDef = identVisDot genericParamList? pragma '=' optInd typeDefAux
|
||||
#| typeDef = identVisDot genericParamList? pragma '=' optInd typeDefValue
|
||||
#| indAndComment?
|
||||
result = newNodeP(nkTypeDef, p)
|
||||
var identifier = identVis(p, allowDot=true)
|
||||
@@ -2158,7 +2218,7 @@ proc parseTypeDef(p: var Parser): PNode =
|
||||
result.info = parLineInfo(p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(parseTypeDefAux(p))
|
||||
result.add(parseTypeDefValue(p))
|
||||
else:
|
||||
result.add(p.emptyNode)
|
||||
indAndComment(p, result) # special extension!
|
||||
|
||||
@@ -81,7 +81,8 @@ const
|
||||
wGuard, wGoto, wCursor, wNoalias, wAlign}
|
||||
constPragmas* = declPragmas + {wHeader, wMagic,
|
||||
wGensym, wInject,
|
||||
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
|
||||
wIntDefine, wStrDefine, wBoolDefine, wDefine,
|
||||
wCompilerProc, wCore}
|
||||
paramPragmas* = {wNoalias, wInject, wGensym}
|
||||
letPragmas* = varPragmas
|
||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
||||
@@ -476,8 +477,16 @@ proc processPop(c: PContext, n: PNode) =
|
||||
when defined(debugOptions):
|
||||
echo c.config $ n.info, " POP config is now ", c.config.options
|
||||
|
||||
proc processDefine(c: PContext, n: PNode) =
|
||||
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
|
||||
proc processDefineConst(c: PContext, n: PNode, sym: PSym, kind: TMagic) =
|
||||
sym.magic = kind
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||
# could also use TLib
|
||||
n[1] = getStrLitNode(c, n)
|
||||
|
||||
proc processDefine(c: PContext, n: PNode, sym: PSym) =
|
||||
if sym != nil and sym.kind == skConst:
|
||||
processDefineConst(c, n, sym, mGenericDefine)
|
||||
elif (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
|
||||
defineSymbol(c.config.symbols, n[1].ident.s)
|
||||
else:
|
||||
invalidPragma(c, n)
|
||||
@@ -1066,7 +1075,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
recordPragma(c, it, "error", s)
|
||||
localError(c.config, it.info, errUser, s)
|
||||
of wFatal: fatal(c.config, it.info, expectStrLit(c, it))
|
||||
of wDefine: processDefine(c, it)
|
||||
of wDefine: processDefine(c, it, sym)
|
||||
of wUndef: processUndef(c, it)
|
||||
of wCompile: processCompile(c, it)
|
||||
of wLink: processLink(c, it)
|
||||
@@ -1213,11 +1222,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
noVal(c, it)
|
||||
sym.flags.incl sfBase
|
||||
of wIntDefine:
|
||||
sym.magic = mIntDefine
|
||||
processDefineConst(c, n, sym, mIntDefine)
|
||||
of wStrDefine:
|
||||
sym.magic = mStrDefine
|
||||
processDefineConst(c, n, sym, mStrDefine)
|
||||
of wBoolDefine:
|
||||
sym.magic = mBoolDefine
|
||||
processDefineConst(c, n, sym, mBoolDefine)
|
||||
of wUsed:
|
||||
noVal(c, it)
|
||||
if sym == nil: invalidPragma(c, it)
|
||||
|
||||
@@ -24,7 +24,7 @@ type
|
||||
TRenderFlag* = enum
|
||||
renderNone, renderNoBody, renderNoComments, renderDocComments,
|
||||
renderNoPragmas, renderIds, renderNoProcDefs, renderSyms, renderRunnableExamples,
|
||||
renderIr
|
||||
renderIr, renderExpandUsing
|
||||
TRenderFlags* = set[TRenderFlag]
|
||||
TRenderTok* = object
|
||||
kind*: TokType
|
||||
@@ -434,6 +434,24 @@ proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
result = 0
|
||||
for i in start..n.len + theEnd: inc(result, lsub(g, n[i]))
|
||||
|
||||
proc origUsingType(n: PNode): PSym {.inline.} =
|
||||
## Returns the type that a parameter references. Check with referencesUsing first
|
||||
## to check `n` is actually referencing a using node
|
||||
# If the node is untyped the typ field will be nil
|
||||
if n[0].sym.typ != nil:
|
||||
n[0].sym.typ.sym
|
||||
else: nil
|
||||
|
||||
proc referencesUsing(n: PNode): bool =
|
||||
## Returns true if n references a using statement.
|
||||
## e.g. proc foo(x) # x doesn't have type or def value so it references a using
|
||||
result = n.kind == nkIdentDefs and
|
||||
# Sometimes the node might not have been semmed (e.g. doc0) and will be nkIdent instead
|
||||
n[0].kind == nkSym and
|
||||
# Templates/macros can have parameters with no type (But their orig type will be nil)
|
||||
n.origUsingType != nil and
|
||||
n[1].kind == nkEmpty and n[2].kind == nkEmpty
|
||||
|
||||
proc lsub(g: TSrcGen; n: PNode): int =
|
||||
# computes the length of a tree
|
||||
if isNil(n): return 0
|
||||
@@ -474,8 +492,11 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkDo: result = lsons(g, n) + len("do__:_")
|
||||
of nkConstDef, nkIdentDefs:
|
||||
result = lcomma(g, n, 0, - 3)
|
||||
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
|
||||
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
|
||||
if n.referencesUsing:
|
||||
result += lsub(g, newSymNode(n.origUsingType)) + 2
|
||||
else:
|
||||
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
|
||||
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
|
||||
of nkVarTuple:
|
||||
if n[^1].kind == nkEmpty:
|
||||
result = lcomma(g, n, 0, - 2) + len("()")
|
||||
@@ -1260,8 +1281,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
gsub(g, n, 0)
|
||||
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString:
|
||||
if renderIds in g.flags:
|
||||
putWithSpace(g, tkAddr, $n.kind)
|
||||
put(g, tkAddr, $n.kind)
|
||||
put(g, tkParLe, "(")
|
||||
gsub(g, n, 0)
|
||||
if renderIds in g.flags:
|
||||
put(g, tkParRi, ")")
|
||||
|
||||
of nkLambda:
|
||||
putWithSpace(g, tkProc, "proc")
|
||||
gsub(g, n, paramsPos)
|
||||
@@ -1280,7 +1305,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
gcomma(g, n, 0, -3)
|
||||
if n.len >= 2 and n[^2].kind != nkEmpty:
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, n.len - 2)
|
||||
gsub(g, n[^2], c)
|
||||
elif n.referencesUsing and renderExpandUsing in g.flags:
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, newSymNode(n.origUsingType), c)
|
||||
|
||||
if n.len >= 1 and n[^1].kind != nkEmpty:
|
||||
put(g, tkSpaces, Space)
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
|
||||
@@ -81,7 +81,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||
proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
let x = arg.skipConv
|
||||
if (x.kind == nkCurly and formal.kind == tySet and formal.base.kind != tyGenericParam) or
|
||||
(x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass}:
|
||||
(x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass, tyAnything}:
|
||||
changeType(c, x, formal, check=true)
|
||||
result = arg
|
||||
result = skipHiddenSubConv(result, c.graph, c.idgen)
|
||||
@@ -439,7 +439,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
# does not mean we expect a tyTypeDesc.
|
||||
retType = retType[0]
|
||||
case retType.kind
|
||||
of tyUntyped:
|
||||
of tyUntyped, tyAnything:
|
||||
# Not expecting a type here allows templates like in ``tmodulealias.in``.
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
of tyTyped:
|
||||
@@ -642,10 +642,10 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, id: var IntSet): PNode
|
||||
if child != nil:
|
||||
let node = newNode(nkIntLit)
|
||||
node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip))
|
||||
result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, a.info, "arrayWith"), a.info),
|
||||
semExprWithType(c, child),
|
||||
node
|
||||
))
|
||||
result = semExpr(c, newTree(nkCall, newSymNode(getCompilerProc(c.graph, "nimArrayWith"), a.info),
|
||||
semExprWithType(c, child),
|
||||
node
|
||||
))
|
||||
result.typ = aTyp
|
||||
elif aTypSkip.kind == tyTuple:
|
||||
var hasDefault = false
|
||||
|
||||
@@ -394,6 +394,8 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
let castedExpr = semExprWithType(c, n[1])
|
||||
if castedExpr.kind == nkClosedSymChoice:
|
||||
errorUseQualifier(c, n[1].info, castedExpr)
|
||||
if targetType == nil:
|
||||
localError(c.config, n.info, "Invalid usage of cast, cast requires a type to convert to, e.g., cast[int](0d).")
|
||||
if tfHasMeta in targetType.flags:
|
||||
localError(c.config, n[0].info, "cannot cast to a non concrete type: '$1'" % $targetType)
|
||||
if not isCastable(c, targetType, castedExpr.typ, n.info):
|
||||
@@ -691,6 +693,9 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
proc fixAbstractType(c: PContext, n: PNode) =
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
if it == nil:
|
||||
localError(c.config, n.info, "'$1' has nil child at index $2" % [renderTree(n, {renderNoComments}), $i])
|
||||
return
|
||||
# do not get rid of nkHiddenSubConv for OpenArrays, the codegen needs it:
|
||||
if it.kind == nkHiddenSubConv and
|
||||
skipTypes(it.typ, abstractVar).kind notin {tyOpenArray, tyVarargs}:
|
||||
@@ -736,7 +741,7 @@ proc hasUnresolvedArgs(c: PContext, n: PNode): bool =
|
||||
if hasUnresolvedArgs(c, n[i]): return true
|
||||
return false
|
||||
|
||||
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||
proc newHiddenAddrTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
|
||||
if n.kind == nkHiddenDeref and not (c.config.backend == backendCpp or
|
||||
sfCompileToCpp in c.module.flags):
|
||||
checkSonsLen(n, 1, c.config)
|
||||
@@ -745,13 +750,17 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
||||
result.add n
|
||||
let aa = isAssignable(c, n)
|
||||
let sym = getRoot(n)
|
||||
if aa notin {arLValue, arLocalLValue}:
|
||||
if aa == arDiscriminant and c.inUncheckedAssignSection > 0:
|
||||
discard "allow access within a cast(unsafeAssign) section"
|
||||
elif strictDefs in c.features and aa == arAddressableConst and
|
||||
sym != nil and sym.kind == skLet and isOutParam:
|
||||
discard "allow let varaibles to be passed to out parameters"
|
||||
else:
|
||||
localError(c.config, n.info, errVarForOutParamNeededX % renderNotLValue(n))
|
||||
|
||||
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||
proc analyseIfAddressTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
|
||||
result = n
|
||||
case n.kind
|
||||
of nkSym:
|
||||
@@ -759,7 +768,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||
if n.sym.typ != nil and
|
||||
skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
|
||||
incl(n.sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
of nkDotExpr:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
if n[1].kind != nkSym:
|
||||
@@ -767,14 +776,14 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||
return
|
||||
if skipTypes(n[1].sym.typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
|
||||
incl(n[1].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
if skipTypes(n[0].typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
|
||||
if n[0].kind == nkSym: incl(n[0].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
else:
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
|
||||
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
@@ -820,7 +829,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
if i < t.len and
|
||||
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind in {tyVar}:
|
||||
if n[i].kind != nkHiddenAddr:
|
||||
n[i] = analyseIfAddressTaken(c, n[i])
|
||||
n[i] = analyseIfAddressTaken(c, n[i], isOutParam(skipTypes(t[i], abstractInst-{tyTypeDesc})))
|
||||
|
||||
include semmagic
|
||||
|
||||
@@ -1266,15 +1275,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
of skMacro:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0):
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
result = semMacroExpr(c, n, n, s, flags)
|
||||
of skTemplate:
|
||||
of skMacro, skTemplate:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0) or
|
||||
sfCustomPragma in sym.flags:
|
||||
@@ -1283,7 +1284,10 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
onUse(info, s)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
result = semTemplateExpr(c, n, s, flags)
|
||||
case s.kind
|
||||
of skMacro: result = semMacroExpr(c, n, n, s, flags)
|
||||
of skTemplate: result = semTemplateExpr(c, n, s, flags)
|
||||
else: discard # unreachable
|
||||
of skParam:
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
@@ -1817,11 +1821,16 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
# a = b # both are vars, means: a[] = b[]
|
||||
# a = b # b no 'var T' means: a = addr(b)
|
||||
var le = a.typ
|
||||
let assignable = isAssignable(c, a)
|
||||
let root = getRoot(a)
|
||||
let useStrictDefLet = root != nil and root.kind == skLet and
|
||||
assignable == arAddressableConst and
|
||||
strictDefs in c.features and isLocalSym(root)
|
||||
if le == nil:
|
||||
localError(c.config, a.info, "expression has no type")
|
||||
elif (skipTypes(le, {tyGenericInst, tyAlias, tySink}).kind notin {tyVar} and
|
||||
isAssignable(c, a) in {arNone, arLentValue, arAddressableConst}) or (
|
||||
skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs} and views notin c.features):
|
||||
assignable in {arNone, arLentValue, arAddressableConst} and not useStrictDefLet
|
||||
) or (skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs} and views notin c.features):
|
||||
# Direct assignment to a discriminant is allowed!
|
||||
localError(c.config, a.info, errXCannotBeAssignedTo %
|
||||
renderTree(a, {renderNoComments}))
|
||||
@@ -1834,6 +1843,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
var rhsTyp = rhs.typ
|
||||
if rhsTyp.kind in tyUserTypeClasses and rhsTyp.isResolvedUserTypeClass:
|
||||
rhsTyp = rhsTyp.lastSon
|
||||
if lhs.sym.typ.kind == tyAnything:
|
||||
rhsTyp = rhsTyp.skipIntLit(c.idgen)
|
||||
if cmpTypes(c, lhs.typ, rhsTyp) in {isGeneric, isEqual}:
|
||||
internalAssert c.config, c.p.resultSym != nil
|
||||
# Make sure the type is valid for the result variable
|
||||
@@ -1907,8 +1918,8 @@ proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
else:
|
||||
localError(c.config, c.p.resultSym.info, errCannotInferReturnType %
|
||||
c.p.owner.name.s)
|
||||
if isInlineIterator(c.p.owner.typ) and c.p.owner.typ[0] != nil and
|
||||
c.p.owner.typ[0].kind == tyUntyped:
|
||||
if isIterator(c.p.owner.typ) and c.p.owner.typ[0] != nil and
|
||||
c.p.owner.typ[0].kind == tyAnything:
|
||||
localError(c.config, c.p.owner.info, errCannotInferReturnType %
|
||||
c.p.owner.name.s)
|
||||
closeScope(c)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import
|
||||
strutils, options, ast, trees, nimsets,
|
||||
platform, math, msgs, idents, renderer, types,
|
||||
commands, magicsys, modulegraphs, strtabs, lineinfos
|
||||
commands, magicsys, modulegraphs, strtabs, lineinfos, wordrecg
|
||||
|
||||
from system/memory import nimCStrLen
|
||||
|
||||
@@ -371,6 +371,11 @@ proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
|
||||
localError(g.config, n.info, "cannot convert " & $value &
|
||||
" to " & typeToString(n.typ))
|
||||
|
||||
proc floatRangeCheck(n: PNode, value: BiggestFloat; g: ModuleGraph) =
|
||||
if value < firstFloat(n.typ) or value > lastFloat(n.typ):
|
||||
localError(g.config, n.info, "cannot convert " & $value &
|
||||
" to " & typeToString(n.typ))
|
||||
|
||||
proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): PNode =
|
||||
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
||||
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
||||
@@ -490,6 +495,81 @@ proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
|
||||
else:
|
||||
result.typ = s.typ
|
||||
|
||||
proc foldDefine(m, s: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
var name = s.name.s
|
||||
let prag = extractPragma(s)
|
||||
if prag != nil:
|
||||
for it in prag:
|
||||
if it.kind in nkPragmaCallKinds and it.len == 2 and it[0].kind == nkIdent:
|
||||
let word = whichKeyword(it[0].ident)
|
||||
if word in {wStrDefine, wIntDefine, wBoolDefine, wDefine}:
|
||||
# should be processed in pragmas.nim already
|
||||
if it[1].kind in {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||
name = it[1].strVal
|
||||
if isDefined(g.config, name):
|
||||
let str = g.config.symbols[name]
|
||||
case s.magic
|
||||
of mIntDefine:
|
||||
try:
|
||||
result = newIntNodeT(toInt128(str.parseInt), n, idgen, g)
|
||||
except ValueError:
|
||||
localError(g.config, s.info,
|
||||
"{.intdefine.} const was set to an invalid integer: '" &
|
||||
str & "'")
|
||||
of mStrDefine:
|
||||
result = newStrNodeT(str, n, g)
|
||||
of mBoolDefine:
|
||||
try:
|
||||
result = newIntNodeT(toInt128(str.parseBool.int), n, idgen, g)
|
||||
except ValueError:
|
||||
localError(g.config, s.info,
|
||||
"{.booldefine.} const was set to an invalid bool: '" &
|
||||
str & "'")
|
||||
of mGenericDefine:
|
||||
let rawTyp = s.typ
|
||||
# pretend we don't support distinct types
|
||||
let typ = rawTyp.skipTypes(abstractVarRange-{tyDistinct})
|
||||
try:
|
||||
template intNode(value): PNode =
|
||||
let val = toInt128(value)
|
||||
rangeCheck(n, val, g)
|
||||
newIntNodeT(val, n, idgen, g)
|
||||
case typ.kind
|
||||
of tyString, tyCstring:
|
||||
result = newStrNodeT(str, n, g)
|
||||
of tyInt..tyInt64:
|
||||
result = intNode(str.parseBiggestInt)
|
||||
of tyUInt..tyUInt64:
|
||||
result = intNode(str.parseBiggestUInt)
|
||||
of tyBool:
|
||||
result = intNode(str.parseBool.int)
|
||||
of tyEnum:
|
||||
# compile time parseEnum
|
||||
let ident = getIdent(g.cache, str)
|
||||
for e in typ.n:
|
||||
if e.kind != nkSym: internalError(g.config, "foldDefine for enum")
|
||||
let es = e.sym
|
||||
let match =
|
||||
if es.ast.isNil:
|
||||
es.name.id == ident.id
|
||||
else:
|
||||
es.ast.strVal == str
|
||||
if match:
|
||||
result = intNode(es.position)
|
||||
break
|
||||
if result.isNil:
|
||||
raise newException(ValueError, "invalid enum value: " & str)
|
||||
else:
|
||||
localError(g.config, s.info, "unsupported type $1 for define '$2'" %
|
||||
[name, typeToString(rawTyp)])
|
||||
except ValueError as e:
|
||||
localError(g.config, s.info,
|
||||
"could not process define '$1' of type $2; $3" %
|
||||
[name, typeToString(rawTyp), e.msg])
|
||||
else: result = copyTree(s.astdef) # unreachable
|
||||
else:
|
||||
result = copyTree(s.astdef)
|
||||
|
||||
proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
result = nil
|
||||
case n.kind
|
||||
@@ -509,31 +589,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g)
|
||||
of mBuildCPU: result = newStrNodeT(platform.CPU[g.config.target.hostCPU].name.toLowerAscii, n, g)
|
||||
of mAppType: result = getAppType(n, g)
|
||||
of mIntDefine:
|
||||
if isDefined(g.config, s.name.s):
|
||||
try:
|
||||
result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseInt), n, idgen, g)
|
||||
except ValueError:
|
||||
localError(g.config, s.info,
|
||||
"{.intdefine.} const was set to an invalid integer: '" &
|
||||
g.config.symbols[s.name.s] & "'")
|
||||
else:
|
||||
result = copyTree(s.astdef)
|
||||
of mStrDefine:
|
||||
if isDefined(g.config, s.name.s):
|
||||
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
|
||||
else:
|
||||
result = copyTree(s.astdef)
|
||||
of mBoolDefine:
|
||||
if isDefined(g.config, s.name.s):
|
||||
try:
|
||||
result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseBool.int), n, idgen, g)
|
||||
except ValueError:
|
||||
localError(g.config, s.info,
|
||||
"{.booldefine.} const was set to an invalid bool: '" &
|
||||
g.config.symbols[s.name.s] & "'")
|
||||
else:
|
||||
result = copyTree(s.astdef)
|
||||
of mIntDefine, mStrDefine, mBoolDefine, mGenericDefine:
|
||||
result = foldDefine(m, s, n, idgen, g)
|
||||
else:
|
||||
result = copyTree(s.astdef)
|
||||
of skProc, skFunc, skMethod:
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
import
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
wordrecg, strutils, options, guards, lineinfos, semfold, semdata,
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling, tables
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling, tables,
|
||||
semstrictfuncs
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -75,7 +76,7 @@ type
|
||||
guards: TModel # nested guards
|
||||
locked: seq[PNode] # locked locations
|
||||
gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool
|
||||
hasDangerousAssign, isInnerProc: bool
|
||||
isInnerProc: bool
|
||||
inEnforcedNoSideEffects: bool
|
||||
currOptions: TOptions
|
||||
config: ConfigRef
|
||||
@@ -84,6 +85,10 @@ type
|
||||
escapingParams: IntSet
|
||||
PEffects = var TEffects
|
||||
|
||||
const
|
||||
errXCannotBeAssignedTo = "'$1' cannot be assigned to"
|
||||
errLetNeedsInit = "'let' symbol requires an initialization"
|
||||
|
||||
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
|
||||
if typ == nil: return
|
||||
when false:
|
||||
@@ -97,8 +102,8 @@ proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
|
||||
optSeqDestructors in tracked.config.globalOptions:
|
||||
tracked.owner.flags.incl sfInjectDestructors
|
||||
|
||||
proc isLocalVar(a: PEffects, s: PSym): bool =
|
||||
s.typ != nil and (s.kind in {skVar, skResult} or (s.kind == skParam and isOutParam(s.typ))) and
|
||||
proc isLocalSym(a: PEffects, s: PSym): bool =
|
||||
s.typ != nil and (s.kind in {skLet, skVar, skResult} or (s.kind == skParam and isOutParam(s.typ))) and
|
||||
sfGlobal notin s.flags and s.owner == a.owner
|
||||
|
||||
proc lockLocations(a: PEffects; pragma: PNode) =
|
||||
@@ -173,10 +178,15 @@ proc initVar(a: PEffects, n: PNode; volatileCheck: bool) =
|
||||
let n = skipHiddenDeref(n)
|
||||
if n.kind != nkSym: return
|
||||
let s = n.sym
|
||||
if isLocalVar(a, s):
|
||||
if isLocalSym(a, s):
|
||||
if volatileCheck: makeVolatile(a, s)
|
||||
for x in a.init:
|
||||
if x == s.id: return
|
||||
if x == s.id:
|
||||
if strictDefs in a.c.features and s.kind == skLet:
|
||||
localError(a.config, n.info, errXCannotBeAssignedTo %
|
||||
renderTree(n, {renderNoComments}
|
||||
))
|
||||
return
|
||||
a.init.add s.id
|
||||
if a.scopes.getOrDefault(s.id) == a.currentBlock:
|
||||
#[ Consider this case:
|
||||
@@ -204,7 +214,7 @@ proc initVarViaNew(a: PEffects, n: PNode) =
|
||||
# 'x' is not nil, but that doesn't mean its "not nil" children
|
||||
# are initialized:
|
||||
initVar(a, n, volatileCheck=true)
|
||||
elif isLocalVar(a, s):
|
||||
elif isLocalSym(a, s):
|
||||
makeVolatile(a, s)
|
||||
|
||||
proc warnAboutGcUnsafe(n: PNode; conf: ConfigRef) =
|
||||
@@ -322,7 +332,7 @@ proc useVar(a: PEffects, n: PNode) =
|
||||
let s = n.sym
|
||||
if a.inExceptOrFinallyStmt > 0:
|
||||
incl s.flags, sfUsedInFinallyOrExcept
|
||||
if isLocalVar(a, s):
|
||||
if isLocalSym(a, s):
|
||||
if sfNoInit in s.flags:
|
||||
# If the variable is explicitly marked as .noinit. do not emit any error
|
||||
a.init.add s.id
|
||||
@@ -331,7 +341,10 @@ proc useVar(a: PEffects, n: PNode) =
|
||||
message(a.config, n.info, warnProveInit, s.name.s)
|
||||
elif a.leftPartOfAsgn <= 0:
|
||||
if strictDefs in a.c.features:
|
||||
message(a.config, n.info, warnUninit, s.name.s)
|
||||
if s.kind == skLet:
|
||||
localError(a.config, n.info, errLetNeedsInit)
|
||||
else:
|
||||
message(a.config, n.info, warnUninit, s.name.s)
|
||||
# prevent superfluous warnings about the same variable:
|
||||
a.init.add s.id
|
||||
useVarNoInitCheck(a, n, s)
|
||||
@@ -478,6 +491,10 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
let b = n[i]
|
||||
if b.kind == nkExceptBranch:
|
||||
setLen(tracked.init, oldState)
|
||||
for j in 0..<b.len - 1:
|
||||
if b[j].isInfixAs(): # skips initialization checks
|
||||
assert(b[j][2].kind == nkSym)
|
||||
tracked.init.add b[j][2].sym.id
|
||||
track(tracked, b[^1])
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
@@ -637,7 +654,7 @@ proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; ar
|
||||
let paramType = if formals != nil and argIndex < formals.len: formals[argIndex] else: nil
|
||||
if paramType != nil and paramType.kind in {tyVar}:
|
||||
invalidateFacts(tracked.guards, n)
|
||||
if n.kind == nkSym and isLocalVar(tracked, n.sym):
|
||||
if n.kind == nkSym and isLocalSym(tracked, n.sym):
|
||||
makeVolatile(tracked, n.sym)
|
||||
if paramType != nil and paramType.kind == tyProc and tfGcSafe in paramType.flags:
|
||||
let argtype = skipTypes(a.typ, abstractInst)
|
||||
@@ -802,9 +819,12 @@ proc passedToEffectsDelayedParam(tracked: PEffects; n: PNode) =
|
||||
]#
|
||||
|
||||
proc checkForSink(tracked: PEffects; n: PNode) =
|
||||
if tracked.inIfStmt == 0:
|
||||
if tracked.inIfStmt == 0 and optSinkInference in tracked.config.options:
|
||||
checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n)
|
||||
|
||||
proc strictFuncsActive(tracked: PEffects): bool {.inline.} =
|
||||
sfNoSideEffect in tracked.owner.flags and strictFuncs in tracked.c.features and not tracked.inEnforcedNoSideEffects
|
||||
|
||||
proc trackCall(tracked: PEffects; n: PNode) =
|
||||
template gcsafeAndSideeffectCheck() =
|
||||
if notGcSafe(op) and not importedFromC(a):
|
||||
@@ -909,12 +929,15 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
createTypeBoundOps(tracked, paramType[0], n.info)
|
||||
checkForSink(tracked, n[i])
|
||||
of tyVar:
|
||||
tracked.hasDangerousAssign = true
|
||||
if isOutParam(paramType):
|
||||
# consider this case: p(out x, x); we want to remark that 'x' is not
|
||||
# initialized until after the call. Since we do this after we analysed the
|
||||
# call, this is fine.
|
||||
initVar(tracked, n[i].skipAddr, false)
|
||||
if tracked.strictFuncsActive and isDangerousLocation(n[i].skipAddr, tracked.owner):
|
||||
localError(tracked.config, n[i].info,
|
||||
"cannot pass $1 to `var T` parameter within a strict func" % renderTree(n[i]))
|
||||
tracked.hasSideEffect = true
|
||||
else: discard
|
||||
|
||||
type
|
||||
@@ -1025,7 +1048,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
# bug #15038: ensure consistency
|
||||
if not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ): n.typ = n.sym.typ
|
||||
of nkHiddenAddr, nkAddr:
|
||||
if n[0].kind == nkSym and isLocalVar(tracked, n[0].sym):
|
||||
if n[0].kind == nkSym and isLocalSym(tracked, n[0].sym):
|
||||
useVarNoInitCheck(tracked, n[0], n[0].sym)
|
||||
else:
|
||||
track(tracked, n[0])
|
||||
@@ -1065,10 +1088,12 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
when false: cstringCheck(tracked, n)
|
||||
if tracked.owner.kind != skMacro and n[0].typ.kind notin {tyOpenArray, tyVarargs}:
|
||||
createTypeBoundOps(tracked, n[0].typ, n.info)
|
||||
if n[0].kind != nkSym or not isLocalVar(tracked, n[0].sym):
|
||||
if n[0].kind != nkSym or not isLocalSym(tracked, n[0].sym):
|
||||
checkForSink(tracked, n[1])
|
||||
if not tracked.hasDangerousAssign and n[0].kind != nkSym:
|
||||
tracked.hasDangerousAssign = true
|
||||
if tracked.strictFuncsActive and isDangerousLocation(n[0], tracked.owner):
|
||||
tracked.hasSideEffect = true
|
||||
localError(tracked.config, n[0].info,
|
||||
"cannot mutate location $1 within a strict func" % renderTree(n[0]))
|
||||
of nkVarSection, nkLetSection:
|
||||
for child in n:
|
||||
let last = lastSon(child)
|
||||
@@ -1501,17 +1526,9 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
effects[ensuresEffects] = ensuresSpec
|
||||
|
||||
var mutationInfo = MutationInfo()
|
||||
var hasMutationSideEffect = false
|
||||
if {strictFuncs, views} * c.features != {}:
|
||||
var goals: set[Goal] = {}
|
||||
if strictFuncs in c.features: goals.incl constParameters
|
||||
if views in c.features: goals.incl borrowChecking
|
||||
var partitions = computeGraphPartitions(s, body, g, goals)
|
||||
if not t.hasSideEffect and t.hasDangerousAssign:
|
||||
t.hasSideEffect = varpartitions.hasSideEffect(partitions, mutationInfo)
|
||||
hasMutationSideEffect = t.hasSideEffect
|
||||
if views in c.features:
|
||||
checkBorrowedLocations(partitions, body, g.config)
|
||||
if views in c.features:
|
||||
var partitions = computeGraphPartitions(s, body, g, {borrowChecking})
|
||||
checkBorrowedLocations(partitions, body, g.config)
|
||||
|
||||
if sfThread in s.flags and t.gcUnsafe:
|
||||
if optThreads in g.config.globalOptions and optThreadAnalysis in g.config.globalOptions:
|
||||
@@ -1524,9 +1541,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
when false:
|
||||
listGcUnsafety(s, onlyWarning=false, g.config)
|
||||
else:
|
||||
if hasMutationSideEffect:
|
||||
localError(g.config, s.info, "'$1' can have side effects$2" % [s.name.s, g.config $ mutationInfo])
|
||||
elif c.compilesContextId == 0: # don't render extended diagnostic messages in `system.compiles` context
|
||||
if c.compilesContextId == 0: # don't render extended diagnostic messages in `system.compiles` context
|
||||
var msg = ""
|
||||
listSideEffects(msg, s, g.config, t.c)
|
||||
message(g.config, s.info, errGenerated, msg)
|
||||
|
||||
@@ -509,13 +509,6 @@ proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
let it = pragmas[i]
|
||||
let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
|
||||
|
||||
when false:
|
||||
let lhs = b[0]
|
||||
let clash = strTableGet(c.currentScope.symbols, lhs.ident)
|
||||
if clash != nil:
|
||||
# refs https://github.com/nim-lang/Nim/issues/8275
|
||||
wrongRedefinition(c, lhs.info, lhs.ident.s, clash.info)
|
||||
|
||||
if isPossibleMacroPragma(c, it, key):
|
||||
# we transform ``var p {.m, rest.}`` into ``m(do: var p {.rest.})`` and
|
||||
# let the semantic checker deal with it:
|
||||
@@ -562,38 +555,18 @@ proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
|
||||
doAssert result != nil
|
||||
|
||||
# since a macro pragma can set pragmas, we process these here again.
|
||||
# This is required for SqueakNim-like export pragmas.
|
||||
if false and result.kind in {nkVarSection, nkLetSection, nkConstSection}:
|
||||
var validPragmas: TSpecialWords
|
||||
case result.kind
|
||||
of nkVarSection:
|
||||
validPragmas = varPragmas
|
||||
of nkLetSection:
|
||||
validPragmas = letPragmas
|
||||
of nkConstSection:
|
||||
validPragmas = constPragmas
|
||||
else:
|
||||
# unreachable
|
||||
discard
|
||||
for defs in result:
|
||||
for i in 0 ..< defs.len - 2:
|
||||
let ex = defs[i]
|
||||
if ex.kind == nkPragmaExpr and
|
||||
ex[namePos].kind == nkSym and
|
||||
ex[pragmaPos].kind != nkEmpty:
|
||||
pragma(c, defs[lhsPos][namePos].sym, defs[lhsPos][pragmaPos], validPragmas)
|
||||
return result
|
||||
|
||||
template isLocalSym(sym: PSym): bool =
|
||||
sym.kind in {skVar, skLet} and not
|
||||
({sfGlobal, sfPure} * sym.flags != {} or
|
||||
sfCompileTime in sym.flags) or
|
||||
sym.kind in {skProc, skFunc, skIterator} and
|
||||
sfGlobal notin sym.flags
|
||||
|
||||
template isLocalVarSym(n: PNode): bool =
|
||||
n.kind == nkSym and
|
||||
(n.sym.kind in {skVar, skLet} and not
|
||||
({sfGlobal, sfPure} <= n.sym.flags or
|
||||
sfCompileTime in n.sym.flags) or
|
||||
n.sym.kind in {skProc, skFunc, skIterator} and
|
||||
sfGlobal notin n.sym.flags
|
||||
)
|
||||
|
||||
n.kind == nkSym and isLocalSym(n.sym)
|
||||
|
||||
proc usesLocalVar(n: PNode): bool =
|
||||
for z in 1 ..< n.len:
|
||||
if n[z].isLocalVarSym:
|
||||
@@ -746,7 +719,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
else:
|
||||
checkNilable(c, v)
|
||||
# allow let to not be initialised if imported from C:
|
||||
if v.kind == skLet and sfImportc notin v.flags:
|
||||
if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
|
||||
localError(c.config, a.info, errLetNeedsInit)
|
||||
if sfCompileTime in v.flags:
|
||||
var x = newNodeI(result.kind, v.info)
|
||||
@@ -1389,7 +1362,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
rawAddSon(s.typ, newTypeS(tyNone, c))
|
||||
s.ast = a
|
||||
inc c.inGenericContext
|
||||
var body = semTypeNode(c, a[2], nil)
|
||||
var body = semTypeNode(c, a[2], s.typ)
|
||||
dec c.inGenericContext
|
||||
if body != nil:
|
||||
body.sym = s
|
||||
@@ -1710,12 +1683,6 @@ proc semProcAnnotation(c: PContext, prc: PNode;
|
||||
|
||||
doAssert result != nil
|
||||
|
||||
# since a proc annotation can set pragmas, we process these here again.
|
||||
# This is required for SqueakNim-like export pragmas.
|
||||
if false and result.kind in procDefs and result[namePos].kind == nkSym and
|
||||
result[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
|
||||
|
||||
return result
|
||||
|
||||
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} =
|
||||
@@ -1881,6 +1848,8 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
if s.magic == mAsgn: return
|
||||
incl(s.flags, sfUsed)
|
||||
incl(s.flags, sfOverriden)
|
||||
if name == "=":
|
||||
message(c.config, n.info, warnDeprecated, "Overriding `=` hook is deprecated; Override `=copy` hook instead")
|
||||
let t = s.typ
|
||||
if t.len == 3 and t[0] == nil and t[1].kind == tyVar:
|
||||
var obj = t[1][0]
|
||||
@@ -2210,8 +2179,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if hasProto: localError(c.config, n.info, errImplOfXexpected % proto.name.s)
|
||||
if {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone:
|
||||
# this is a forward declaration and we're building the prototype
|
||||
if s.kind in {skProc, skFunc} and s.typ[0] != nil and s.typ[0].kind == tyUntyped:
|
||||
# `auto` is represented as `tyUntyped` at this point in compilation.
|
||||
if s.kind in {skProc, skFunc} and s.typ[0] != nil and s.typ[0].kind == tyAnything:
|
||||
localError(c.config, n[paramsPos][0].info, "return type 'auto' cannot be used in forward declarations")
|
||||
|
||||
incl(s.flags, sfForward)
|
||||
@@ -2478,9 +2446,12 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType =
|
||||
else:
|
||||
n.typ = n[i].typ
|
||||
if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
|
||||
if n[i].kind in nkLastBlockStmts or
|
||||
n[i].kind in nkCallKinds and n[i][0].kind == nkSym and
|
||||
sfNoReturn in n[i][0].sym.flags:
|
||||
var m = n[i]
|
||||
while m.kind in {nkStmtListExpr, nkStmtList} and m.len > 0: # from templates
|
||||
m = m.lastSon
|
||||
if m.kind in nkLastBlockStmts or
|
||||
m.kind in nkCallKinds and m[0].kind == nkSym and
|
||||
sfNoReturn in m[0].sym.flags:
|
||||
for j in i + 1..<n.len:
|
||||
case n[j].kind
|
||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkState: discard
|
||||
|
||||
55
compiler/semstrictfuncs.nim
Normal file
55
compiler/semstrictfuncs.nim
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2022 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## New "strict funcs" checking. Much simpler and hopefully easier to teach than
|
||||
## the old but more advanced algorithm that can/could be found in `varpartitions.nim`.
|
||||
|
||||
import ast, typeallowed, renderer
|
||||
from aliasanalysis import PathKinds0, PathKinds1
|
||||
from trees import getMagic
|
||||
|
||||
proc isDangerousLocation*(n: PNode; owner: PSym): bool =
|
||||
var n = n
|
||||
var hasDeref = false
|
||||
while true:
|
||||
case n.kind
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
if n[0].typ.kind != tyVar:
|
||||
hasDeref = true
|
||||
n = n[0]
|
||||
of PathKinds0 - {nkDerefExpr, nkHiddenDeref}:
|
||||
n = n[0]
|
||||
of PathKinds1:
|
||||
n = n[1]
|
||||
of nkCallKinds:
|
||||
if n.len > 1:
|
||||
if (n.typ != nil and classifyViewType(n.typ) != noView) or getMagic(n) == mSlice:
|
||||
# borrow from first parameter:
|
||||
n = n[1]
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
if n.kind == nkSym:
|
||||
# dangerous if contains a pointer deref or if it doesn't belong to us:
|
||||
result = hasDeref or n.sym.owner != owner
|
||||
when false:
|
||||
# store to something that belongs to a `var` parameter is fine:
|
||||
let s = n.sym
|
||||
if s.kind == skParam:
|
||||
# dangerous unless a `var T` parameter:
|
||||
result = s.typ.kind != tyVar
|
||||
else:
|
||||
# dangerous if contains a pointer deref or if it doesn't belong to us:
|
||||
result = hasDeref or s.owner != owner
|
||||
else:
|
||||
# dangerous if it contains a pointer deref
|
||||
result = hasDeref
|
||||
@@ -691,7 +691,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
elif not comesFromShadowscope:
|
||||
if {sfTemplateRedefinition, sfGenSym} * s.flags == {}:
|
||||
#wrongRedefinition(c, n.info, proto.name.s, proto.info)
|
||||
message(c.config, n.info, warnTemplateRedefinition, s.name.s)
|
||||
message(c.config, n.info, warnImplicitTemplateRedefinition, s.name.s)
|
||||
symTabReplace(c.currentScope.symbols, proto, s)
|
||||
if n[patternPos].kind != nkEmpty:
|
||||
c.patterns.add(s)
|
||||
|
||||
@@ -38,7 +38,7 @@ const
|
||||
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"
|
||||
|
||||
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
||||
if prev == nil:
|
||||
if prev == nil or prev.kind == tyGenericBody:
|
||||
result = newTypeS(kind, c)
|
||||
else:
|
||||
result = prev
|
||||
@@ -777,9 +777,10 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecWhen:
|
||||
var a = copyTree(n)
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
for i in 0..<a.len:
|
||||
var it = a[i]
|
||||
if it == nil: illFormedAst(n, c.config)
|
||||
var idx = 1
|
||||
case it.kind
|
||||
@@ -805,7 +806,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
semRecordNodeAux(c, it[idx], newCheck, newPos, newf, rectype, hasCaseFields)
|
||||
it[idx] = if newf.len == 1: newf[0] else: newf
|
||||
if c.inGenericContext > 0:
|
||||
father.add n
|
||||
father.add a
|
||||
elif branch != nil:
|
||||
semRecordNodeAux(c, branch, check, pos, father, rectype, hasCaseFields)
|
||||
elif father.kind in {nkElse, nkOfBranch}:
|
||||
@@ -977,7 +978,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
let n = if n[0].kind == nkBracket: n[0] else: n
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
let body = n.lastSon
|
||||
var t = if prev != nil and body.kind == nkObjectTy:
|
||||
var t = if prev != nil and prev.kind != tyGenericBody and body.kind == nkObjectTy:
|
||||
semObjectNode(c, body, nil, prev.flags)
|
||||
else:
|
||||
semTypeNode(c, body, nil)
|
||||
@@ -1404,9 +1405,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
"' is only valid for macros and templates")
|
||||
# 'auto' as a return type does not imply a generic:
|
||||
elif r.kind == tyAnything:
|
||||
# 'p(): auto' and 'p(): untyped' are equivalent, but the rest of the
|
||||
# compiler is hardly aware of 'auto':
|
||||
r = newTypeS(tyUntyped, c)
|
||||
discard
|
||||
elif r.kind == tyStatic:
|
||||
# type allowed should forbid this type
|
||||
discard
|
||||
@@ -1575,21 +1574,23 @@ proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType =
|
||||
result = newTypeS(tyAlias, c)
|
||||
result.rawAddSon typeExpr
|
||||
result.sym = prev.sym
|
||||
assignType(prev, result)
|
||||
if prev.kind != tyGenericBody:
|
||||
assignType(prev, result)
|
||||
|
||||
proc fixupTypeOf(c: PContext, prev: PType, typExpr: PNode) =
|
||||
if prev != nil:
|
||||
let result = newTypeS(tyAlias, c)
|
||||
result.rawAddSon typExpr.typ
|
||||
result.sym = prev.sym
|
||||
assignType(prev, result)
|
||||
if prev.kind != tyGenericBody:
|
||||
assignType(prev, result)
|
||||
|
||||
proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
|
||||
var n = semExprWithType(c, n, {efDetermineType})
|
||||
if n.typ.kind == tyTypeDesc:
|
||||
result = n.typ.base
|
||||
# fix types constructed by macros/template:
|
||||
if prev != nil and prev.sym != nil:
|
||||
if prev != nil and prev.kind != tyGenericBody and prev.sym != nil:
|
||||
if result.sym.isNil:
|
||||
# Behold! you're witnessing enormous power yielded
|
||||
# by macros. Only macros can summon unnamed types
|
||||
@@ -1610,7 +1611,7 @@ proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
|
||||
result = errorType(c)
|
||||
|
||||
proc freshType(c: PContext; res, prev: PType): PType {.inline.} =
|
||||
if prev.isNil:
|
||||
if prev.isNil or prev.kind == tyGenericBody:
|
||||
result = copyType(res, nextTypeId c.idgen, res.owner)
|
||||
copyTypeProps(c.graph, c.idgen.module, result, res)
|
||||
else:
|
||||
@@ -1988,6 +1989,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
let alias = maybeAliasType(c, s.typ, prev)
|
||||
if alias != nil:
|
||||
result = alias
|
||||
elif prev.kind == tyGenericBody:
|
||||
result = s.typ
|
||||
else:
|
||||
assignType(prev, s.typ)
|
||||
# bugfix: keep the fresh id for aliases to integral types:
|
||||
@@ -2007,7 +2010,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
let alias = maybeAliasType(c, t, prev)
|
||||
if alias != nil:
|
||||
result = alias
|
||||
elif prev == nil:
|
||||
elif prev == nil or prev.kind == tyGenericBody:
|
||||
result = t
|
||||
else:
|
||||
assignType(prev, t)
|
||||
|
||||
@@ -499,10 +499,20 @@ proc propagateFieldFlags(t: PType, n: PNode) =
|
||||
|
||||
proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
template bailout =
|
||||
if t.sym != nil and sfGeneratedType in t.sym.flags:
|
||||
# Only consider the recursion limit if the symbol is a type with generic
|
||||
# parameters that have not been explicitly supplied, typechecking should
|
||||
# terminate when generic parameters are explicitly supplied.
|
||||
if (t.sym == nil) or (t.sym != nil and sfGeneratedType in t.sym.flags):
|
||||
# In the first case 't.sym' can be 'nil' if the type is a ref/ptr, see
|
||||
# issue https://github.com/nim-lang/Nim/issues/20416 for more details.
|
||||
# Fortunately for us this works for now because partial ref/ptr types are
|
||||
# not allowed in object construction, eg.
|
||||
# type
|
||||
# Container[T] = ...
|
||||
# O = object
|
||||
# val: ref Container
|
||||
#
|
||||
# In the second case only consider the recursion limit if the symbol is a
|
||||
# type with generic parameters that have not been explicitly supplied,
|
||||
# typechecking should terminate when generic parameters are explicitly
|
||||
# supplied.
|
||||
if cl.recursionLimit > 100:
|
||||
# bail out, see bug #2509. But note this caching is in general wrong,
|
||||
# look at this example where TwoVectors should not share the generic
|
||||
|
||||
@@ -373,14 +373,16 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
|
||||
else:
|
||||
result = t # Note: empty is valid here
|
||||
|
||||
proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
proc handleRange(c: PContext, f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
if a.kind == f.kind:
|
||||
result = isEqual
|
||||
else:
|
||||
let ab = skipTypes(a, {tyRange})
|
||||
let k = ab.kind
|
||||
let nf = c.config.normalizeKind(f.kind)
|
||||
let na = c.config.normalizeKind(k)
|
||||
if k == f.kind: result = isSubrange
|
||||
elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
|
||||
elif k == tyInt and f.kind in {tyRange, tyInt..tyInt64,
|
||||
tyUInt..tyUInt64} and
|
||||
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
|
||||
getInt(ab.n) <= lastOrd(nil, f):
|
||||
@@ -389,9 +391,13 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
# integer literal in the proper range; we want ``i16 + 4`` to stay an
|
||||
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16
|
||||
result = isFromIntLit
|
||||
elif f.kind == tyInt and k in {tyInt8..tyInt32}:
|
||||
elif a.kind == tyInt and nf == c.config.targetSizeSignedToKind:
|
||||
result = isIntConv
|
||||
elif f.kind == tyUInt and k in {tyUInt8..tyUInt32}:
|
||||
elif a.kind == tyUInt and nf == c.config.targetSizeUnsignedToKind:
|
||||
result = isIntConv
|
||||
elif f.kind == tyInt and na in {tyInt8 .. pred(c.config.targetSizeSignedToKind)}:
|
||||
result = isIntConv
|
||||
elif f.kind == tyUInt and na in {tyUInt8 .. pred(c.config.targetSizeUnsignedToKind)}:
|
||||
result = isIntConv
|
||||
elif k >= min and k <= max:
|
||||
result = isConvertible
|
||||
@@ -405,7 +411,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
result = isConvertible
|
||||
else: result = isNone
|
||||
|
||||
proc isConvertibleToRange(f, a: PType): bool =
|
||||
proc isConvertibleToRange(c: PContext, f, a: PType): bool =
|
||||
if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
|
||||
a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
|
||||
case f.kind
|
||||
@@ -413,13 +419,14 @@ proc isConvertibleToRange(f, a: PType): bool =
|
||||
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
|
||||
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
|
||||
# This is wrong, but seems like there's a lot of code that relies on it :(
|
||||
of tyInt, tyUInt, tyUInt64: result = true
|
||||
of tyInt, tyUInt: result = true
|
||||
# of tyInt: result = isIntLit(a) or a.kind in {tyInt8 .. c.config.targetSizeSignedToKind}
|
||||
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
|
||||
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
|
||||
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
|
||||
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
|
||||
#of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
|
||||
#of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
|
||||
# of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8 .. c.config.targetSizeUnsignedToKind}
|
||||
of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt64}
|
||||
else: result = false
|
||||
elif f.kind in {tyFloat..tyFloat128}:
|
||||
# `isIntLit` is correct and should be used above as well, see PR:
|
||||
@@ -1148,18 +1155,18 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let f = skipTypes(f, {tyRange})
|
||||
if f.kind == a.kind and (f.kind != tyEnum or sameEnumTypes(f, a)):
|
||||
result = isIntConv
|
||||
elif isConvertibleToRange(f, a):
|
||||
elif isConvertibleToRange(c.c, f, a):
|
||||
result = isConvertible # a convertible to f
|
||||
of tyInt: result = handleRange(f, a, tyInt8, tyInt32)
|
||||
of tyInt8: result = handleRange(f, a, tyInt8, tyInt8)
|
||||
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
|
||||
of tyInt32: result = handleRange(f, a, tyInt8, tyInt32)
|
||||
of tyInt64: result = handleRange(f, a, tyInt, tyInt64)
|
||||
of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32)
|
||||
of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8)
|
||||
of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16)
|
||||
of tyUInt32: result = handleRange(f, a, tyUInt8, tyUInt32)
|
||||
of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64)
|
||||
of tyInt: result = handleRange(c.c, f, a, tyInt8, c.c.config.targetSizeSignedToKind)
|
||||
of tyInt8: result = handleRange(c.c, f, a, tyInt8, tyInt8)
|
||||
of tyInt16: result = handleRange(c.c, f, a, tyInt8, tyInt16)
|
||||
of tyInt32: result = handleRange(c.c, f, a, tyInt8, tyInt32)
|
||||
of tyInt64: result = handleRange(c.c, f, a, tyInt, tyInt64)
|
||||
of tyUInt: result = handleRange(c.c, f, a, tyUInt8, c.c.config.targetSizeUnsignedToKind)
|
||||
of tyUInt8: result = handleRange(c.c, f, a, tyUInt8, tyUInt8)
|
||||
of tyUInt16: result = handleRange(c.c, f, a, tyUInt8, tyUInt16)
|
||||
of tyUInt32: result = handleRange(c.c, f, a, tyUInt8, tyUInt32)
|
||||
of tyUInt64: result = handleRange(c.c, f, a, tyUInt, tyUInt64)
|
||||
of tyFloat: result = handleFloatRange(f, a)
|
||||
of tyFloat32: result = handleFloatRange(f, a)
|
||||
of tyFloat64: result = handleFloatRange(f, a)
|
||||
@@ -1912,13 +1919,16 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
result.add c.graph.emptyNode
|
||||
result.add arg
|
||||
|
||||
proc isLValue(c: PContext; n: PNode): bool {.inline.} =
|
||||
proc isLValue(c: PContext; n: PNode, isOutParam = false): bool {.inline.} =
|
||||
let aa = isAssignable(nil, n)
|
||||
case aa
|
||||
of arLValue, arLocalLValue, arStrange:
|
||||
result = true
|
||||
of arDiscriminant:
|
||||
result = c.inUncheckedAssignSection > 0
|
||||
of arAddressableConst:
|
||||
let sym = getRoot(n)
|
||||
result = strictDefs in c.features and sym != nil and sym.kind == skLet and isOutParam
|
||||
else:
|
||||
result = false
|
||||
|
||||
@@ -2109,11 +2119,15 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
|
||||
case r
|
||||
of isConvertible:
|
||||
if f.skipTypes({tyRange}).kind in {tyInt, tyUInt}:
|
||||
inc(m.convMatches)
|
||||
inc(m.convMatches)
|
||||
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||
of isIntConv:
|
||||
# I'm too lazy to introduce another ``*matches`` field, so we conflate
|
||||
# ``isIntConv`` and ``isIntLit`` here:
|
||||
if f.skipTypes({tyRange}).kind notin {tyInt, tyUInt}:
|
||||
inc(m.intConvMatches)
|
||||
inc(m.intConvMatches)
|
||||
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||
of isSubtype:
|
||||
@@ -2178,6 +2192,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
return arg
|
||||
elif a.kind == tyVoid and f.matchesVoidProc and argOrig.kind == nkStmtList:
|
||||
# lift do blocks without params to lambdas
|
||||
# now deprecated
|
||||
message(c.config, argOrig.info, warnStmtListLambda)
|
||||
let p = c.graph
|
||||
let lifted = c.semExpr(c, newProcNode(nkDo, argOrig.info, body = argOrig,
|
||||
params = nkFormalParams.newTree(p.emptyNode), name = p.emptyNode, pattern = p.emptyNode,
|
||||
@@ -2383,7 +2399,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
if argConverter.typ.kind notin {tyVar}:
|
||||
m.firstMismatch.kind = kVarNeeded
|
||||
noMatch()
|
||||
elif not isLValue(c, n):
|
||||
elif not (isLValue(c, n, isOutParam(formal.typ))):
|
||||
m.firstMismatch.kind = kVarNeeded
|
||||
noMatch()
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
|
||||
var local = p # sink parameter?
|
||||
passToSink(local)
|
||||
]#
|
||||
if optSinkInference notin config.options: return
|
||||
case arg.kind
|
||||
of nkSym:
|
||||
if arg.sym.kind == skParam and
|
||||
|
||||
@@ -1,383 +1,207 @@
|
||||
import os, strformat, strutils, tables, sets, ropes, json, algorithm
|
||||
import std/[strutils, strscans, parseutils, assertions]
|
||||
|
||||
type
|
||||
SourceNode* = ref object
|
||||
line*: int
|
||||
column*: int
|
||||
source*: string
|
||||
name*: string
|
||||
children*: seq[Child]
|
||||
Segment = object
|
||||
## Segment refers to a block of something in the JS output.
|
||||
## This could be a token or an entire line
|
||||
original: int # Column in the Nim source
|
||||
generated: int # Column in the generated JS
|
||||
name: int # Index into names list (-1 for no name)
|
||||
|
||||
C = enum cSourceNode, cSourceString
|
||||
Mapping = object
|
||||
## Mapping refers to a line in the JS output.
|
||||
## It is made up of segments which refer to the tokens in the line
|
||||
case inSource: bool # Whether the line in JS has Nim equivilant
|
||||
of true:
|
||||
file: int # Index into files list
|
||||
line: int # 0 indexed line of code in the Nim source
|
||||
segments: seq[Segment]
|
||||
else: discard
|
||||
|
||||
Child* = ref object
|
||||
case kind*: C:
|
||||
of cSourceNode:
|
||||
node*: SourceNode
|
||||
of cSourceString:
|
||||
s*: string
|
||||
SourceInfo = object
|
||||
mappings: seq[Mapping]
|
||||
names, files: seq[string]
|
||||
|
||||
SourceMap* = ref object
|
||||
SourceMap* = object
|
||||
version*: int
|
||||
sources*: seq[string]
|
||||
names*: seq[string]
|
||||
mappings*: string
|
||||
file*: string
|
||||
# sourceRoot*: string
|
||||
# sourcesContent*: string
|
||||
|
||||
SourceMapGenerator = ref object
|
||||
file: string
|
||||
sourceRoot: string
|
||||
skipValidation: bool
|
||||
sources: seq[string]
|
||||
names: seq[string]
|
||||
mappings: seq[Mapping]
|
||||
func addSegment(info: var SourceInfo, original, generated: int, name: string = "") {.raises: [].} =
|
||||
## Adds a new segment into the current line
|
||||
assert info.mappings.len > 0, "No lines have been added yet"
|
||||
var segment = Segment(original: original, generated: generated, name: -1)
|
||||
if name != "":
|
||||
# Make name be index into names list
|
||||
segment.name = info.names.find(name)
|
||||
if segment.name == -1:
|
||||
segment.name = info.names.len
|
||||
info.names &= name
|
||||
|
||||
Mapping* = ref object
|
||||
source*: string
|
||||
original*: tuple[line: int, column: int]
|
||||
generated*: tuple[line: int, column: int]
|
||||
name*: string
|
||||
noSource*: bool
|
||||
noName*: bool
|
||||
assert info.mappings[^1].inSource, "Current line isn't in Nim source"
|
||||
info.mappings[^1].segments &= segment
|
||||
|
||||
func newLine(info: var SourceInfo) {.raises: [].} =
|
||||
## Add new mapping which doesn't appear in the Nim source
|
||||
info.mappings &= Mapping(inSource: false)
|
||||
|
||||
proc child*(s: string): Child =
|
||||
Child(kind: cSourceString, s: s)
|
||||
|
||||
|
||||
proc child*(node: SourceNode): Child =
|
||||
Child(kind: cSourceNode, node: node)
|
||||
|
||||
|
||||
proc newSourceNode(line: int, column: int, path: string, node: SourceNode, name: string = ""): SourceNode =
|
||||
SourceNode(line: line, column: column, source: path, name: name, children: @[child(node)])
|
||||
|
||||
|
||||
proc newSourceNode(line: int, column: int, path: string, s: string, name: string = ""): SourceNode =
|
||||
SourceNode(line: line, column: column, source: path, name: name, children: @[child(s)])
|
||||
|
||||
|
||||
proc newSourceNode(line: int, column: int, path: string, children: seq[Child], name: string = ""): SourceNode =
|
||||
SourceNode(line: line, column: column, source: path, name: name, children: children)
|
||||
|
||||
|
||||
|
||||
|
||||
# debugging
|
||||
|
||||
|
||||
proc text*(sourceNode: SourceNode, depth: int): string =
|
||||
let empty = " "
|
||||
result = &"{repeat(empty, depth)}SourceNode({sourceNode.source}:{sourceNode.line}:{sourceNode.column}):\n"
|
||||
for child in sourceNode.children:
|
||||
if child.kind == cSourceString:
|
||||
result.add(&"{repeat(empty, depth + 1)}{child.s}\n")
|
||||
else:
|
||||
result.add(child.node.text(depth + 1))
|
||||
|
||||
|
||||
proc `$`*(sourceNode: SourceNode): string = text(sourceNode, 0)
|
||||
func newLine(info: var SourceInfo, file: string, line: int) {.raises: [].} =
|
||||
## Starts a new line in the mappings. Call addSegment after this to add
|
||||
## segments into the line
|
||||
var mapping = Mapping(inSource: true, line: line)
|
||||
# Set file to file position. Add in if needed
|
||||
mapping.file = info.files.find(file)
|
||||
if mapping.file == -1:
|
||||
mapping.file = info.files.len
|
||||
info.files &= file
|
||||
info.mappings &= mapping
|
||||
|
||||
|
||||
# base64_VLQ
|
||||
func encode*(values: seq[int]): string {.raises: [].} =
|
||||
## Encodes a series of integers into a VLQ base64 encoded string
|
||||
# References:
|
||||
# - https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/
|
||||
# - https://github.com/rails/sprockets/blob/main/guides/source_maps.md#source-map-file
|
||||
const
|
||||
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
shift = 5
|
||||
continueBit = 1 shl 5
|
||||
mask = continueBit - 1
|
||||
for val in values:
|
||||
# Sign is stored in first bit
|
||||
var newVal = abs(val) shl 1
|
||||
if val < 0:
|
||||
newVal = newVal or 1
|
||||
# Now comes the variable length part
|
||||
# This is how we are able to store large numbers
|
||||
while true:
|
||||
# We only encode 5 bits.
|
||||
var masked = newVal and mask
|
||||
newVal = newVal shr shift
|
||||
# If there is still something left
|
||||
# then signify with the continue bit that the
|
||||
# decoder should keep decoding
|
||||
if newVal > 0:
|
||||
masked = masked or continueBit
|
||||
result &= alphabet[masked]
|
||||
# If the value is zero then we have nothing left to encode
|
||||
if newVal == 0:
|
||||
break
|
||||
|
||||
iterator tokenize*(line: string): (int, string) =
|
||||
## Goes through a line and splits it into Nim identifiers and
|
||||
## normal JS code. This allows us to map mangled names back to Nim names.
|
||||
## Yields (column, name). Doesn't yield anything but identifiers.
|
||||
## See mangleName in compiler/jsgen.nim for how name mangling is done
|
||||
var
|
||||
col = 0
|
||||
token = ""
|
||||
while col < line.len:
|
||||
var
|
||||
token: string
|
||||
name: string
|
||||
# First we find the next identifier
|
||||
col += line.skipWhitespace(col)
|
||||
col += line.skipUntil(IdentStartChars, col)
|
||||
let identStart = col
|
||||
col += line.parseIdent(token, col)
|
||||
# Idents will either be originalName_randomInt or HEXhexCode_randomInt
|
||||
if token.startsWith("HEX"):
|
||||
var hex: int
|
||||
# 3 = "HEX".len and we only want to parse the two integers after it
|
||||
discard token[3 ..< 5].parseHex(hex)
|
||||
name = $chr(hex)
|
||||
elif not token.endsWith("_Idx"): # Ignore address indexes
|
||||
# It might be in the form originalName_randomInt
|
||||
let lastUnderscore = token.rfind('_')
|
||||
if lastUnderscore != -1:
|
||||
name = token[0..<lastUnderscore]
|
||||
if name != "":
|
||||
yield (identStart, name)
|
||||
|
||||
let integers = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
||||
|
||||
|
||||
proc encode*(i: int): string =
|
||||
result = ""
|
||||
var n = i
|
||||
if n < 0:
|
||||
n = (-n shl 1) or 1
|
||||
else:
|
||||
n = n shl 1
|
||||
|
||||
var z = 0
|
||||
while z == 0 or n > 0:
|
||||
var e = n and 31
|
||||
n = n shr 5
|
||||
if n > 0:
|
||||
e = e or 32
|
||||
|
||||
result.add(integers[e])
|
||||
z += 1
|
||||
|
||||
|
||||
type TokenState = enum Normal, String, Ident, Mangled
|
||||
|
||||
iterator tokenize*(line: string): (bool, string) =
|
||||
# result = @[]
|
||||
var state = Normal
|
||||
var token = ""
|
||||
var isMangled = false
|
||||
for z, ch in line:
|
||||
if ch.isAlphaAscii:
|
||||
if state == Normal:
|
||||
state = Ident
|
||||
if token.len > 0:
|
||||
yield (isMangled, token)
|
||||
token = $ch
|
||||
isMangled = false
|
||||
else:
|
||||
token.add(ch)
|
||||
elif ch == '_':
|
||||
if state == Ident:
|
||||
state = Mangled
|
||||
isMangled = true
|
||||
token.add($ch)
|
||||
elif ch != '"' and not ch.isAlphaNumeric:
|
||||
if state in {Ident, Mangled}:
|
||||
state = Normal
|
||||
if token.len > 0:
|
||||
yield (isMangled, token)
|
||||
token = $ch
|
||||
isMangled = false
|
||||
else:
|
||||
token.add($ch)
|
||||
elif ch == '"':
|
||||
if state != String:
|
||||
state = String
|
||||
if token.len > 0:
|
||||
yield (isMangled, token)
|
||||
token = $ch
|
||||
isMangled = false
|
||||
else:
|
||||
state = Normal
|
||||
token.add($ch)
|
||||
if token.len > 0:
|
||||
yield (isMangled, token)
|
||||
isMangled = false
|
||||
token = ""
|
||||
func parse*(source: string): SourceInfo =
|
||||
## Parses the JS output for embedded line info
|
||||
## So it can convert those into a series of mappings
|
||||
var
|
||||
skipFirstLine = true
|
||||
currColumn = 0
|
||||
currLine = 0
|
||||
currFile = ""
|
||||
# Add each line as a node into the output
|
||||
for line in source.splitLines():
|
||||
var
|
||||
lineNumber: int
|
||||
linePath: string
|
||||
column: int
|
||||
if line.strip().scanf("/* line $i:$i \"$+\" */", lineNumber, column, linePath):
|
||||
# When we reach the first line mappinsegmentg then we can assume
|
||||
# we can map the rest of the JS lines to Nim lines
|
||||
currColumn = column # Column is already zero indexed
|
||||
currLine = lineNumber - 1
|
||||
currFile = linePath
|
||||
# Lines are zero indexed
|
||||
result.newLine(currFile, currLine)
|
||||
# Skip whitespace to find the starting column
|
||||
result.addSegment(currColumn, line.skipWhitespace())
|
||||
elif currFile != "":
|
||||
result.newLine(currFile, currLine)
|
||||
# There mightn't be any tokens so add a starting segment
|
||||
result.addSegment(currColumn, line.skipWhitespace())
|
||||
for jsColumn, token in line.tokenize:
|
||||
result.addSegment(currColumn, jsColumn, token)
|
||||
else:
|
||||
token.add($ch)
|
||||
if token.len > 0:
|
||||
yield (isMangled, token)
|
||||
result.newLine()
|
||||
|
||||
proc parse*(source: string, path: string): SourceNode =
|
||||
let lines = source.splitLines()
|
||||
var lastLocation: SourceNode = nil
|
||||
result = newSourceNode(0, 0, path, @[])
|
||||
|
||||
# we just use one single parent and add all nim lines
|
||||
# as its children, I guess in typical codegen
|
||||
# that happens recursively on ast level
|
||||
# we also don't have column info, but I doubt more one nim lines can compile to one js
|
||||
# maybe in macros?
|
||||
func toSourceMap*(info: SourceInfo, file: string): SourceMap {.raises: [].} =
|
||||
## Convert from high level SourceInfo into the required SourceMap object
|
||||
# Add basic info
|
||||
result.version = 3
|
||||
result.file = file
|
||||
result.sources = info.files
|
||||
result.names = info.names
|
||||
# Convert nodes into mappings.
|
||||
# Mappings are split into blocks where each block referes to a line in the outputted JS.
|
||||
# Blocks can be seperated into statements which refere to tokens on the line.
|
||||
# Since the mappings depend on previous values we need to
|
||||
# keep track of previous file, name, etc
|
||||
var
|
||||
prevFile = 0
|
||||
prevLine = 0
|
||||
prevName = 0
|
||||
prevNimCol = 0
|
||||
|
||||
for i, originalLine in lines:
|
||||
let line = originalLine.strip
|
||||
if line.len == 0:
|
||||
continue
|
||||
|
||||
# this shouldn't be a problem:
|
||||
# jsgen doesn't generate comments
|
||||
# and if you emit // line you probably know what you're doing
|
||||
if line.startsWith("// line"):
|
||||
if result.children.len > 0:
|
||||
result.children[^1].node.children.add(child(line & "\n"))
|
||||
let pos = line.find(" ", 8)
|
||||
let lineNumber = line[8 .. pos - 1].parseInt
|
||||
let linePath = line[pos + 2 .. ^2] # quotes
|
||||
|
||||
lastLocation = newSourceNode(
|
||||
lineNumber,
|
||||
0,
|
||||
linePath,
|
||||
@[])
|
||||
result.children.add(child(lastLocation))
|
||||
else:
|
||||
var last: SourceNode
|
||||
for token in line.tokenize():
|
||||
var name = ""
|
||||
if token[0]:
|
||||
name = token[1].split('_', 1)[0]
|
||||
|
||||
|
||||
if result.children.len > 0:
|
||||
result.children[^1].node.children.add(
|
||||
child(
|
||||
newSourceNode(
|
||||
result.children[^1].node.line,
|
||||
0,
|
||||
result.children[^1].node.source,
|
||||
token[1],
|
||||
name)))
|
||||
last = result.children[^1].node.children[^1].node
|
||||
else:
|
||||
result.children.add(
|
||||
child(
|
||||
newSourceNode(i + 1, 0, path, token[1], name)))
|
||||
last = result.children[^1].node
|
||||
let nl = "\n"
|
||||
if not last.isNil:
|
||||
last.source.add(nl)
|
||||
for mapping in info.mappings:
|
||||
# We know need to encode segments with the following fields
|
||||
# All these fields are relative to their previous values
|
||||
# - 0: Column in generated code
|
||||
# - 1: Index of Nim file in source list
|
||||
# - 2: Line in Nim source
|
||||
# - 3: Column in Nim source
|
||||
# - 4: Index in names list
|
||||
if mapping.inSource:
|
||||
# JS Column is special in that it is reset after every line
|
||||
var prevJSCol = 0
|
||||
for segment in mapping.segments:
|
||||
var values = @[segment.generated - prevJSCol, mapping.file - prevFile, mapping.line - prevLine, segment.original - prevNimCol]
|
||||
# Add name field if needed
|
||||
if segment.name != -1:
|
||||
values &= segment.name - prevName
|
||||
prevName = segment.name
|
||||
prevJSCol = segment.generated
|
||||
prevNimCol = segment.original
|
||||
prevFile = mapping.file
|
||||
prevLine = mapping.line
|
||||
result.mappings &= encode(values) & ","
|
||||
# Remove trailing ,
|
||||
if mapping.segments.len > 0:
|
||||
result.mappings.setLen(result.mappings.len - 1)
|
||||
|
||||
proc cmp(a: Mapping, b: Mapping): int =
|
||||
var c = cmp(a.generated, b.generated)
|
||||
if c != 0:
|
||||
return c
|
||||
result.mappings &= ";"
|
||||
|
||||
c = cmp(a.source, b.source)
|
||||
if c != 0:
|
||||
return c
|
||||
|
||||
c = cmp(a.original, b.original)
|
||||
if c != 0:
|
||||
return c
|
||||
|
||||
return cmp(a.name, b.name)
|
||||
|
||||
|
||||
proc index*[T](elements: seq[T], element: T): int =
|
||||
for z in 0 ..< elements.len:
|
||||
if elements[z] == element:
|
||||
return z
|
||||
return -1
|
||||
|
||||
|
||||
proc serializeMappings(map: SourceMapGenerator, mappings: seq[Mapping]): string =
|
||||
var previous = Mapping(generated: (line: 1, column: 0), original: (line: 0, column: 0), name: "", source: "")
|
||||
var previousSourceId = 0
|
||||
var previousNameId = 0
|
||||
var next = ""
|
||||
var nameId = 0
|
||||
var sourceId = 0
|
||||
result = ""
|
||||
|
||||
for z, mapping in mappings:
|
||||
next = ""
|
||||
|
||||
if mapping.generated.line != previous.generated.line:
|
||||
previous.generated.column = 0
|
||||
|
||||
while mapping.generated.line != previous.generated.line:
|
||||
next.add(";")
|
||||
previous.generated.line += 1
|
||||
|
||||
else:
|
||||
if z > 0:
|
||||
if cmp(mapping, mappings[z - 1]) == 0:
|
||||
continue
|
||||
next.add(",")
|
||||
|
||||
next.add(encode(mapping.generated.column - previous.generated.column))
|
||||
previous.generated.column = mapping.generated.column
|
||||
|
||||
if not mapping.noSource and mapping.source.len > 0:
|
||||
sourceId = map.sources.index(mapping.source)
|
||||
next.add(encode(sourceId - previousSourceId))
|
||||
previousSourceId = sourceId
|
||||
next.add(encode(mapping.original.line - 1 - previous.original.line))
|
||||
previous.original.line = mapping.original.line - 1
|
||||
next.add(encode(mapping.original.column - previous.original.column))
|
||||
previous.original.column = mapping.original.column
|
||||
|
||||
if not mapping.noName and mapping.name.len > 0:
|
||||
nameId = map.names.index(mapping.name)
|
||||
next.add(encode(nameId - previousNameId))
|
||||
previousNameId = nameId
|
||||
|
||||
result.add(next)
|
||||
|
||||
|
||||
proc gen*(map: SourceMapGenerator): SourceMap =
|
||||
var mappings = map.mappings.sorted do (a: Mapping, b: Mapping) -> int:
|
||||
cmp(a, b)
|
||||
result = SourceMap(
|
||||
file: map.file,
|
||||
version: 3,
|
||||
sources: map.sources[0..^1],
|
||||
names: map.names[0..^1],
|
||||
mappings: map.serializeMappings(mappings))
|
||||
|
||||
|
||||
|
||||
proc addMapping*(map: SourceMapGenerator, mapping: Mapping) =
|
||||
if not mapping.noSource and mapping.source notin map.sources:
|
||||
map.sources.add(mapping.source)
|
||||
|
||||
if not mapping.noName and mapping.name.len > 0 and mapping.name notin map.names:
|
||||
map.names.add(mapping.name)
|
||||
|
||||
# echo "map ", mapping.source, " ", mapping.original, " ", mapping.generated, " ", mapping.name
|
||||
map.mappings.add(mapping)
|
||||
|
||||
|
||||
proc walk*(node: SourceNode, fn: proc(line: string, original: SourceNode)) =
|
||||
for child in node.children:
|
||||
if child.kind == cSourceString and child.s.len > 0:
|
||||
fn(child.s, node)
|
||||
else:
|
||||
child.node.walk(fn)
|
||||
|
||||
|
||||
proc toSourceMap*(node: SourceNode, file: string): SourceMapGenerator =
|
||||
var map = SourceMapGenerator(file: file, sources: @[], names: @[], mappings: @[])
|
||||
|
||||
var generated = (line: 1, column: 0)
|
||||
var sourceMappingActive = false
|
||||
var lastOriginal = SourceNode(source: "", line: -1, column: 0, name: "", children: @[])
|
||||
|
||||
node.walk do (line: string, original: SourceNode):
|
||||
if original.source.endsWith(".js"):
|
||||
# ignore it
|
||||
discard
|
||||
else:
|
||||
if original.line != -1:
|
||||
if lastOriginal.source != original.source or
|
||||
lastOriginal.line != original.line or
|
||||
lastOriginal.column != original.column or
|
||||
lastOriginal.name != original.name:
|
||||
map.addMapping(
|
||||
Mapping(
|
||||
source: original.source,
|
||||
original: (line: original.line, column: original.column),
|
||||
generated: (line: generated.line, column: generated.column),
|
||||
name: original.name))
|
||||
|
||||
lastOriginal = SourceNode(
|
||||
source: original.source,
|
||||
line: original.line,
|
||||
column: original.column,
|
||||
name: original.name,
|
||||
children: lastOriginal.children)
|
||||
sourceMappingActive = true
|
||||
elif sourceMappingActive:
|
||||
map.addMapping(
|
||||
Mapping(
|
||||
noSource: true,
|
||||
noName: true,
|
||||
generated: (line: generated.line, column: generated.column),
|
||||
original: (line: -1, column: -1)))
|
||||
lastOriginal.line = -1
|
||||
sourceMappingActive = false
|
||||
|
||||
for z in 0 ..< line.len:
|
||||
if line[z] in Newlines:
|
||||
generated.line += 1
|
||||
generated.column = 0
|
||||
|
||||
if z == line.len - 1:
|
||||
lastOriginal.line = -1
|
||||
sourceMappingActive = false
|
||||
elif sourceMappingActive:
|
||||
map.addMapping(
|
||||
Mapping(
|
||||
source: original.source,
|
||||
original: (line: original.line, column: original.column),
|
||||
generated: (line: generated.line, column: generated.column),
|
||||
name: original.name))
|
||||
else:
|
||||
generated.column += 1
|
||||
|
||||
map
|
||||
|
||||
|
||||
proc genSourceMap*(source: string, outFile: string): (Rope, SourceMap) =
|
||||
let node = parse(source, outFile)
|
||||
let map = node.toSourceMap(file = outFile)
|
||||
((&"{source}\n//# sourceMappingURL={outFile}.map").rope, map.gen)
|
||||
proc genSourceMap*(source: string, outFile: string): SourceMap =
|
||||
let node = parse(source)
|
||||
result = node.toSourceMap(outFile)
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ proc newTransNode(kind: TNodeKind, n: PNode,
|
||||
sons: int): PNode {.inline.} =
|
||||
var x = newNodeIT(kind, n.info, n.typ)
|
||||
newSeq(x.sons, sons)
|
||||
x.typ = n.typ
|
||||
# x.flags = n.flags
|
||||
result = x
|
||||
|
||||
|
||||
@@ -753,8 +753,13 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
assert(t.n.kind == nkRange)
|
||||
result = getOrdValue(t.n[0])
|
||||
of tyInt:
|
||||
if conf != nil and conf.target.intSize == 4:
|
||||
result = toInt128(-2147483648)
|
||||
if conf != nil:
|
||||
case conf.target.intSize
|
||||
of 8: result = toInt128(0x8000000000000000'i64)
|
||||
of 4: result = toInt128(-2147483648)
|
||||
of 2: result = toInt128(-32768)
|
||||
of 1: result = toInt128(-128)
|
||||
else: discard
|
||||
else:
|
||||
result = toInt128(0x8000000000000000'i64)
|
||||
of tyInt8: result = toInt128(-128)
|
||||
@@ -797,6 +802,29 @@ proc firstFloat*(t: PType): BiggestFloat =
|
||||
internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')')
|
||||
NaN
|
||||
|
||||
proc targetSizeSignedToKind*(conf: ConfigRef): TTypeKind =
|
||||
case conf.target.intSize
|
||||
of 8: result = tyInt64
|
||||
of 4: result = tyInt32
|
||||
of 2: result = tyInt16
|
||||
else: discard
|
||||
|
||||
proc targetSizeUnsignedToKind*(conf: ConfigRef): TTypeKind =
|
||||
case conf.target.intSize
|
||||
of 8: result = tyUInt64
|
||||
of 4: result = tyUInt32
|
||||
of 2: result = tyUInt16
|
||||
else: discard
|
||||
|
||||
proc normalizeKind*(conf: ConfigRef, k: TTypeKind): TTypeKind =
|
||||
case k
|
||||
of tyInt:
|
||||
result = conf.targetSizeSignedToKind()
|
||||
of tyUInt:
|
||||
result = conf.targetSizeUnsignedToKind()
|
||||
else:
|
||||
result = k
|
||||
|
||||
proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
case t.kind
|
||||
of tyBool: result = toInt128(1'u)
|
||||
@@ -808,7 +836,13 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
assert(t.n.kind == nkRange)
|
||||
result = getOrdValue(t.n[1])
|
||||
of tyInt:
|
||||
if conf != nil and conf.target.intSize == 4: result = toInt128(0x7FFFFFFF)
|
||||
if conf != nil:
|
||||
case conf.target.intSize
|
||||
of 8: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
|
||||
of 4: result = toInt128(0x7FFFFFFF)
|
||||
of 2: result = toInt128(0x00007FFF)
|
||||
of 1: result = toInt128(0x0000007F)
|
||||
else: discard
|
||||
else: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
|
||||
of tyInt8: result = toInt128(0x0000007F)
|
||||
of tyInt16: result = toInt128(0x00007FFF)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import ast
|
||||
import ast, idents, lineinfos, astalgo
|
||||
import vmdef
|
||||
import std/times
|
||||
|
||||
template elementType*(T: typedesc): typedesc =
|
||||
typeof(block:
|
||||
@@ -43,3 +45,12 @@ proc toLit*[T](a: T): PNode =
|
||||
else:
|
||||
static: doAssert false, "not yet supported: " & $T # add as needed
|
||||
|
||||
proc toTimeLit*(a: Time, c: PCtx, obj: PNode, info: TLineInfo): PNode =
|
||||
# probably refactor it into `toLit` in the future
|
||||
result = newTree(nkObjConstr)
|
||||
result.add(newNode(nkEmpty)) # can be changed to a symbol according to PType
|
||||
for k, ai in fieldPairs(a):
|
||||
let reti = newNode(nkExprColonExpr)
|
||||
reti.add newSymNode(lookupInRecord(obj, getIdent(c.cache, k)), info)
|
||||
reti.add ai.toLit
|
||||
result.add reti
|
||||
|
||||
@@ -328,8 +328,9 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
registerCallback c, "stdlib.osproc.execCmdEx", proc (a: VmArgs) {.nimcall.} =
|
||||
let options = getNode(a, 1).fromLit(set[osproc.ProcessOption])
|
||||
a.setResult osproc.execCmdEx(getString(a, 0), options).toLit
|
||||
registerCallback c, "stdlib.times.getTime", proc (a: VmArgs) {.nimcall.} =
|
||||
setResult(a, times.getTime().toLit)
|
||||
registerCallback c, "stdlib.times.getTimeImpl", proc (a: VmArgs) =
|
||||
let obj = a.getNode(0).typ.n
|
||||
setResult(a, times.getTime().toTimeLit(c, obj, a.currentLineInfo))
|
||||
|
||||
proc getEffectList(c: PCtx; a: VmArgs; effectIndex: int) =
|
||||
let fn = getNode(a, 0)
|
||||
|
||||
@@ -28,7 +28,9 @@ operatorB = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 |
|
||||
symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
|
||||
| IDENT | KEYW
|
||||
exprColonEqExpr = expr (':'|'=' expr)?
|
||||
exprEqExpr = expr ('=' expr)?
|
||||
exprList = expr ^+ comma
|
||||
optionalExprList = expr ^* comma
|
||||
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
|
||||
qualifiedIdent = symbol ('.' optInd symbol)?
|
||||
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
|
||||
@@ -60,25 +62,26 @@ primarySuffix = '(' (exprColonEqExpr comma?)* ')'
|
||||
| DOTLIKEOP optInd symbol generalizedLit?
|
||||
| '[' optInd exprColonEqExprList optPar ']'
|
||||
| '{' optInd exprColonEqExprList optPar '}'
|
||||
| &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||
pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
|
||||
identVis = symbol OPR? # postfix position
|
||||
identVisDot = symbol '.' optInd symbol OPR?
|
||||
identWithPragma = identVis pragma?
|
||||
identWithPragmaDot = identVisDot pragma?
|
||||
declColonEquals = identWithPragma (comma identWithPragma)* comma?
|
||||
(':' optInd typeDesc)? ('=' optInd expr)?
|
||||
(':' optInd typeDescExpr)? ('=' optInd expr)?
|
||||
identColonEquals = IDENT (comma IDENT)* comma?
|
||||
(':' optInd typeDesc)? ('=' optInd expr)?)
|
||||
tupleDecl = 'tuple'
|
||||
'[' optInd (identColonEquals (comma/semicolon)?)* optPar ']' |
|
||||
COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
|
||||
(':' optInd typeDescExpr)? ('=' optInd expr)?)
|
||||
tupleTypeBracket = '[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
|
||||
tupleType = 'tuple' tupleTypeBracket
|
||||
tupleDecl = 'tuple' (tupleTypeBracket /
|
||||
COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?)
|
||||
paramList = '(' declColonEquals ^* (comma/semicolon) ')'
|
||||
paramListArrow = paramList? ('->' optInd typeDesc)?
|
||||
paramListColon = paramList? (':' optInd typeDesc)?
|
||||
doBlock = 'do' paramListArrow pragma? colcom stmt
|
||||
routineExpr = ('proc' | 'func' | 'iterator') paramListColon pragma? ('=' COMMENT? stmt)?
|
||||
forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
|
||||
routineType = ('proc' | 'iterator') paramListColon pragma?
|
||||
forStmt = 'for' ((varTuple / identWithPragma) ^+ comma) 'in' expr colcom stmt
|
||||
forExpr = forStmt
|
||||
expr = (blockExpr
|
||||
| ifExpr
|
||||
@@ -87,25 +90,32 @@ expr = (blockExpr
|
||||
| forExpr
|
||||
| tryExpr)
|
||||
/ simpleExpr
|
||||
primary = operatorB primary primarySuffix* |
|
||||
tupleDecl | routineExpr | enumDecl
|
||||
objectDecl | conceptDecl | ('bind' primary)
|
||||
('var' | 'out' | 'ref' | 'ptr' | 'distinct') primary
|
||||
/ prefixOperator* identOrLiteral primarySuffix*
|
||||
typeDesc = simpleExpr ('not' expr)?
|
||||
typeDefAux = simpleExpr ('not' expr
|
||||
| postExprBlocks)?
|
||||
simplePrimary = SIGILLIKEOP? identOrLiteral primarySuffix*
|
||||
commandStart = &('`'|IDENT|literal|'cast'|'addr'|'type'|'var'|'out'|
|
||||
'static'|'enum'|'tuple'|'object'|'proc')
|
||||
primary = simplePrimary (commandStart expr)
|
||||
/ operatorB primary
|
||||
/ routineExpr
|
||||
/ rawTypeDesc
|
||||
/ prefixOperator primary
|
||||
rawTypeDesc = (tupleType | routineType | 'enum' | 'object' |
|
||||
('var' | 'out' | 'ref' | 'ptr' | 'distinct') typeDesc?)
|
||||
('not' expr)?
|
||||
typeDescExpr = (routineType / simpleExpr) ('not' expr)?
|
||||
typeDesc = rawTypeDesc / typeDescExpr
|
||||
typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
|
||||
('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
|
||||
/ (simpleExpr (exprEqExpr ^+ comma postExprBlocks)?))
|
||||
('not' expr)?
|
||||
postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||
| IND{=} 'of' exprList ':' stmt
|
||||
| IND{=} 'elif' expr ':' stmt
|
||||
| IND{=} 'except' exprList ':' stmt
|
||||
| IND{=} 'except' optionalExprList ':' stmt
|
||||
| IND{=} 'finally' ':' stmt
|
||||
| IND{=} 'else' ':' stmt )*
|
||||
exprStmt = simpleExpr
|
||||
(( '=' optInd expr colonBody? )
|
||||
/ ( expr ^+ comma
|
||||
postExprBlocks
|
||||
))?
|
||||
exprStmt = simpleExpr postExprBlocks?
|
||||
/ simplePrimary (exprEqExpr ^+ comma) postExprBlocks?
|
||||
/ simpleExpr '=' optInd (expr postExprBlocks?)
|
||||
importStmt = 'import' optInd expr
|
||||
((comma expr)*
|
||||
/ 'except' optInd (expr ^+ comma))
|
||||
@@ -139,10 +149,10 @@ caseStmt = 'case' expr ':'? COMMENT?
|
||||
(IND{>} ofBranches DED
|
||||
| IND{=} ofBranches)
|
||||
tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||
(IND{=}? 'except' exprList colcom stmt)*
|
||||
(IND{=}? 'except' optionalExprList colcom stmt)*
|
||||
(IND{=}? 'finally' colcom stmt)?
|
||||
tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
||||
(optInd 'except' exprList colcom stmt)*
|
||||
(optInd 'except' optionalExprList colcom stmt)*
|
||||
(optInd 'finally' colcom stmt)?
|
||||
blockStmt = 'block' symbol? colcom stmt
|
||||
blockExpr = 'block' symbol? colcom stmt
|
||||
@@ -175,7 +185,7 @@ objectDecl = 'object' ('of' typeDesc)? COMMENT? objectPart
|
||||
conceptParam = ('var' | 'out')? symbol
|
||||
conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
|
||||
&IND{>} stmt
|
||||
typeDef = identVisDot genericParamList? pragma '=' optInd typeDefAux
|
||||
typeDef = identVisDot genericParamList? pragma '=' optInd typeDefValue
|
||||
indAndComment?
|
||||
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||
colonBody = colcom stmt postExprBlocks?
|
||||
|
||||
179
doc/lib.md
179
doc/lib.md
@@ -46,15 +46,19 @@ Core
|
||||
* [bitops](bitops.html)
|
||||
Provides a series of low-level methods for bit manipulation.
|
||||
|
||||
* [compilesettings](compilesettings.html)
|
||||
This module allows querying the compiler about diverse configuration settings.
|
||||
|
||||
* [cpuinfo](cpuinfo.html)
|
||||
This module implements procs to determine the number of CPUs / cores.
|
||||
|
||||
* [effecttraits](effecttraits.html)
|
||||
This module provides access to the inferred .raises effects
|
||||
for Nim's macro system.
|
||||
|
||||
* [endians](endians.html)
|
||||
This module contains helpers that deal with different byte orders.
|
||||
|
||||
* [lenientops](lenientops.html)
|
||||
Provides binary operators for mixed integer/float expressions for convenience.
|
||||
|
||||
* [locks](locks.html)
|
||||
Locks and condition variables for Nim.
|
||||
|
||||
@@ -122,9 +126,19 @@ Collections
|
||||
* [packedsets](packedsets.html)
|
||||
Efficient implementation of a set of ordinals as a sparse bit set.
|
||||
|
||||
* [ropes](ropes.html)
|
||||
This module contains support for a *rope* data type.
|
||||
Ropes can represent very long strings efficiently;
|
||||
in particular, concatenation is done in O(1) instead of O(n).
|
||||
|
||||
* [sets](sets.html)
|
||||
Nim hash set support.
|
||||
|
||||
* [strtabs](strtabs.html)
|
||||
The `strtabs` module implements an efficient hash table that is a mapping
|
||||
from strings to strings. Supports a case-sensitive, case-insensitive and
|
||||
style-insensitive modes.
|
||||
|
||||
* [tables](tables.html)
|
||||
Nim hash table support. Contains tables, ordered tables, and count tables.
|
||||
|
||||
@@ -143,20 +157,15 @@ String handling
|
||||
Converts between different character encodings. On UNIX, this uses
|
||||
the `iconv` library, on Windows the Windows API.
|
||||
|
||||
* [parseutils](parseutils.html)
|
||||
This module contains helpers for parsing tokens, numbers, identifiers, etc.
|
||||
* [formatfloat](formatfloat.html)
|
||||
This module implements formatting floats as strings.
|
||||
|
||||
* [pegs](pegs.html)
|
||||
This module contains procedures and operators for handling PEGs.
|
||||
* [objectdollar](objectdollar.html)
|
||||
This module implements a generic `$` operator to convert objects to strings.
|
||||
|
||||
* [punycode](punycode.html)
|
||||
Implements a representation of Unicode with the limited ASCII character subset.
|
||||
|
||||
* [ropes](ropes.html)
|
||||
This module contains support for a *rope* data type.
|
||||
Ropes can represent very long strings efficiently;
|
||||
in particular, concatenation is done in O(1) instead of O(n).
|
||||
|
||||
* [strbasics](strbasics.html)
|
||||
This module provides some high performance string operations.
|
||||
|
||||
@@ -171,11 +180,6 @@ String handling
|
||||
* [strscans](strscans.html)
|
||||
This module contains a `scanf` macro for convenient parsing of mini languages.
|
||||
|
||||
* [strtabs](strtabs.html)
|
||||
The `strtabs` module implements an efficient hash table that is a mapping
|
||||
from strings to strings. Supports a case-sensitive, case-insensitive and
|
||||
style-insensitive modes.
|
||||
|
||||
* [strutils](strutils.html)
|
||||
This module contains common string handling operations like changing
|
||||
case of a string, splitting a string into substrings, searching for
|
||||
@@ -188,6 +192,9 @@ String handling
|
||||
It provides a single proc that does Unicode to ASCII transliterations.
|
||||
Based on Python's Unidecode module.
|
||||
|
||||
* [widestrs](widestrs.html)
|
||||
Nim support for C/C++'s wide strings.
|
||||
|
||||
* [wordwrap](wordwrap.html)
|
||||
This module contains an algorithm to wordwrap a Unicode string.
|
||||
|
||||
@@ -205,6 +212,16 @@ Time handling
|
||||
Generic Operating System Services
|
||||
---------------------------------
|
||||
|
||||
* [appdirs](appdirs.html)
|
||||
This module implements helpers for determining special directories used by apps.
|
||||
|
||||
* [cmdline](cmdline.html)
|
||||
This module contains system facilities for reading command
|
||||
line parameters.
|
||||
|
||||
* [dirs](dirs.html)
|
||||
This module implements directory handling.
|
||||
|
||||
* [distros](distros.html)
|
||||
This module implements the basics for OS distribution ("distro") detection
|
||||
and the OS's native package manager.
|
||||
@@ -216,9 +233,14 @@ Generic Operating System Services
|
||||
* [dynlib](dynlib.html)
|
||||
This module implements the ability to access symbols from shared libraries.
|
||||
|
||||
* [marshal](marshal.html)
|
||||
Contains procs for serialization and deserialization of arbitrary Nim
|
||||
data structures.
|
||||
* [envvars](envvars.html)
|
||||
This module implements environment variable handling.
|
||||
|
||||
* [exitprocs](exitprocs.html)
|
||||
This module allows adding hooks to program exit.
|
||||
|
||||
* [files](files.html)
|
||||
This module implements file handling.
|
||||
|
||||
* [memfiles](memfiles.html)
|
||||
This module provides support for memory-mapped files (Posix's `mmap`)
|
||||
@@ -229,15 +251,31 @@ Generic Operating System Services
|
||||
reading command line arguments, working with directories, running shell
|
||||
commands, etc.
|
||||
|
||||
* [oserrors](oserrors.html)
|
||||
This module implements OS error reporting.
|
||||
|
||||
* [osproc](osproc.html)
|
||||
Module for process communication beyond `os.execShellCmd`.
|
||||
|
||||
* [paths](paths.html)
|
||||
This module implements path handling.
|
||||
|
||||
* [reservedmem](reservedmem.html)
|
||||
This module provides utilities for reserving portions of the
|
||||
address space of a program without consuming physical memory.
|
||||
|
||||
* [streams](streams.html)
|
||||
This module provides a stream interface and two implementations thereof:
|
||||
the `FileStream` and the `StringStream` which implement the stream
|
||||
interface for Nim file objects (`File`) and strings. Other modules
|
||||
may provide other implementations for this standard stream interface.
|
||||
|
||||
* [symlinks](symlinks.html)
|
||||
This module implements symlink handling.
|
||||
|
||||
* [syncio](syncio.html)
|
||||
This module implements various synchronized I/O operations.
|
||||
|
||||
* [terminal](terminal.html)
|
||||
This module contains a few procedures to control the *terminal*
|
||||
(also called *console*). The implementation simply uses ANSI escape
|
||||
@@ -258,6 +296,9 @@ Math libraries
|
||||
Floating-point environment. Handling of floating-point rounding and
|
||||
exceptions (overflow, zero-divide, etc.).
|
||||
|
||||
* [lenientops](lenientops.html)
|
||||
Provides binary operators for mixed integer/float expressions for convenience.
|
||||
|
||||
* [math](math.html)
|
||||
Mathematical operations like cosine, square root.
|
||||
|
||||
@@ -270,9 +311,6 @@ Math libraries
|
||||
* [stats](stats.html)
|
||||
Statistical analysis.
|
||||
|
||||
* [sums](sums.html)
|
||||
Accurate summation functions.
|
||||
|
||||
* [sysrand](sysrand.html)
|
||||
Cryptographically secure pseudorandom number generator.
|
||||
|
||||
@@ -280,6 +318,9 @@ Math libraries
|
||||
Internet Protocols and Support
|
||||
------------------------------
|
||||
|
||||
* [async](async.html)
|
||||
Exports `asyncmacro` and `asyncfutures` for native backends, and `asyncjs` on the JS backend.
|
||||
|
||||
* [asyncdispatch](asyncdispatch.html)
|
||||
This module implements an asynchronous dispatcher for IO operations.
|
||||
|
||||
@@ -295,6 +336,9 @@ Internet Protocols and Support
|
||||
This module implements an asynchronous HTTP server using the `asyncnet`
|
||||
module.
|
||||
|
||||
* [asyncmacro](asyncmacro.html)
|
||||
Implements the `async` and `multisync` macros for `asyncdispatch`.
|
||||
|
||||
* [asyncnet](asyncnet.html)
|
||||
This module implements asynchronous sockets based on the `asyncdispatch`
|
||||
module.
|
||||
@@ -326,6 +370,13 @@ Internet Protocols and Support
|
||||
This module implements a selector API with backends specific to each OS.
|
||||
Currently, epoll on Linux and select on other operating systems.
|
||||
|
||||
* [smtp](smtp.html)
|
||||
This module implements a simple SMTP client.
|
||||
|
||||
* [socketstreams](socketstreams.html)
|
||||
This module provides an implementation of the streams interface for sockets.
|
||||
|
||||
|
||||
* [uri](uri.html)
|
||||
This module provides functions for working with URIs.
|
||||
|
||||
@@ -333,12 +384,20 @@ Internet Protocols and Support
|
||||
Threading
|
||||
---------
|
||||
|
||||
* [threads](threads.html)
|
||||
Basic Nim thread support.
|
||||
* [isolation](isolation.html)
|
||||
This module implements the `Isolated[T]` type for
|
||||
safe construction of isolated subgraphs that can be
|
||||
passed efficiently to different channels and threads.
|
||||
|
||||
* [tasks](tasks.html)
|
||||
This module provides basic primitives for creating parallel programs.
|
||||
|
||||
* [threadpool](threadpool.html)
|
||||
Implements Nim's [spawn](manual_experimental.html#parallel-amp-spawn).
|
||||
|
||||
* [typedthreads](typedthreads.html)
|
||||
Basic Nim thread support.
|
||||
|
||||
|
||||
Parsers
|
||||
-------
|
||||
@@ -349,9 +408,6 @@ Parsers
|
||||
* [json](json.html)
|
||||
High-performance JSON parser.
|
||||
|
||||
* [jsonutils](jsonutils.html)
|
||||
This module implements a hookable (de)serialization for arbitrary types.
|
||||
|
||||
* [lexbase](lexbase.html)
|
||||
This is a low-level module that implements an extremely efficient buffering
|
||||
scheme for lexers and parsers. This is used by the diverse parsing modules.
|
||||
@@ -375,12 +431,18 @@ Parsers
|
||||
* [parsesql](parsesql.html)
|
||||
The `parsesql` module implements a simple high-performance SQL parser.
|
||||
|
||||
* [parseutils](parseutils.html)
|
||||
This module contains helpers for parsing tokens, numbers, identifiers, etc.
|
||||
|
||||
* [parsexml](parsexml.html)
|
||||
The `parsexml` module implements a simple high performance XML/HTML parser.
|
||||
The only encoding that is supported is UTF-8. The parser has been designed
|
||||
to be somewhat error-correcting, so that even some "wild HTML" found on the
|
||||
web can be parsed with it.
|
||||
|
||||
* [pegs](pegs.html)
|
||||
This module contains procedures and operators for handling PEGs.
|
||||
|
||||
|
||||
Docutils
|
||||
--------
|
||||
@@ -415,6 +477,9 @@ XML Processing
|
||||
Generators
|
||||
----------
|
||||
|
||||
* [genasts](genasts.html)
|
||||
This module implements AST generation using captured variables for macros.
|
||||
|
||||
* [htmlgen](htmlgen.html)
|
||||
This module implements a simple XML and HTML code
|
||||
generator. Each commonly used HTML tag has a corresponding macro
|
||||
@@ -443,9 +508,24 @@ Hashing
|
||||
This module implements the SHA-1 checksum algorithm.
|
||||
|
||||
|
||||
Serialization
|
||||
-------------
|
||||
|
||||
* [jsonutils](jsonutils.html)
|
||||
This module implements a hookable (de)serialization for arbitrary types
|
||||
using JSON.
|
||||
|
||||
* [marshal](marshal.html)
|
||||
Contains procs for serialization and deserialization of arbitrary Nim
|
||||
data structures.
|
||||
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
* [assertions](assertions.html)
|
||||
This module implements assertion handling.
|
||||
|
||||
* [browsers](browsers.html)
|
||||
This module implements procs for opening URLs with the user's default
|
||||
browser.
|
||||
@@ -456,9 +536,15 @@ Miscellaneous
|
||||
* [coro](coro.html)
|
||||
This module implements experimental coroutines in Nim.
|
||||
|
||||
* [decls](decls.html)
|
||||
This module implements syntax sugar for some declarations.
|
||||
|
||||
* [enumerate](enumerate.html)
|
||||
This module implements `enumerate` syntactic sugar based on Nim's macro system.
|
||||
|
||||
* [importutils](importutils.html)
|
||||
Utilities related to import and symbol resolution.
|
||||
|
||||
* [logging](logging.html)
|
||||
This module implements a simple logger.
|
||||
|
||||
@@ -477,9 +563,12 @@ Miscellaneous
|
||||
* [with](with.html)
|
||||
This module implements the `with` macro for easy function chaining.
|
||||
|
||||
* [wrapnils](wrapnils.html)
|
||||
This module allows evaluating expressions safely against nil dereferences.
|
||||
|
||||
Modules for the JS backend
|
||||
--------------------------
|
||||
|
||||
Modules for the JavaScript backend
|
||||
----------------------------------
|
||||
|
||||
* [asyncjs](asyncjs.html)
|
||||
Types and macros for writing asynchronous procedures in JavaScript.
|
||||
@@ -497,9 +586,15 @@ Modules for the JS backend
|
||||
The wrapper of core JavaScript functions. For most purposes, you should be using
|
||||
the `math`, `json`, and `times` stdlib modules instead of this module.
|
||||
|
||||
* [jsfetch](jshttp.html)
|
||||
Wrapper for `fetch`.
|
||||
|
||||
* [jsffi](jsffi.html)
|
||||
Types and macros for easier interaction with JavaScript.
|
||||
|
||||
* [jsre](jsre.html)
|
||||
Regular Expressions for the JavaScript target.
|
||||
|
||||
|
||||
Impure libraries
|
||||
================
|
||||
@@ -511,18 +606,26 @@ Regular expressions
|
||||
This module contains procedures and operators for handling regular
|
||||
expressions. The current implementation uses PCRE.
|
||||
|
||||
* [nre](nre.html)
|
||||
|
||||
This module contains many help functions for handling regular expressions.
|
||||
The current implementation uses PCRE.
|
||||
|
||||
Database support
|
||||
----------------
|
||||
|
||||
* [db_postgres](db_postgres.html)
|
||||
A higher level PostgreSQL database wrapper. The same interface is implemented
|
||||
for other databases too.
|
||||
|
||||
* [db_mysql](db_mysql.html)
|
||||
A higher level MySQL database wrapper. The same interface is implemented
|
||||
for other databases too.
|
||||
|
||||
* [db_odbc](db_odbc.html)
|
||||
A higher level ODBC database wrapper. The same interface is implemented
|
||||
for other databases too.
|
||||
|
||||
* [db_postgres](db_postgres.html)
|
||||
A higher level PostgreSQL database wrapper. The same interface is implemented
|
||||
for other databases too.
|
||||
|
||||
* [db_sqlite](db_sqlite.html)
|
||||
A higher level SQLite database wrapper. The same interface is implemented
|
||||
for other databases too.
|
||||
@@ -570,14 +673,14 @@ Regular expressions
|
||||
Database support
|
||||
----------------
|
||||
|
||||
* [postgres](postgres.html)
|
||||
Contains a wrapper for the PostgreSQL API.
|
||||
* [mysql](mysql.html)
|
||||
Contains a wrapper for the mySQL API.
|
||||
* [sqlite3](sqlite3.html)
|
||||
Contains a wrapper for the SQLite 3 API.
|
||||
* [odbcsql](odbcsql.html)
|
||||
interface to the ODBC driver.
|
||||
* [postgres](postgres.html)
|
||||
Contains a wrapper for the PostgreSQL API.
|
||||
* [sqlite3](sqlite3.html)
|
||||
Contains a wrapper for the SQLite 3 API.
|
||||
|
||||
|
||||
Network Programming and Internet Protocols
|
||||
|
||||
@@ -8049,6 +8049,24 @@ used. To see if a value was provided, `defined(FooBar)` can be used.
|
||||
The syntax `-d:flag`:option: is actually just a shortcut for
|
||||
`-d:flag=true`:option:.
|
||||
|
||||
These pragmas also accept an optional string argument for qualified
|
||||
define names.
|
||||
|
||||
```nim
|
||||
const FooBar {.intdefine: "package.FooBar".}: int = 5
|
||||
echo FooBar
|
||||
```
|
||||
|
||||
```cmd
|
||||
nim c -d:package.FooBar=42 foobar.nim
|
||||
```
|
||||
|
||||
This helps disambiguate define names in different packages.
|
||||
|
||||
See also the [generic `define` pragma](manual_experimental.html#generic-define-pragma)
|
||||
for a version of these pragmas that detects the type of the define based on
|
||||
the constant value.
|
||||
|
||||
User-defined pragmas
|
||||
====================
|
||||
|
||||
@@ -8424,23 +8442,12 @@ This is only useful if the program is compiled as a dynamic library via the
|
||||
`--app:lib`:option: command-line option.
|
||||
|
||||
|
||||
|
||||
Threads
|
||||
=======
|
||||
|
||||
To enable thread support the `--threads:on`:option: command-line switch needs to
|
||||
be used. The [system module](system.html) module then contains several threading primitives.
|
||||
See the [channels](channels_builtin.html) modules
|
||||
for the low-level thread API. There are also high-level parallelism constructs
|
||||
available. See [spawn](manual_experimental.html#parallel-amp-spawn) for
|
||||
The `--threads:on`:option: command-line switch is enabled by default. The [typedthreads module](typedthreads.html) module then contains several threading primitives. See [spawn](manual_experimental.html#parallel-amp-spawn) for
|
||||
further details.
|
||||
|
||||
Nim's memory model for threads is quite different than that of other common
|
||||
programming languages (C, Pascal, Java): Each thread has its own (garbage
|
||||
collected) heap, and sharing of memory is restricted to global variables. This
|
||||
helps to prevent race conditions. GC efficiency is improved quite a lot,
|
||||
because the GC never has to stop other threads and see what they reference.
|
||||
|
||||
The only way to create a thread is via `spawn` or
|
||||
`createThread`. The invoked proc must not use `var` parameters nor must
|
||||
any of its parameters contain a `ref` or `closure` type. This enforces
|
||||
|
||||
@@ -65,6 +65,29 @@ However, a `void` type cannot be inferred in generic code:
|
||||
The `void` type is only valid for parameters and return types; other symbols
|
||||
cannot have the type `void`.
|
||||
|
||||
Generic `define` pragma
|
||||
=======================
|
||||
|
||||
Aside the [typed define pragmas for constants](manual.html#implementation-specific-pragmas-compileminustime-define-pragmas),
|
||||
there is a generic `{.define.}` pragma that interprets the value of the define
|
||||
based on the type of the constant value.
|
||||
|
||||
```nim
|
||||
const foo {.define: "package.foo".} = 123
|
||||
const bar {.define: "package.bar".} = false
|
||||
```
|
||||
|
||||
```cmd
|
||||
nim c -d:package.foo=456 -d:package.bar foobar.nim
|
||||
```
|
||||
|
||||
The following types are supported:
|
||||
|
||||
* `string` and `cstring`
|
||||
* Signed and unsigned integer types
|
||||
* `bool`
|
||||
* Enums
|
||||
|
||||
Top-down type inference
|
||||
=======================
|
||||
|
||||
@@ -519,8 +542,7 @@ Since version 1.4, a stricter definition of "side effect" is available.
|
||||
In addition to the existing rule that a side effect is calling a function
|
||||
with side effects, the following rule is also enforced:
|
||||
|
||||
Any mutation to an object does count as a side effect if that object is reachable
|
||||
via a parameter that is not declared as a `var` parameter.
|
||||
A store to the heap via a `ref` or `ptr` indirection is not allowed.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -540,17 +562,14 @@ For example:
|
||||
it = it.ri
|
||||
|
||||
func mut(n: Node) =
|
||||
let m = n # is the statement that connected the mutation to the parameter
|
||||
m.data = "yeah" # the mutation is here
|
||||
# Error: 'mut' can have side effects
|
||||
# an object reachable from 'n' is potentially mutated
|
||||
var it = n
|
||||
while it != nil:
|
||||
it.data = "yeah" # forbidden mutation
|
||||
it = it.ri
|
||||
|
||||
```
|
||||
|
||||
|
||||
The algorithm behind this analysis is described in
|
||||
the [view types algorithm][Algorithm].
|
||||
|
||||
|
||||
View types
|
||||
==========
|
||||
|
||||
@@ -1859,6 +1878,20 @@ before it is used. Thus the following is valid:
|
||||
|
||||
In this example every path does set `s` to a value before it is used.
|
||||
|
||||
```nim
|
||||
{.experimental: "strictDefs".}
|
||||
|
||||
proc test(cond: bool) =
|
||||
let s: seq[string]
|
||||
if cond:
|
||||
s = @["y"]
|
||||
else:
|
||||
s = @[]
|
||||
```
|
||||
|
||||
With `experimental: "strictDefs"`, `let` statements are allowed to not have an initial value, but every path should set `s` to a value before it is used.
|
||||
|
||||
|
||||
`out` parameters
|
||||
----------------
|
||||
|
||||
|
||||
@@ -74,7 +74,9 @@ local turn on/off
|
||||
---------------------
|
||||
|
||||
You can still turn off nil checking on function/module level by using a `{.strictNotNil: off.}` pragma.
|
||||
Note: test that/TODO for code/manual.
|
||||
|
||||
..
|
||||
Note: test that/TODO for code/manual.
|
||||
|
||||
nilability state
|
||||
-----------------
|
||||
@@ -101,7 +103,8 @@ Types are either nilable or non-nilable.
|
||||
When you pass a param or a default value, we use the type : for nilable types we return `MaybeNil`
|
||||
and for non-nilable `Safe`.
|
||||
|
||||
TODO: fix the manual here. (This is not great, as default values for non-nilables and nilables are usually actually `nil` , so we should think a bit more about this section.)
|
||||
..
|
||||
TODO: fix the manual here. (This is not great, as default values for non-nilables and nilables are usually actually `nil` , so we should think a bit more about this section.)
|
||||
|
||||
params rules
|
||||
------------
|
||||
@@ -236,11 +239,11 @@ e.g.
|
||||
left = nil # moving out
|
||||
```
|
||||
|
||||
..
|
||||
initialization of non nilable and nilable values
|
||||
-------------------------------------------------
|
||||
|
||||
initialization of non nilable and nilable values
|
||||
-------------------------------------------------
|
||||
|
||||
TODO
|
||||
TODO
|
||||
|
||||
warnings and errors
|
||||
---------------------
|
||||
|
||||
@@ -440,6 +440,7 @@ or setup a ``nim.cfg`` file like so:
|
||||
#nim.cfg
|
||||
--mm:orc
|
||||
--d:nimAllocPagesViaMalloc
|
||||
--define:nimInheritHandles
|
||||
--passC="-I$DEVKITPRO/libnx/include"
|
||||
--passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx"
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ At least the following standard library modules are available:
|
||||
* [htmlgen](htmlgen.html)
|
||||
* [httpcore](httpcore.html)
|
||||
* [lenientops](lenientops.html)
|
||||
* [mersenne](mersenne.html)
|
||||
* [options](options.html)
|
||||
* [parseutils](parseutils.html)
|
||||
* [punycode](punycode.html)
|
||||
@@ -89,7 +88,6 @@ At least the following standard library modules are available:
|
||||
* [uri](uri.html)
|
||||
* [std/editdistance](editdistance.html)
|
||||
* [std/wordwrap](wordwrap.html)
|
||||
* [std/sums](sums.html)
|
||||
* [parsecsv](parsecsv.html)
|
||||
* [parsecfg](parsecfg.html)
|
||||
* [parsesql](parsesql.html)
|
||||
|
||||
@@ -38,6 +38,14 @@ can also be used to include elements (and ranges of elements):
|
||||
# from '0' to '9'
|
||||
```
|
||||
|
||||
The module [`std/setutils`](https://nim-lang.org/docs/setutils.html) provides a way to initialize a set from an iterable:
|
||||
|
||||
```nim
|
||||
import std/setutils
|
||||
|
||||
let uniqueChars = myString.toSet
|
||||
```
|
||||
|
||||
These operations are supported by sets:
|
||||
|
||||
================== ========================================================
|
||||
|
||||
2
koch.nim
2
koch.nim
@@ -10,7 +10,7 @@
|
||||
#
|
||||
|
||||
const
|
||||
NimbleStableCommit = "d13f3b8ce288b4dc8c34c219a4e050aaeaf43fc9" # master
|
||||
NimbleStableCommit = "0777f33d1ddbd505b3aa7b714032125349323ceb" # master
|
||||
# examples of possible values: #head, #ea82b54, 1.2.3
|
||||
FusionStableHash = "#372ee4313827ef9f2ea388840f7d6b46c2b1b014"
|
||||
HeadHash = "#head"
|
||||
|
||||
@@ -1582,11 +1582,9 @@ proc customPragmaNode(n: NimNode): NimNode =
|
||||
|
||||
if n.kind in {nnkDotExpr, nnkCheckedFieldExpr}:
|
||||
let name = $(if n.kind == nnkCheckedFieldExpr: n[0][1] else: n[1])
|
||||
let typInst = getTypeInst(if n.kind == nnkCheckedFieldExpr or n[0].kind == nnkHiddenDeref: n[0][0] else: n[0])
|
||||
var typDef = getImpl(
|
||||
if typInst.kind in {nnkVarTy, nnkBracketExpr}: typInst[0]
|
||||
else: typInst
|
||||
)
|
||||
var typInst = getTypeInst(if n.kind == nnkCheckedFieldExpr or n[0].kind == nnkHiddenDeref: n[0][0] else: n[0])
|
||||
while typInst.kind in {nnkVarTy, nnkBracketExpr}: typInst = typInst[0]
|
||||
var typDef = getImpl(typInst)
|
||||
while typDef != nil:
|
||||
typDef.expectKind(nnkTypeDef)
|
||||
let typ = typDef[2].extractTypeImpl()
|
||||
|
||||
@@ -29,7 +29,7 @@ const
|
||||
CLONE_NEWPID* = 0x20000000'i32
|
||||
CLONE_NEWNET* = 0x40000000'i32
|
||||
CLONE_IO* = 0x80000000'i32
|
||||
CLONE_STOPPED* {.deprecated.} = 0x02000000'i32
|
||||
|
||||
|
||||
# fn should be of type proc (a2: pointer) {.cdecl.}
|
||||
proc clone*(fn: pointer; child_stack: pointer; flags: cint;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
## Exports [asyncmacro](asyncmacro.html) and [asyncfutures](asyncfutures.html) for native backends,
|
||||
## and [asyncjs](asyncjs.html) on the JS backend.
|
||||
|
||||
when defined(js):
|
||||
import asyncjs
|
||||
export asyncjs
|
||||
|
||||
@@ -1983,7 +1983,8 @@ proc send*(socket: AsyncFD, data: string,
|
||||
return retFuture
|
||||
|
||||
# -- Await Macro
|
||||
include asyncmacro
|
||||
import asyncmacro
|
||||
export asyncmacro
|
||||
|
||||
proc readAll*(future: FutureStream[string]): owned(Future[string]) {.async.} =
|
||||
## Returns a future that will complete when all the string data from the
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## `asyncdispatch` module depends on the `asyncmacro` module to work properly.
|
||||
## Implements the `async` and `multisync` macros for `asyncdispatch`.
|
||||
|
||||
import macros, strutils, asyncfutures
|
||||
|
||||
@@ -214,9 +214,18 @@ proc asyncSingleProc(prc: NimNode): NimNode =
|
||||
# don't do anything with forward bodies (empty)
|
||||
if procBody.kind != nnkEmpty:
|
||||
# fix #13899, defer should not escape its original scope
|
||||
procBody = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
|
||||
procBody.add(createFutureVarCompletions(futureVarIdents, nil))
|
||||
let blockStmt = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
|
||||
procBody = newStmtList()
|
||||
let resultIdent = ident"result"
|
||||
procBody.add quote do:
|
||||
template nimAsyncDispatchSetResult(x: `subRetType`) {.used.} =
|
||||
# If the proc has implicit return then this will get called
|
||||
`resultIdent` = x
|
||||
template nimAsyncDispatchSetResult(x: untyped) {.used.} =
|
||||
# If the proc doesn't have implicit return then this will get called
|
||||
x
|
||||
procBody.add newCall(ident"nimAsyncDispatchSetResult", blockStmt)
|
||||
procBody.add(createFutureVarCompletions(futureVarIdents, nil))
|
||||
procBody.insert(0): quote do:
|
||||
{.push warning[resultshadowed]: off.}
|
||||
when `subRetType` isnot void:
|
||||
@@ -277,8 +286,8 @@ macro async*(prc: untyped): untyped =
|
||||
proc splitParamType(paramType: NimNode, async: bool): NimNode =
|
||||
result = paramType
|
||||
if paramType.kind == nnkInfix and paramType[0].strVal in ["|", "or"]:
|
||||
let firstAsync = "async" in paramType[1].strVal.normalize
|
||||
let secondAsync = "async" in paramType[2].strVal.normalize
|
||||
let firstAsync = "async" in paramType[1].toStrLit().strVal.normalize
|
||||
let secondAsync = "async" in paramType[2].toStrLit().strVal.normalize
|
||||
|
||||
if firstAsync:
|
||||
result = paramType[if async: 1 else: 2]
|
||||
|
||||
@@ -38,16 +38,6 @@ proc slotsNeeded(count: Natural): int {.inline.} =
|
||||
# Make sure to synchronize with `mustRehash` above
|
||||
result = nextPowerOfTwo(count * 3 div 2 + 4)
|
||||
|
||||
proc rightSize*(count: Natural): int {.inline, deprecated: "Deprecated since 1.4.0".} =
|
||||
## It is not needed anymore because
|
||||
## picking the correct size is done internally.
|
||||
##
|
||||
## Returns the value of `initialSize` to support `count` items.
|
||||
##
|
||||
## If more items are expected to be added, simply add that
|
||||
## expected extra amount to the parameter before calling this.
|
||||
result = count
|
||||
|
||||
template rawGetKnownHCImpl() {.dirty.} =
|
||||
if t.dataLen == 0:
|
||||
return -1
|
||||
|
||||
@@ -347,7 +347,7 @@ proc missingOrExcl*[A](s: var HashSet[A], key: A): bool =
|
||||
proc pop*[A](s: var HashSet[A]): A =
|
||||
## Removes and returns an arbitrary element from the set `s`.
|
||||
##
|
||||
## Raises KeyError if the set `s` is empty.
|
||||
## Raises `KeyError` if the set `s` is empty.
|
||||
##
|
||||
## See also:
|
||||
## * `clear proc <#clear,HashSet[A]>`_
|
||||
@@ -425,7 +425,7 @@ proc intersection*[A](s1, s2: HashSet[A]): HashSet[A] =
|
||||
assert c == toHashSet(["b"])
|
||||
|
||||
result = initHashSet[A](max(min(s1.data.len, s2.data.len), 2))
|
||||
|
||||
|
||||
# iterate over the elements of the smaller set
|
||||
if s1.data.len < s2.data.len:
|
||||
for item in s1:
|
||||
@@ -433,7 +433,7 @@ proc intersection*[A](s1, s2: HashSet[A]): HashSet[A] =
|
||||
else:
|
||||
for item in s2:
|
||||
if item in s1: incl(result, item)
|
||||
|
||||
|
||||
|
||||
proc difference*[A](s1, s2: HashSet[A]): HashSet[A] =
|
||||
## Returns the difference of the sets `s1` and `s2`.
|
||||
|
||||
@@ -132,17 +132,13 @@ func toCaseInsensitive(headers: HttpHeaders, s: string): string {.inline.} =
|
||||
func newHttpHeaders*(titleCase=false): HttpHeaders =
|
||||
## Returns a new `HttpHeaders` object. if `titleCase` is set to true,
|
||||
## headers are passed to the server in title case (e.g. "Content-Length")
|
||||
new result
|
||||
result.table = newTable[string, seq[string]]()
|
||||
result.isTitleCase = titleCase
|
||||
result = HttpHeaders(table: newTable[string, seq[string]](), isTitleCase: titleCase)
|
||||
|
||||
func newHttpHeaders*(keyValuePairs:
|
||||
openArray[tuple[key: string, val: string]], titleCase=false): HttpHeaders =
|
||||
## Returns a new `HttpHeaders` object from an array. if `titleCase` is set to true,
|
||||
## headers are passed to the server in title case (e.g. "Content-Length")
|
||||
new result
|
||||
result.table = newTable[string, seq[string]]()
|
||||
result.isTitleCase = titleCase
|
||||
result = HttpHeaders(table: newTable[string, seq[string]](), isTitleCase: titleCase)
|
||||
|
||||
for pair in keyValuePairs:
|
||||
let key = result.toCaseInsensitive(pair.key)
|
||||
|
||||
@@ -47,7 +47,6 @@ runnableExamples:
|
||||
## * `fenv module <fenv.html>`_ for handling of floating-point rounding
|
||||
## and exceptions (overflow, zero-divide, etc.)
|
||||
## * `random module <random.html>`_ for a fast and tiny random number generator
|
||||
## * `mersenne module <mersenne.html>`_ for the Mersenne Twister random number generator
|
||||
## * `stats module <stats.html>`_ for statistical analysis
|
||||
## * `strformat module <strformat.html>`_ for formatting floats for printing
|
||||
## * `system module <system.html>`_ for some very basic and trivial math operators
|
||||
|
||||
@@ -168,8 +168,9 @@ func charSet*(s: set[char]): Peg {.rtl, extern: "npegs$1".} =
|
||||
## constructs a PEG from a character set `s`
|
||||
assert '\0' notin s
|
||||
result = Peg(kind: pkCharChoice)
|
||||
new(result.charChoice)
|
||||
result.charChoice[] = s
|
||||
{.cast(noSideEffect).}:
|
||||
new(result.charChoice)
|
||||
result.charChoice[] = s
|
||||
|
||||
func len(a: Peg): int {.inline.} = return a.sons.len
|
||||
func add(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
|
||||
@@ -1823,9 +1824,7 @@ type
|
||||
skip: Peg
|
||||
|
||||
func pegError(p: PegParser, msg: string, line = -1, col = -1) =
|
||||
var e: ref EInvalidPeg
|
||||
new(e)
|
||||
e.msg = errorStr(p, msg, line, col)
|
||||
var e = (ref EInvalidPeg)(msg: errorStr(p, msg, line, col))
|
||||
raise e
|
||||
|
||||
func getTok(p: var PegParser) =
|
||||
@@ -1909,7 +1908,8 @@ func primary(p: var PegParser): Peg =
|
||||
getTok(p)
|
||||
elif not arrowIsNextTok(p):
|
||||
var nt = getNonTerminal(p, p.tok.literal)
|
||||
incl(nt.flags, ntUsed)
|
||||
{.cast(noSideEffect).}:
|
||||
incl(nt.flags, ntUsed)
|
||||
result = nonterminal(nt).token(p)
|
||||
getTok(p)
|
||||
else:
|
||||
@@ -2002,12 +2002,14 @@ func parseRule(p: var PegParser): NonTerminal =
|
||||
result = getNonTerminal(p, p.tok.literal)
|
||||
if ntDeclared in result.flags:
|
||||
pegError(p, "attempt to redefine: " & result.name)
|
||||
result.line = getLine(p)
|
||||
result.col = getColumn(p)
|
||||
{.cast(noSideEffect).}:
|
||||
result.line = getLine(p)
|
||||
result.col = getColumn(p)
|
||||
getTok(p)
|
||||
eat(p, tkArrow)
|
||||
result.rule = parseExpr(p)
|
||||
incl(result.flags, ntDeclared) # NOW inlining may be attempted
|
||||
{.cast(noSideEffect).}:
|
||||
result.rule = parseExpr(p)
|
||||
incl(result.flags, ntDeclared) # NOW inlining may be attempted
|
||||
else:
|
||||
pegError(p, "rule expected, but found: " & p.tok.literal)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ when defined(nimdoc) and isMainModule:
|
||||
runnableExamples:
|
||||
include std/prelude
|
||||
# same as:
|
||||
# import std/[os, strutils, times, parseutils, hashes, tables, sets, sequtils, parseopt]
|
||||
# import std/[os, strutils, times, parseutils, hashes, tables, sets, sequtils, parseopt, strformat]
|
||||
let x = 1
|
||||
assert "foo $# $#" % [$x, "bar"] == "foo 1 bar"
|
||||
assert toSeq(1..3) == @[1, 2, 3]
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2016 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Implements a representation of Unicode with the limited
|
||||
## ASCII character subset.
|
||||
|
||||
import strutils
|
||||
import unicode
|
||||
|
||||
# issue #3045
|
||||
|
||||
const
|
||||
Base = 36
|
||||
TMin = 1
|
||||
TMax = 26
|
||||
Skew = 38
|
||||
Damp = 700
|
||||
InitialBias = 72
|
||||
InitialN = 128
|
||||
Delimiter = '-'
|
||||
|
||||
type
|
||||
PunyError* = object of ValueError
|
||||
|
||||
func decodeDigit(x: char): int {.raises: [PunyError].} =
|
||||
if '0' <= x and x <= '9':
|
||||
result = ord(x) - (ord('0') - 26)
|
||||
elif 'A' <= x and x <= 'Z':
|
||||
result = ord(x) - ord('A')
|
||||
elif 'a' <= x and x <= 'z':
|
||||
result = ord(x) - ord('a')
|
||||
else:
|
||||
raise newException(PunyError, "Bad input")
|
||||
|
||||
func encodeDigit(digit: int): Rune {.raises: [PunyError].} =
|
||||
if 0 <= digit and digit < 26:
|
||||
result = Rune(digit + ord('a'))
|
||||
elif 26 <= digit and digit < 36:
|
||||
result = Rune(digit + (ord('0') - 26))
|
||||
else:
|
||||
raise newException(PunyError, "internal error in punycode encoding")
|
||||
|
||||
func isBasic(c: char): bool = ord(c) < 0x80
|
||||
func isBasic(r: Rune): bool = int(r) < 0x80
|
||||
|
||||
func adapt(delta, numPoints: int, first: bool): int =
|
||||
var d = if first: delta div Damp else: delta div 2
|
||||
d += d div numPoints
|
||||
var k = 0
|
||||
while d > ((Base-TMin)*TMax) div 2:
|
||||
d = d div (Base - TMin)
|
||||
k += Base
|
||||
result = k + (Base - TMin + 1) * d div (d + Skew)
|
||||
|
||||
func encode*(prefix, s: string): string {.raises: [PunyError].} =
|
||||
## Encode a string that may contain Unicode.
|
||||
## Prepend `prefix` to the result
|
||||
result = prefix
|
||||
var (d, n, bias) = (0, InitialN, InitialBias)
|
||||
var (b, remaining) = (0, 0)
|
||||
for r in s.runes:
|
||||
if r.isBasic:
|
||||
# basic Ascii character
|
||||
inc b
|
||||
result.add($r)
|
||||
else:
|
||||
# special character
|
||||
inc remaining
|
||||
|
||||
var h = b
|
||||
if b > 0:
|
||||
result.add(Delimiter) # we have some Ascii chars
|
||||
while remaining != 0:
|
||||
var m: int = high(int32)
|
||||
for r in s.runes:
|
||||
if m > int(r) and int(r) >= n:
|
||||
m = int(r)
|
||||
d += (m - n) * (h + 1)
|
||||
if d < 0:
|
||||
raise newException(PunyError, "invalid label " & s)
|
||||
n = m
|
||||
for r in s.runes:
|
||||
if int(r) < n:
|
||||
inc d
|
||||
if d < 0:
|
||||
raise newException(PunyError, "invalid label " & s)
|
||||
continue
|
||||
if int(r) > n:
|
||||
continue
|
||||
var q = d
|
||||
var k = Base
|
||||
while true:
|
||||
var t = k - bias
|
||||
if t < TMin:
|
||||
t = TMin
|
||||
elif t > TMax:
|
||||
t = TMax
|
||||
if q < t:
|
||||
break
|
||||
result.add($encodeDigit(t + (q - t) mod (Base - t)))
|
||||
q = (q - t) div (Base - t)
|
||||
k += Base
|
||||
result.add($encodeDigit(q))
|
||||
bias = adapt(d, h + 1, h == b)
|
||||
d = 0
|
||||
inc h
|
||||
dec remaining
|
||||
inc d
|
||||
inc n
|
||||
|
||||
func encode*(s: string): string {.raises: [PunyError].} =
|
||||
## Encode a string that may contain Unicode. Prefix is empty.
|
||||
result = encode("", s)
|
||||
|
||||
func decode*(encoded: string): string {.raises: [PunyError].} =
|
||||
## Decode a Punycode-encoded string
|
||||
var
|
||||
n = InitialN
|
||||
i = 0
|
||||
bias = InitialBias
|
||||
var d = rfind(encoded, Delimiter)
|
||||
var output: seq[Rune]
|
||||
|
||||
if d > 0:
|
||||
# found Delimiter
|
||||
for j in 0..<d:
|
||||
var c = encoded[j] # char
|
||||
if not c.isBasic:
|
||||
raise newException(PunyError, "Encoded contains a non-basic char")
|
||||
output.add(Rune(c)) # add the character
|
||||
inc d
|
||||
else:
|
||||
d = 0 # set to first index
|
||||
|
||||
while (d < len(encoded)):
|
||||
var oldi = i
|
||||
var w = 1
|
||||
var k = Base
|
||||
while true:
|
||||
if d == len(encoded):
|
||||
raise newException(PunyError, "Bad input: " & encoded)
|
||||
var c = encoded[d]; inc d
|
||||
var digit = int(decodeDigit(c))
|
||||
if digit > (high(int32) - i) div w:
|
||||
raise newException(PunyError, "Too large a value: " & $digit)
|
||||
i += digit * w
|
||||
var t: int
|
||||
if k <= bias:
|
||||
t = TMin
|
||||
elif k >= bias + TMax:
|
||||
t = TMax
|
||||
else:
|
||||
t = k - bias
|
||||
if digit < t:
|
||||
break
|
||||
w *= Base - t
|
||||
k += Base
|
||||
bias = adapt(i - oldi, len(output) + 1, oldi == 0)
|
||||
|
||||
if i div (len(output) + 1) > high(int32) - n:
|
||||
raise newException(PunyError, "Value too large")
|
||||
|
||||
n += i div (len(output) + 1)
|
||||
i = i mod (len(output) + 1)
|
||||
insert(output, Rune(n), i)
|
||||
inc i
|
||||
|
||||
result = $output
|
||||
|
||||
runnableExamples:
|
||||
static:
|
||||
block:
|
||||
doAssert encode("") == ""
|
||||
doAssert encode("a") == "a-"
|
||||
doAssert encode("A") == "A-"
|
||||
doAssert encode("3") == "3-"
|
||||
doAssert encode("-") == "--"
|
||||
doAssert encode("--") == "---"
|
||||
doAssert encode("abc") == "abc-"
|
||||
doAssert encode("London") == "London-"
|
||||
doAssert encode("Lloyd-Atkinson") == "Lloyd-Atkinson-"
|
||||
doAssert encode("This has spaces") == "This has spaces-"
|
||||
doAssert encode("ü") == "tda"
|
||||
doAssert encode("München") == "Mnchen-3ya"
|
||||
doAssert encode("Mnchen-3ya") == "Mnchen-3ya-"
|
||||
doAssert encode("München-Ost") == "Mnchen-Ost-9db"
|
||||
doAssert encode("Bahnhof München-Ost") == "Bahnhof Mnchen-Ost-u6b"
|
||||
block:
|
||||
doAssert decode("") == ""
|
||||
doAssert decode("a-") == "a"
|
||||
doAssert decode("A-") == "A"
|
||||
doAssert decode("3-") == "3"
|
||||
doAssert decode("--") == "-"
|
||||
doAssert decode("---") == "--"
|
||||
doAssert decode("abc-") == "abc"
|
||||
doAssert decode("London-") == "London"
|
||||
doAssert decode("Lloyd-Atkinson-") == "Lloyd-Atkinson"
|
||||
doAssert decode("This has spaces-") == "This has spaces"
|
||||
doAssert decode("tda") == "ü"
|
||||
doAssert decode("Mnchen-3ya") == "München"
|
||||
doAssert decode("Mnchen-3ya-") == "Mnchen-3ya"
|
||||
doAssert decode("Mnchen-Ost-9db") == "München-Ost"
|
||||
doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost"
|
||||
@@ -66,7 +66,6 @@ runnableExamples:
|
||||
## See also
|
||||
## ========
|
||||
## * `std/sysrand module <sysrand.html>`_ for a cryptographically secure pseudorandom number generator
|
||||
## * `mersenne module <mersenne.html>`_ for the Mersenne Twister random number generator
|
||||
## * `math module <math.html>`_ for basic math routines
|
||||
## * `stats module <stats.html>`_ for statistical analysis
|
||||
## * `list of cryptographic and hashing modules <lib.html#pure-libraries-hashing>`_
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## :Authors: Zahary Karadjov
|
||||
##
|
||||
## This module provides utilities for reserving a portions of the
|
||||
## This module provides utilities for reserving portions of the
|
||||
## address space of a program without consuming physical memory.
|
||||
## It can be used to implement a dynamically resizable buffer that
|
||||
## is guaranteed to remain in the same memory location. The buffer
|
||||
|
||||
@@ -261,10 +261,7 @@ proc newStringTable*(mode: StringTableMode): owned(StringTableRef) {.
|
||||
## See also:
|
||||
## * `newStringTable(keyValuePairs) proc
|
||||
## <#newStringTable,varargs[tuple[string,string]],StringTableMode>`_
|
||||
new(result)
|
||||
result.mode = mode
|
||||
result.counter = 0
|
||||
newSeq(result.data, startSize)
|
||||
result = StringTableRef(mode: mode, counter: 0, data: newSeq[KeyValuePair](startSize))
|
||||
|
||||
proc newStringTable*(keyValuePairs: varargs[string],
|
||||
mode: StringTableMode): owned(StringTableRef) {.
|
||||
|
||||
@@ -624,7 +624,7 @@ iterator splitLines*(s: string, keepEol = false): string =
|
||||
##
|
||||
## Every `character literal <manual.html#lexical-analysis-character-literals>`_
|
||||
## newline combination (CR, LF, CR-LF) is supported. The result strings
|
||||
## contain no trailing end of line characters unless parameter `keepEol`
|
||||
## contain no trailing end of line characters unless the parameter `keepEol`
|
||||
## is set to `true`.
|
||||
##
|
||||
## Example:
|
||||
|
||||
@@ -953,27 +953,33 @@ proc toWinTime*(t: Time): int64 =
|
||||
## since `1601-01-01T00:00:00Z`).
|
||||
result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100
|
||||
|
||||
proc getTimeImpl(typ: typedesc[Time]): Time =
|
||||
discard "implemented in the vm"
|
||||
|
||||
proc getTime*(): Time {.tags: [TimeEffect], benign.} =
|
||||
## Gets the current time as a `Time` with up to nanosecond resolution.
|
||||
when defined(js):
|
||||
let millis = newDate().getTime()
|
||||
let seconds = convert(Milliseconds, Seconds, millis)
|
||||
let nanos = convert(Milliseconds, Nanoseconds,
|
||||
millis mod convert(Seconds, Milliseconds, 1).int)
|
||||
result = initTime(seconds, nanos)
|
||||
elif defined(macosx):
|
||||
var a {.noinit.}: Timeval
|
||||
gettimeofday(a)
|
||||
result = initTime(a.tv_sec.int64,
|
||||
convert(Microseconds, Nanoseconds, a.tv_usec.int))
|
||||
elif defined(posix):
|
||||
var ts {.noinit.}: Timespec
|
||||
discard clock_gettime(CLOCK_REALTIME, ts)
|
||||
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
|
||||
elif defined(windows):
|
||||
var f {.noinit.}: FILETIME
|
||||
getSystemTimeAsFileTime(f)
|
||||
result = fromWinTime(rdFileTime(f))
|
||||
when nimvm:
|
||||
result = getTimeImpl(Time)
|
||||
else:
|
||||
when defined(js):
|
||||
let millis = newDate().getTime()
|
||||
let seconds = convert(Milliseconds, Seconds, millis)
|
||||
let nanos = convert(Milliseconds, Nanoseconds,
|
||||
millis mod convert(Seconds, Milliseconds, 1).int)
|
||||
result = initTime(seconds, nanos)
|
||||
elif defined(macosx):
|
||||
var a {.noinit.}: Timeval
|
||||
gettimeofday(a)
|
||||
result = initTime(a.tv_sec.int64,
|
||||
convert(Microseconds, Nanoseconds, a.tv_usec.int))
|
||||
elif defined(posix):
|
||||
var ts {.noinit.}: Timespec
|
||||
discard clock_gettime(CLOCK_REALTIME, ts)
|
||||
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
|
||||
elif defined(windows):
|
||||
var f {.noinit.}: FILETIME
|
||||
getSystemTimeAsFileTime(f)
|
||||
result = fromWinTime(rdFileTime(f))
|
||||
|
||||
proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
|
||||
## Computes the duration between two points in time.
|
||||
|
||||
@@ -433,8 +433,6 @@ proc matchFilter(suiteName, testName, filter: string): bool =
|
||||
return glob(suiteName, suiteAndTestFilters[0]) and
|
||||
glob(testName, suiteAndTestFilters[1])
|
||||
|
||||
when defined(testing): export matchFilter
|
||||
|
||||
proc shouldRun(currentSuiteName, testName: string): bool =
|
||||
## Check if a test should be run by matching suiteName and testName against
|
||||
## test filters.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements helpers for determining special directories used by apps.
|
||||
|
||||
from std/private/osappdirs import nil
|
||||
import std/paths
|
||||
import std/envvars
|
||||
|
||||
@@ -34,7 +34,7 @@ elif defined(windows):
|
||||
elif defined(posix):
|
||||
import posix
|
||||
else:
|
||||
{.error: "cmdparam module not ported to your operating system!".}
|
||||
{.error: "The cmdline module has not been implemented for the target platform.".}
|
||||
|
||||
|
||||
# Needed by windows in order to obtain the command line for targets
|
||||
@@ -310,4 +310,4 @@ when declared(paramCount) or defined(nimdoc):
|
||||
else:
|
||||
proc commandLineParams*(): seq[string] {.error:
|
||||
"commandLineParams() unsupported by dynamic libraries".} =
|
||||
discard
|
||||
discard
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# see `semLowerLetVarCustomPragma` for compiler support that enables these
|
||||
# lowerings
|
||||
## This module implements syntax sugar for some declarations.
|
||||
|
||||
import macros
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements directory handling.
|
||||
|
||||
from paths import Path, ReadDirEffect, WriteDirEffect
|
||||
|
||||
from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
|
||||
|
||||
## The `std/envvars` module implements environment variables handling.
|
||||
## The `std/envvars` module implements environment variable handling.
|
||||
import std/oserrors
|
||||
|
||||
type
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module allows adding hooks to program exit.
|
||||
|
||||
import locks
|
||||
|
||||
type
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements file handling.
|
||||
|
||||
from paths import Path, ReadDirEffect, WriteDirEffect
|
||||
|
||||
from std/private/osfiles import fileExists, removeFile,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements formatting floats as strings.
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
else:
|
||||
@@ -28,11 +30,11 @@ proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat)
|
||||
##
|
||||
## returns the amount of bytes written to `buf` not counting the
|
||||
## terminating '\0' character.
|
||||
result = toChars(buf, value, forceTrailingDotZero=true)
|
||||
result = toChars(buf, value, forceTrailingDotZero=true).int
|
||||
buf[result] = '\0'
|
||||
|
||||
proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int =
|
||||
result = float32ToChars(buf, value, forceTrailingDotZero=true)
|
||||
result = float32ToChars(buf, value, forceTrailingDotZero=true).int
|
||||
buf[result] = '\0'
|
||||
|
||||
proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
|
||||
@@ -49,7 +51,7 @@ proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat):
|
||||
##
|
||||
## returns the amount of bytes written to `buf` not counting the
|
||||
## terminating '\0' character.
|
||||
var n: int = c_sprintf(cast[cstring](addr buf), "%.16g", value)
|
||||
var n = c_sprintf(cast[cstring](addr buf), "%.16g", value).int
|
||||
var hasDot = false
|
||||
for i in 0..n-1:
|
||||
if buf[i] == ',':
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements AST generation using captured variables for macros.
|
||||
|
||||
import macros
|
||||
|
||||
type GenAstOpt* = enum
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
when not defined(js):
|
||||
{.fatal: "Module jsfetch is designed to be used with the JavaScript backend.".}
|
||||
|
||||
import std/[asyncjs, jsheaders, jsformdata]
|
||||
import std/[asyncjs, jsformdata, jsheaders]
|
||||
export jsformdata, jsheaders
|
||||
from std/httpcore import HttpMethod
|
||||
from std/jsffi import JsObject
|
||||
|
||||
@@ -116,7 +117,7 @@ func `$`*(self: Request | Response | FetchOptions): string = $toCstring(self)
|
||||
|
||||
|
||||
runnableExamples("-r:off"):
|
||||
import std/[asyncjs, jsconsole, jsheaders, jsformdata]
|
||||
import std/[asyncjs, jsconsole, jsformdata, jsheaders]
|
||||
from std/httpcore import HttpMethod
|
||||
from std/jsffi import JsObject
|
||||
from std/sugar import `=>`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
##[
|
||||
This module implements a hookable (de)serialization for arbitrary types.
|
||||
This module implements a hookable (de)serialization for arbitrary types using JSON.
|
||||
Design goal: avoid importing modules where a custom serialization is needed;
|
||||
see strtabs.fromJsonHook,toJsonHook for an example.
|
||||
]##
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements a generic `$` operator to convert objects to strings.
|
||||
|
||||
import std/private/miscdollars
|
||||
|
||||
proc `$`*[T: object](x: T): string =
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements path handling.
|
||||
|
||||
import std/private/osseps
|
||||
export osseps
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.}
|
||||
#copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))
|
||||
|
||||
proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
|
||||
return trailingZeros100[digits]
|
||||
return trailingZeros100[digits.int8]
|
||||
|
||||
when defined(js):
|
||||
proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".}
|
||||
@@ -63,14 +63,14 @@ func addIntImpl(result: var string, x: uint64) {.inline.} =
|
||||
while num >= nbatch:
|
||||
let originNum = num
|
||||
num = num div nbatch
|
||||
let index = (originNum - num * nbatch) shl 1
|
||||
let index = int16((originNum - num * nbatch) shl 1)
|
||||
tmp[next] = digits100[index + 1]
|
||||
tmp[next - 1] = digits100[index]
|
||||
dec(next, 2)
|
||||
|
||||
# process last 1-2 digits
|
||||
if num < 10:
|
||||
tmp[next] = chr(ord('0') + num)
|
||||
tmp[next] = chr(ord('0') + num.uint8)
|
||||
else:
|
||||
let index = num * 2
|
||||
tmp[next] = digits100[index + 1]
|
||||
|
||||
@@ -1146,7 +1146,7 @@ proc printDecimalDigitsBackwards*(buf: var openArray[char]; pos: int; output64:
|
||||
buf[pos] = chr(ord('0') + q)
|
||||
return tz
|
||||
|
||||
proc decimalLength*(v: uint64): int32 {.inline.} =
|
||||
proc decimalLength*(v: uint64): int {.inline.} =
|
||||
dragonbox_Assert(v >= 1)
|
||||
dragonbox_Assert(v <= 99999999999999999'u64)
|
||||
if cast[uint32](v shr 32) != 0:
|
||||
@@ -1166,48 +1166,48 @@ proc decimalLength*(v: uint64): int32 {.inline.} =
|
||||
return 11
|
||||
return 10
|
||||
let v32: uint32 = cast[uint32](v)
|
||||
if v32 >= 1000000000'u:
|
||||
if v32 >= 1000000000'u32:
|
||||
return 10
|
||||
if v32 >= 100000000'u:
|
||||
if v32 >= 100000000'u32:
|
||||
return 9
|
||||
if v32 >= 10000000'u:
|
||||
if v32 >= 10000000'u32:
|
||||
return 8
|
||||
if v32 >= 1000000'u:
|
||||
if v32 >= 1000000'u32:
|
||||
return 7
|
||||
if v32 >= 100000'u:
|
||||
if v32 >= 100000'u32:
|
||||
return 6
|
||||
if v32 >= 10000'u:
|
||||
if v32 >= 10000'u32:
|
||||
return 5
|
||||
if v32 >= 1000'u:
|
||||
if v32 >= 1000'u32:
|
||||
return 4
|
||||
if v32 >= 100'u:
|
||||
if v32 >= 100'u32:
|
||||
return 3
|
||||
if v32 >= 10'u:
|
||||
if v32 >= 10'u32:
|
||||
return 2
|
||||
return 1
|
||||
|
||||
proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decimalExponent: int32;
|
||||
proc formatDigits*[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint64; decimalExponent: int;
|
||||
forceTrailingDotZero = false): int {.inline.} =
|
||||
const
|
||||
minFixedDecimalPoint: int32 = -6
|
||||
minFixedDecimalPoint = -6
|
||||
const
|
||||
maxFixedDecimalPoint: int32 = 17
|
||||
var pos = pos
|
||||
maxFixedDecimalPoint = 17
|
||||
var pos:int = pos.int
|
||||
assert(minFixedDecimalPoint <= -1, "internal error")
|
||||
assert(maxFixedDecimalPoint >= 17, "internal error")
|
||||
dragonbox_Assert(digits >= 1)
|
||||
dragonbox_Assert(digits <= 99999999999999999'u64)
|
||||
dragonbox_Assert(decimalExponent >= -999)
|
||||
dragonbox_Assert(decimalExponent <= 999)
|
||||
var numDigits: int32 = decimalLength(digits)
|
||||
let decimalPoint: int32 = numDigits + decimalExponent
|
||||
var numDigits = decimalLength(digits)
|
||||
let decimalPoint = numDigits + decimalExponent
|
||||
let useFixed: bool = minFixedDecimalPoint <= decimalPoint and
|
||||
decimalPoint <= maxFixedDecimalPoint
|
||||
## Prepare the buffer.
|
||||
for i in 0..<32: buffer[pos+i] = '0'
|
||||
assert(minFixedDecimalPoint >= -30, "internal error")
|
||||
assert(maxFixedDecimalPoint <= 32, "internal error")
|
||||
var decimalDigitsPosition: int32
|
||||
var decimalDigitsPosition: int
|
||||
if useFixed:
|
||||
if decimalPoint <= 0:
|
||||
## 0.[000]digits
|
||||
@@ -1258,7 +1258,7 @@ proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decima
|
||||
## d.igitsE+123
|
||||
buffer[pos+1] = '.'
|
||||
pos = digitsEnd
|
||||
let scientificExponent: int32 = decimalPoint - 1
|
||||
let scientificExponent: int = decimalPoint - 1
|
||||
## SF_ASSERT(scientific_exponent != 0);
|
||||
buffer[pos] = 'e'
|
||||
buffer[pos+1] = if scientificExponent < 0: '-' else: '+'
|
||||
@@ -1291,7 +1291,7 @@ proc toChars*(buffer: var openArray[char]; v: float; forceTrailingDotZero = fals
|
||||
if exponent != 0 or significand != 0:
|
||||
## != 0
|
||||
let dec = toDecimal64(significand, exponent)
|
||||
return formatDigits(buffer, pos, dec.significand, dec.exponent,
|
||||
return formatDigits(buffer, pos, dec.significand, dec.exponent.int,
|
||||
forceTrailingDotZero)
|
||||
else:
|
||||
buffer[pos] = '0'
|
||||
|
||||
@@ -244,7 +244,7 @@ proc toDecimal32(ieeeSignificand: uint32; ieeeExponent: uint32): FloatingDecimal
|
||||
## ToChars
|
||||
## ==================================================================================================
|
||||
|
||||
proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uint32): int32 {.inline.} =
|
||||
proc printDecimalDigitsBackwards[T: Ordinal](buf: var openArray[char]; pos: T; output: uint32): int32 {.inline.} =
|
||||
var output = output
|
||||
var pos = pos
|
||||
var tz: int32 = 0
|
||||
@@ -300,7 +300,7 @@ proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uin
|
||||
buf[pos] = chr(uint32('0') + q)
|
||||
return tz
|
||||
|
||||
proc decimalLength(v: uint32): int32 {.inline.} =
|
||||
proc decimalLength(v: uint32): int {.inline.} =
|
||||
sf_Assert(v >= 1)
|
||||
sf_Assert(v <= 999999999'u)
|
||||
if v >= 100000000'u:
|
||||
@@ -321,7 +321,7 @@ proc decimalLength(v: uint32): int32 {.inline.} =
|
||||
return 2
|
||||
return 1
|
||||
|
||||
proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimalExponent: int32;
|
||||
proc formatDigits[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint32; decimalExponent: int;
|
||||
forceTrailingDotZero: bool = false): int {.inline.} =
|
||||
const
|
||||
minFixedDecimalPoint: int32 = -4
|
||||
@@ -333,8 +333,8 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal
|
||||
sf_Assert(digits <= 999999999'u)
|
||||
sf_Assert(decimalExponent >= -99)
|
||||
sf_Assert(decimalExponent <= 99)
|
||||
var numDigits: int32 = decimalLength(digits)
|
||||
let decimalPoint: int32 = numDigits + decimalExponent
|
||||
var numDigits = decimalLength(digits)
|
||||
let decimalPoint = numDigits + decimalExponent
|
||||
let useFixed: bool = minFixedDecimalPoint <= decimalPoint and
|
||||
decimalPoint <= maxFixedDecimalPoint
|
||||
## Prepare the buffer.
|
||||
@@ -342,7 +342,7 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal
|
||||
for i in 0..<32: buffer[pos+i] = '0'
|
||||
assert(minFixedDecimalPoint >= -30, "internal error")
|
||||
assert(maxFixedDecimalPoint <= 32, "internal error")
|
||||
var decimalDigitsPosition: int32
|
||||
var decimalDigitsPosition: int
|
||||
if useFixed:
|
||||
if decimalPoint <= 0:
|
||||
## 0.[000]digits
|
||||
@@ -386,7 +386,7 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal
|
||||
## d.igitsE+123
|
||||
buffer[pos+1] = '.'
|
||||
pos = digitsEnd
|
||||
let scientificExponent: int32 = decimalPoint - 1
|
||||
let scientificExponent = decimalPoint - 1
|
||||
## SF_ASSERT(scientific_exponent != 0);
|
||||
buffer[pos] = 'e'
|
||||
buffer[pos+1] = if scientificExponent < 0: '-' else: '+'
|
||||
@@ -412,7 +412,7 @@ proc float32ToChars*(buffer: var openArray[char]; v: float32; forceTrailingDotZe
|
||||
if exponent != 0 or significand != 0:
|
||||
## != 0
|
||||
let dec: auto = toDecimal32(significand, exponent)
|
||||
return formatDigits(buffer, pos, dec.digits, dec.exponent, forceTrailingDotZero)
|
||||
return formatDigits(buffer, pos, dec.digits, dec.exponent.int, forceTrailingDotZero)
|
||||
else:
|
||||
buffer[pos] = '0'
|
||||
buffer[pos+1] = '.'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## This module implements symlink (symbolic link) handling.
|
||||
|
||||
from paths import Path, ReadDirEffect
|
||||
|
||||
from std/private/ossymlinks import symlinkExists, createSymlink, expandSymlink
|
||||
|
||||
@@ -376,7 +376,7 @@ when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(w
|
||||
flags = if inheritable: flags and not FD_CLOEXEC else: flags or FD_CLOEXEC
|
||||
result = c_fcntl(f, F_SETFD, flags) != -1
|
||||
else:
|
||||
result = setHandleInformation(cast[IoHandle](f), HANDLE_FLAG_INHERIT,
|
||||
result = setHandleInformation(cast[IoHandle](getOsfhandle(f)), HANDLE_FLAG_INHERIT,
|
||||
inheritable.WinDWORD) != 0
|
||||
|
||||
proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
|
||||
@@ -391,7 +391,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
|
||||
importc: "memchr", header: "<string.h>".}
|
||||
|
||||
when defined(windows) and not defined(useWinAnsi):
|
||||
proc readConsole(hConsoleInput: FileHandle, lpBuffer: pointer,
|
||||
proc readConsole(hConsoleInput: IoHandle, lpBuffer: pointer,
|
||||
nNumberOfCharsToRead: int32,
|
||||
lpNumberOfCharsRead: ptr int32,
|
||||
pInputControl: pointer): int32 {.
|
||||
@@ -423,7 +423,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
|
||||
const numberOfCharsToRead = 2048
|
||||
var numberOfCharsRead = 0'i32
|
||||
var buffer = newWideCString("", numberOfCharsToRead)
|
||||
if readConsole(getOsFileHandle(f), addr(buffer[0]),
|
||||
if readConsole(cast[IoHandle](getOsfhandle(getFileHandle(f))), addr(buffer[0]),
|
||||
numberOfCharsToRead, addr(numberOfCharsRead), nil) == 0:
|
||||
var error = getLastError()
|
||||
var errorMsg: string
|
||||
@@ -573,7 +573,7 @@ proc readAllFile(file: File, len: int64): string =
|
||||
result = newString(len)
|
||||
let bytes = readBuffer(file, addr(result[0]), len)
|
||||
if endOfFile(file):
|
||||
if bytes < len:
|
||||
if bytes.int64 < len:
|
||||
result.setLen(bytes)
|
||||
else:
|
||||
# We read all the bytes but did not reach the EOF
|
||||
@@ -711,13 +711,13 @@ proc open*(f: var File, filename: string,
|
||||
return false
|
||||
when not defined(nimInheritHandles) and declared(setInheritable) and
|
||||
NoInheritFlag.len == 0:
|
||||
if not setInheritable(getOsFileHandle(f2), false):
|
||||
if not setInheritable(getFileHandle(f2), false):
|
||||
close(f2)
|
||||
return false
|
||||
|
||||
result = true
|
||||
f = cast[File](p)
|
||||
if bufSize > 0 and bufSize <= high(cint).int:
|
||||
if bufSize > 0 and bufSize.uint <= high(uint):
|
||||
discard c_setvbuf(f, nil, IOFBF, cast[csize_t](bufSize))
|
||||
elif bufSize == 0:
|
||||
discard c_setvbuf(f, nil, IONBF, 0)
|
||||
@@ -734,7 +734,7 @@ proc reopen*(f: File, filename: string, mode: FileMode = fmRead): bool {.
|
||||
if freopen(filename.cstring, FormatOpen[mode], f) != nil:
|
||||
when not defined(nimInheritHandles) and declared(setInheritable) and
|
||||
NoInheritFlag.len == 0:
|
||||
if not setInheritable(getOsFileHandle(f), false):
|
||||
if not setInheritable(getFileHandle(f), false):
|
||||
close(f)
|
||||
return false
|
||||
result = true
|
||||
@@ -747,9 +747,7 @@ proc open*(f: var File, filehandle: FileHandle,
|
||||
##
|
||||
## The passed file handle will no longer be inheritable.
|
||||
when not defined(nimInheritHandles) and declared(setInheritable):
|
||||
let oshandle = when defined(windows): FileHandle getOsfhandle(
|
||||
filehandle) else: filehandle
|
||||
if not setInheritable(oshandle, false):
|
||||
if not setInheritable(filehandle, false):
|
||||
return false
|
||||
f = c_fdopen(filehandle, FormatOpen[mode])
|
||||
result = f != nil
|
||||
@@ -821,7 +819,7 @@ when defined(windows) and appType == "console" and
|
||||
proc getConsoleCP(): cuint {.stdcall, dynlib: "kernel32",
|
||||
importc: "GetConsoleCP".}
|
||||
|
||||
const Utf8codepage = 65001
|
||||
const Utf8codepage = 65001'u32
|
||||
|
||||
let
|
||||
consoleOutputCP = getConsoleOutputCP()
|
||||
|
||||
@@ -9,12 +9,6 @@
|
||||
|
||||
## Thread support for Nim.
|
||||
##
|
||||
## Nim's memory model for threads is quite different from other common
|
||||
## programming languages (C, Pascal): Each thread has its own
|
||||
## (garbage collected) heap and sharing of memory is restricted. This helps
|
||||
## to prevent race conditions and improves efficiency. See `the manual for
|
||||
## details of this memory model <manual.html#threads>`_.
|
||||
##
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
@@ -52,7 +46,7 @@ when defined(genode):
|
||||
import genode/env
|
||||
|
||||
|
||||
when hasAllocStack or defined(zephyr) or defined(freertos):
|
||||
when hasAllocStack or defined(zephyr) or defined(freertos) or defined(cpu16) or defined(cpu8):
|
||||
const
|
||||
nimThreadStackSize {.intdefine.} = 8192
|
||||
nimThreadStackGuard {.intdefine.} = 128
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Nim support for C/C++'s `wide strings`:idx:.
|
||||
## Nim support for C/C++'s `wide strings`:idx:.
|
||||
|
||||
#when not declared(ThisIsSystem):
|
||||
# {.error: "You must not import this module explicitly".}
|
||||
@@ -15,214 +15,215 @@
|
||||
type
|
||||
Utf16Char* = distinct int16
|
||||
|
||||
when defined(nimv2):
|
||||
when not (defined(cpu16) or defined(cpu8)):
|
||||
when defined(nimv2):
|
||||
|
||||
type
|
||||
WideCString* = ptr UncheckedArray[Utf16Char]
|
||||
type
|
||||
WideCString* = ptr UncheckedArray[Utf16Char]
|
||||
|
||||
WideCStringObj* = object
|
||||
bytes: int
|
||||
data: WideCString
|
||||
WideCStringObj* = object
|
||||
bytes: int
|
||||
data: WideCString
|
||||
|
||||
proc `=destroy`(a: var WideCStringObj) =
|
||||
if a.data != nil:
|
||||
proc `=destroy`(a: var WideCStringObj) =
|
||||
if a.data != nil:
|
||||
when compileOption("threads"):
|
||||
deallocShared(a.data)
|
||||
else:
|
||||
dealloc(a.data)
|
||||
|
||||
proc `=copy`(a: var WideCStringObj; b: WideCStringObj) {.error.}
|
||||
|
||||
proc `=sink`(a: var WideCStringObj; b: WideCStringObj) =
|
||||
a.bytes = b.bytes
|
||||
a.data = b.data
|
||||
|
||||
proc createWide(a: var WideCStringObj; bytes: int) =
|
||||
a.bytes = bytes
|
||||
when compileOption("threads"):
|
||||
deallocShared(a.data)
|
||||
a.data = cast[typeof(a.data)](allocShared0(bytes))
|
||||
else:
|
||||
dealloc(a.data)
|
||||
a.data = cast[typeof(a.data)](alloc0(bytes))
|
||||
|
||||
proc `=copy`(a: var WideCStringObj; b: WideCStringObj) {.error.}
|
||||
template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx]
|
||||
template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val
|
||||
|
||||
proc `=sink`(a: var WideCStringObj; b: WideCStringObj) =
|
||||
a.bytes = b.bytes
|
||||
a.data = b.data
|
||||
template nullWide(): untyped = WideCStringObj(bytes: 0, data: nil)
|
||||
|
||||
proc createWide(a: var WideCStringObj; bytes: int) =
|
||||
a.bytes = bytes
|
||||
when compileOption("threads"):
|
||||
a.data = cast[typeof(a.data)](allocShared0(bytes))
|
||||
else:
|
||||
a.data = cast[typeof(a.data)](alloc0(bytes))
|
||||
converter toWideCString*(x: WideCStringObj): WideCString {.inline.} =
|
||||
result = x.data
|
||||
|
||||
template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx]
|
||||
template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val
|
||||
|
||||
template nullWide(): untyped = WideCStringObj(bytes: 0, data: nil)
|
||||
|
||||
converter toWideCString*(x: WideCStringObj): WideCString {.inline.} =
|
||||
result = x.data
|
||||
|
||||
else:
|
||||
template nullWide(): untyped = nil
|
||||
|
||||
type
|
||||
WideCString* = ref UncheckedArray[Utf16Char]
|
||||
WideCStringObj* = WideCString
|
||||
|
||||
template createWide(a; L) =
|
||||
unsafeNew(a, L)
|
||||
|
||||
proc ord(arg: Utf16Char): int = int(cast[uint16](arg))
|
||||
|
||||
proc len*(w: WideCString): int =
|
||||
## returns the length of a widestring. This traverses the whole string to
|
||||
## find the binary zero end marker!
|
||||
result = 0
|
||||
while int16(w[result]) != 0'i16: inc result
|
||||
|
||||
const
|
||||
UNI_REPLACEMENT_CHAR = Utf16Char(0xFFFD'i16)
|
||||
UNI_MAX_BMP = 0x0000FFFF
|
||||
UNI_MAX_UTF16 = 0x0010FFFF
|
||||
# UNI_MAX_UTF32 = 0x7FFFFFFF
|
||||
# UNI_MAX_LEGAL_UTF32 = 0x0010FFFF
|
||||
|
||||
halfShift = 10
|
||||
halfBase = 0x0010000
|
||||
halfMask = 0x3FF
|
||||
|
||||
UNI_SUR_HIGH_START = 0xD800
|
||||
UNI_SUR_HIGH_END = 0xDBFF
|
||||
UNI_SUR_LOW_START = 0xDC00
|
||||
UNI_SUR_LOW_END = 0xDFFF
|
||||
UNI_REPL = 0xFFFD
|
||||
|
||||
template ones(n: untyped): untyped = ((1 shl n)-1)
|
||||
|
||||
template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) =
|
||||
## Returns the unicode character `s[i]` in `result`. If `doInc == true`
|
||||
## `i` is incremented by the number of bytes that have been processed.
|
||||
bind ones
|
||||
|
||||
if ord(s[i]) <= 127:
|
||||
result = ord(s[i])
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
if i <= L - 2:
|
||||
result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
when doInc: inc(i, 2)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
if i <= L - 3:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
when doInc: inc(i, 3)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
if i <= L - 4:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
when doInc: inc(i, 4)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
else:
|
||||
result = 0xFFFD
|
||||
when doInc: inc(i)
|
||||
template nullWide(): untyped = nil
|
||||
|
||||
iterator runes(s: cstring, L: int): int =
|
||||
var
|
||||
i = 0
|
||||
result: int
|
||||
while i < L:
|
||||
fastRuneAt(s, i, L, result, true)
|
||||
yield result
|
||||
type
|
||||
WideCString* = ref UncheckedArray[Utf16Char]
|
||||
WideCStringObj* = WideCString
|
||||
|
||||
proc newWideCString*(size: int): WideCStringObj =
|
||||
createWide(result, size * 2 + 2)
|
||||
template createWide(a; L) =
|
||||
unsafeNew(a, L)
|
||||
|
||||
proc newWideCString*(source: cstring, L: int): WideCStringObj =
|
||||
createWide(result, L * 2 + 2)
|
||||
var d = 0
|
||||
for ch in runes(source, L):
|
||||
proc ord(arg: Utf16Char): int = int(cast[uint16](arg))
|
||||
|
||||
if ch <= UNI_MAX_BMP:
|
||||
if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_LOW_END:
|
||||
proc len*(w: WideCString): int =
|
||||
## returns the length of a widestring. This traverses the whole string to
|
||||
## find the binary zero end marker!
|
||||
result = 0
|
||||
while int16(w[result]) != 0'i16: inc result
|
||||
|
||||
const
|
||||
UNI_REPLACEMENT_CHAR = Utf16Char(0xFFFD'i16)
|
||||
UNI_MAX_BMP = 0x0000FFFF
|
||||
UNI_MAX_UTF16 = 0x0010FFFF
|
||||
# UNI_MAX_UTF32 = 0x7FFFFFFF
|
||||
# UNI_MAX_LEGAL_UTF32 = 0x0010FFFF
|
||||
|
||||
halfShift = 10
|
||||
halfBase = 0x0010000
|
||||
halfMask = 0x3FF
|
||||
|
||||
UNI_SUR_HIGH_START = 0xD800
|
||||
UNI_SUR_HIGH_END = 0xDBFF
|
||||
UNI_SUR_LOW_START = 0xDC00
|
||||
UNI_SUR_LOW_END = 0xDFFF
|
||||
UNI_REPL = 0xFFFD
|
||||
|
||||
template ones(n: untyped): untyped = ((1 shl n)-1)
|
||||
|
||||
template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) =
|
||||
## Returns the unicode character `s[i]` in `result`. If `doInc == true`
|
||||
## `i` is incremented by the number of bytes that have been processed.
|
||||
bind ones
|
||||
|
||||
if ord(s[i]) <= 127:
|
||||
result = ord(s[i])
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
if i <= L - 2:
|
||||
result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
when doInc: inc(i, 2)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
if i <= L - 3:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
when doInc: inc(i, 3)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
if i <= L - 4:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
when doInc: inc(i, 4)
|
||||
else:
|
||||
result = UNI_REPL
|
||||
when doInc: inc(i)
|
||||
else:
|
||||
result = 0xFFFD
|
||||
when doInc: inc(i)
|
||||
|
||||
iterator runes(s: cstring, L: int): int =
|
||||
var
|
||||
i = 0
|
||||
result: int
|
||||
while i < L:
|
||||
fastRuneAt(s, i, L, result, true)
|
||||
yield result
|
||||
|
||||
proc newWideCString*(size: int): WideCStringObj =
|
||||
createWide(result, size * 2 + 2)
|
||||
|
||||
proc newWideCString*(source: cstring, L: int): WideCStringObj =
|
||||
createWide(result, L * 2 + 2)
|
||||
var d = 0
|
||||
for ch in runes(source, L):
|
||||
|
||||
if ch <= UNI_MAX_BMP:
|
||||
if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_LOW_END:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
result[d] = cast[Utf16Char](uint16(ch))
|
||||
elif ch > UNI_MAX_UTF16:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
result[d] = cast[Utf16Char](uint16(ch))
|
||||
elif ch > UNI_MAX_UTF16:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
let ch = ch - halfBase
|
||||
result[d] = cast[Utf16Char](uint16((ch shr halfShift) + UNI_SUR_HIGH_START))
|
||||
let ch = ch - halfBase
|
||||
result[d] = cast[Utf16Char](uint16((ch shr halfShift) + UNI_SUR_HIGH_START))
|
||||
inc d
|
||||
result[d] = cast[Utf16Char](uint16((ch and halfMask) + UNI_SUR_LOW_START))
|
||||
inc d
|
||||
result[d] = cast[Utf16Char](uint16((ch and halfMask) + UNI_SUR_LOW_START))
|
||||
inc d
|
||||
result[d] = Utf16Char(0)
|
||||
result[d] = Utf16Char(0)
|
||||
|
||||
proc newWideCString*(s: cstring): WideCStringObj =
|
||||
if s.isNil: return nullWide
|
||||
proc newWideCString*(s: cstring): WideCStringObj =
|
||||
if s.isNil: return nullWide
|
||||
|
||||
result = newWideCString(s, s.len)
|
||||
result = newWideCString(s, s.len)
|
||||
|
||||
proc newWideCString*(s: string): WideCStringObj =
|
||||
result = newWideCString(cstring s, s.len)
|
||||
proc newWideCString*(s: string): WideCStringObj =
|
||||
result = newWideCString(cstring s, s.len)
|
||||
|
||||
proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string =
|
||||
result = newStringOfCap(estimate + estimate shr 2)
|
||||
proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string =
|
||||
result = newStringOfCap(estimate + estimate shr 2)
|
||||
|
||||
var i = 0
|
||||
while w[i].int16 != 0'i16:
|
||||
var ch = ord(w[i])
|
||||
inc i
|
||||
if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END:
|
||||
# If the 16 bits following the high surrogate are in the source buffer...
|
||||
let ch2 = ord(w[i])
|
||||
var i = 0
|
||||
while w[i].int16 != 0'i16:
|
||||
var ch = ord(w[i])
|
||||
inc i
|
||||
if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END:
|
||||
# If the 16 bits following the high surrogate are in the source buffer...
|
||||
let ch2 = ord(w[i])
|
||||
|
||||
# If it's a low surrogate, convert to UTF32:
|
||||
if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END:
|
||||
ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase
|
||||
inc i
|
||||
else:
|
||||
# If it's a low surrogate, convert to UTF32:
|
||||
if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END:
|
||||
ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase
|
||||
inc i
|
||||
else:
|
||||
#invalid UTF-16
|
||||
ch = replacement
|
||||
elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END:
|
||||
#invalid UTF-16
|
||||
ch = replacement
|
||||
elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END:
|
||||
#invalid UTF-16
|
||||
ch = replacement
|
||||
|
||||
if ch < 0x80:
|
||||
result.add chr(ch)
|
||||
elif ch < 0x800:
|
||||
result.add chr((ch shr 6) or 0xc0)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
elif ch < 0x10000:
|
||||
result.add chr((ch shr 12) or 0xe0)
|
||||
result.add chr(((ch shr 6) and 0x3f) or 0x80)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
elif ch <= 0x10FFFF:
|
||||
result.add chr((ch shr 18) or 0xf0)
|
||||
result.add chr(((ch shr 12) and 0x3f) or 0x80)
|
||||
result.add chr(((ch shr 6) and 0x3f) or 0x80)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
else:
|
||||
# replacement char(in case user give very large number):
|
||||
result.add chr(0xFFFD shr 12 or 0b1110_0000)
|
||||
result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(0xFFFD and ones(6) or 0b10_0000_00)
|
||||
if ch < 0x80:
|
||||
result.add chr(ch)
|
||||
elif ch < 0x800:
|
||||
result.add chr((ch shr 6) or 0xc0)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
elif ch < 0x10000:
|
||||
result.add chr((ch shr 12) or 0xe0)
|
||||
result.add chr(((ch shr 6) and 0x3f) or 0x80)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
elif ch <= 0x10FFFF:
|
||||
result.add chr((ch shr 18) or 0xf0)
|
||||
result.add chr(((ch shr 12) and 0x3f) or 0x80)
|
||||
result.add chr(((ch shr 6) and 0x3f) or 0x80)
|
||||
result.add chr((ch and 0x3f) or 0x80)
|
||||
else:
|
||||
# replacement char(in case user give very large number):
|
||||
result.add chr(0xFFFD shr 12 or 0b1110_0000)
|
||||
result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(0xFFFD and ones(6) or 0b10_0000_00)
|
||||
|
||||
proc `$`*(s: WideCString): string =
|
||||
result = s $ 80
|
||||
proc `$`*(s: WideCString): string =
|
||||
result = s $ 80
|
||||
|
||||
when defined(nimv2):
|
||||
proc `$`*(s: WideCStringObj, estimate: int, replacement: int = 0xFFFD): string =
|
||||
`$`(s.data, estimate, replacement)
|
||||
when defined(nimv2):
|
||||
proc `$`*(s: WideCStringObj, estimate: int, replacement: int = 0xFFFD): string =
|
||||
`$`(s.data, estimate, replacement)
|
||||
|
||||
proc `$`*(s: WideCStringObj): string =
|
||||
$(s.data)
|
||||
proc `$`*(s: WideCStringObj): string =
|
||||
$(s.data)
|
||||
|
||||
proc len*(w: WideCStringObj): int {.inline.} =
|
||||
len(w.data)
|
||||
proc len*(w: WideCStringObj): int {.inline.} =
|
||||
len(w.data)
|
||||
|
||||
@@ -1664,6 +1664,8 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
|
||||
proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
|
||||
## Returns the last item of `s` and decreases `s.len` by one. This treats
|
||||
## `s` as a stack and implements the common *pop* operation.
|
||||
##
|
||||
## Raises `IndexDefect` if `s` is empty.
|
||||
runnableExamples:
|
||||
var a = @[1, 3, 5, 7]
|
||||
let b = pop(a)
|
||||
@@ -2001,7 +2003,7 @@ when notJSnotNims:
|
||||
proc equalMem(a, b: pointer, size: Natural): bool =
|
||||
nimCmpMem(a, b, size) == 0
|
||||
proc cmpMem(a, b: pointer, size: Natural): int =
|
||||
nimCmpMem(a, b, size)
|
||||
nimCmpMem(a, b, size).int
|
||||
|
||||
when not defined(js):
|
||||
proc cmp(x, y: string): int =
|
||||
@@ -2300,11 +2302,13 @@ else:
|
||||
type ExitCodeRange = int8
|
||||
else: # win32 uses low 32 bits
|
||||
type ExitCodeRange = cint
|
||||
|
||||
if errorcode < low(ExitCodeRange):
|
||||
rawQuit(low(ExitCodeRange).cint)
|
||||
elif errorcode > high(ExitCodeRange):
|
||||
rawQuit(high(ExitCodeRange).cint)
|
||||
when sizeof(errorcode) > sizeof(ExitCodeRange):
|
||||
if errorcode < low(ExitCodeRange):
|
||||
rawQuit(low(ExitCodeRange).cint)
|
||||
elif errorcode > high(ExitCodeRange):
|
||||
rawQuit(high(ExitCodeRange).cint)
|
||||
else:
|
||||
rawQuit(errorcode.cint)
|
||||
else:
|
||||
rawQuit(errorcode.cint)
|
||||
|
||||
@@ -2356,7 +2360,8 @@ when not defined(gcArc) and not defined(gcOrc):
|
||||
if s.len == 0: return
|
||||
when not defined(js) and not defined(nimscript) and not defined(nimSeqsV2):
|
||||
var s = cast[PGenericSeq](s)
|
||||
s.reserved = s.reserved or seqShallowFlag
|
||||
{.noSideEffect.}:
|
||||
s.reserved = s.reserved or seqShallowFlag
|
||||
|
||||
proc shallow*(s: var string) {.noSideEffect, inline.} =
|
||||
## Marks a string `s` as `shallow`:idx:. Subsequent assignments will not
|
||||
@@ -2369,7 +2374,8 @@ when not defined(gcArc) and not defined(gcOrc):
|
||||
s = cast[PGenericSeq](newString(0))
|
||||
# string literals cannot become 'shallow':
|
||||
if (s.reserved and strlitFlag) == 0:
|
||||
s.reserved = s.reserved or seqShallowFlag
|
||||
{.noSideEffect.}:
|
||||
s.reserved = s.reserved or seqShallowFlag
|
||||
|
||||
type
|
||||
NimNodeObj = object
|
||||
@@ -2796,7 +2802,7 @@ when notJSnotNims and not defined(nimSeqsV2):
|
||||
assert y == "abcgh"
|
||||
discard
|
||||
|
||||
proc arrayWith*[T](y: T, size: static int): array[size, T] {.noinit.} = # ? exempt from default value for result
|
||||
proc nimArrayWith[T](y: T, size: static int): array[size, T] {.compilerRtl, raises: [].} =
|
||||
## Creates a new array filled with `y`.
|
||||
for i in 0..size-1:
|
||||
result[i] = y
|
||||
|
||||
@@ -24,7 +24,7 @@ template track(op, address, size) =
|
||||
const
|
||||
nimMinHeapPages {.intdefine.} = 128 # 0.5 MB
|
||||
SmallChunkSize = PageSize
|
||||
MaxFli = 30
|
||||
MaxFli = when sizeof(int) > 2: 30 else: 14
|
||||
MaxLog2Sli = 5 # 32, this cannot be increased without changing 'uint32'
|
||||
# everywhere!
|
||||
MaxSli = 1 shl MaxLog2Sli
|
||||
@@ -32,7 +32,7 @@ const
|
||||
RealFli = MaxFli - FliOffset
|
||||
|
||||
# size of chunks in last matrix bin
|
||||
MaxBigChunkSize = 1 shl MaxFli - 1 shl (MaxFli-MaxLog2Sli-1)
|
||||
MaxBigChunkSize = int(1'i32 shl MaxFli - 1'i32 shl (MaxFli-MaxLog2Sli-1))
|
||||
HugeChunkSize = MaxBigChunkSize + 1
|
||||
|
||||
type
|
||||
@@ -115,7 +115,7 @@ type
|
||||
MemRegion = object
|
||||
when not defined(gcDestructors):
|
||||
minLargeObj, maxLargeObj: int
|
||||
freeSmallChunks: array[0..SmallChunkSize div MemAlign-1, PSmallChunk]
|
||||
freeSmallChunks: array[0..max(1,SmallChunkSize div MemAlign-1), PSmallChunk]
|
||||
flBitmap: uint32
|
||||
slBitmap: array[RealFli, uint32]
|
||||
matrix: array[RealFli, array[MaxSli, PBigChunk]]
|
||||
@@ -196,7 +196,7 @@ proc mappingSearch(r, fl, sl: var int) {.inline.} =
|
||||
let t = roundup((1 shl (msbit(uint32 r) - MaxLog2Sli)), PageSize) - 1
|
||||
r = r + t
|
||||
r = r and not t
|
||||
r = min(r, MaxBigChunkSize)
|
||||
r = min(r, MaxBigChunkSize).int
|
||||
fl = msbit(uint32 r)
|
||||
sl = (r shr (fl - MaxLog2Sli)) - MaxSli
|
||||
dec fl, FliOffset
|
||||
@@ -472,7 +472,7 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
|
||||
a.nextChunkSize = PageSize*4
|
||||
else:
|
||||
a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2)
|
||||
a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize)
|
||||
a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize).int
|
||||
|
||||
var size = size
|
||||
if size > a.nextChunkSize:
|
||||
@@ -787,8 +787,9 @@ when defined(gcDestructors):
|
||||
while it != nil:
|
||||
if maxIters == 0:
|
||||
let rest = it.next.loada
|
||||
it.next.storea nil
|
||||
addToSharedFreeList(c, rest)
|
||||
if rest != nil:
|
||||
it.next.storea nil
|
||||
addToSharedFreeList(c, rest)
|
||||
break
|
||||
inc x, size
|
||||
it = it.next.loada
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.} =
|
||||
proc succ*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Succ", noSideEffect.} =
|
||||
## Returns the `y`-th successor (default: 1) of the value `x`.
|
||||
##
|
||||
## If such a value does not exist, `OverflowDefect` is raised
|
||||
@@ -7,7 +7,7 @@ proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.} =
|
||||
assert succ(5) == 6
|
||||
assert succ(5, 3) == 8
|
||||
|
||||
proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.} =
|
||||
proc pred*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Pred", noSideEffect.} =
|
||||
## Returns the `y`-th predecessor (default: 1) of the value `x`.
|
||||
##
|
||||
## If such a value does not exist, `OverflowDefect` is raised
|
||||
@@ -16,7 +16,7 @@ proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.} =
|
||||
assert pred(5) == 4
|
||||
assert pred(5, 3) == 2
|
||||
|
||||
proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.} =
|
||||
proc inc*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Inc", noSideEffect.} =
|
||||
## Increments the ordinal `x` by `y`.
|
||||
##
|
||||
## If such a value does not exist, `OverflowDefect` is raised or a compile
|
||||
@@ -28,7 +28,7 @@ proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.} =
|
||||
inc(i, 3)
|
||||
assert i == 6
|
||||
|
||||
proc dec*[T: Ordinal](x: var T, y = 1) {.magic: "Dec", noSideEffect.} =
|
||||
proc dec*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Dec", noSideEffect.} =
|
||||
## Decrements the ordinal `x` by `y`.
|
||||
##
|
||||
## If such a value does not exist, `OverflowDefect` is raised or a compile
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Page size of the system; in most cases 4096 bytes. For exotic OS or
|
||||
# CPU this needs to be changed:
|
||||
const
|
||||
PageShift = when defined(nimPage256) or defined(cpu16): 8
|
||||
PageShift = when defined(nimPage256) or defined(cpu16): 3
|
||||
elif defined(nimPage512): 9
|
||||
elif defined(nimPage1k): 10
|
||||
else: 12 # \ # my tests showed no improvements for using larger page sizes.
|
||||
|
||||
@@ -103,16 +103,17 @@ proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffec
|
||||
## containers should also call their adding proc `add` for consistency.
|
||||
## Generic code becomes much easier to write if the Nim naming scheme is
|
||||
## respected.
|
||||
let oldLen = x.len
|
||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||
if xu.p == nil or xu.p.cap < oldLen+1:
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
|
||||
xu.len = oldLen+1
|
||||
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
||||
# copyMem(). This is fine as know by construction that
|
||||
# in `xu.p.data[oldLen]` there is nothing to destroy.
|
||||
# We also save the `wasMoved + destroy` pair for the sink parameter.
|
||||
xu.p.data[oldLen] = value
|
||||
{.cast(noSideEffect).}:
|
||||
let oldLen = x.len
|
||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||
if xu.p == nil or xu.p.cap < oldLen+1:
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
|
||||
xu.len = oldLen+1
|
||||
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
||||
# copyMem(). This is fine as know by construction that
|
||||
# in `xu.p.data[oldLen]` there is nothing to destroy.
|
||||
# We also save the `wasMoved + destroy` pair for the sink parameter.
|
||||
xu.p.data[oldLen] = value
|
||||
|
||||
proc setLen[T](s: var seq[T], newlen: Natural) =
|
||||
{.noSideEffect.}:
|
||||
|
||||
@@ -17,7 +17,7 @@ proc cmpStrings(a, b: string): int {.inline, compilerproc.} =
|
||||
let blen = b.len
|
||||
let minlen = min(alen, blen)
|
||||
if minlen > 0:
|
||||
result = c_memcmp(unsafeAddr a[0], unsafeAddr b[0], cast[csize_t](minlen))
|
||||
result = c_memcmp(unsafeAddr a[0], unsafeAddr b[0], cast[csize_t](minlen)).int
|
||||
if result == 0:
|
||||
result = alen - blen
|
||||
else:
|
||||
|
||||
@@ -36,7 +36,7 @@ template frees(s) =
|
||||
|
||||
proc resize(old: int): int {.inline.} =
|
||||
if old <= 0: result = 4
|
||||
elif old < 65536: result = old * 2
|
||||
elif old <= high(int16): result = old * 2
|
||||
else: result = old * 3 div 2 # for large arrays * 3/2 is better
|
||||
|
||||
proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,844 +0,0 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2015 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/widestrs
|
||||
|
||||
when not defined(ODBCVER):
|
||||
const
|
||||
ODBCVER = 0x0351 ## define ODBC version 3.51 by default
|
||||
|
||||
when defined(windows):
|
||||
{.push callconv: stdcall.}
|
||||
const odbclib = "odbc32.dll"
|
||||
else:
|
||||
{.push callconv: cdecl.}
|
||||
const odbclib = "libodbc.so"
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
# DATA TYPES CORRESPONDENCE
|
||||
# BDE fields ODBC types
|
||||
# ---------- ------------------
|
||||
# ftBlob SQL_BINARY
|
||||
# ftBoolean SQL_BIT
|
||||
# ftDate SQL_TYPE_DATE
|
||||
# ftTime SQL_TYPE_TIME
|
||||
# ftDateTime SQL_TYPE_TIMESTAMP
|
||||
# ftInteger SQL_INTEGER
|
||||
# ftSmallint SQL_SMALLINT
|
||||
# ftFloat SQL_DOUBLE
|
||||
# ftString SQL_CHAR
|
||||
# ftMemo SQL_BINARY // SQL_VARCHAR
|
||||
#
|
||||
|
||||
type
|
||||
TSqlChar* = char
|
||||
TSqlSmallInt* = int16
|
||||
SqlUSmallInt* = int16
|
||||
SqlHandle* = pointer
|
||||
SqlHEnv* = SqlHandle
|
||||
SqlHDBC* = SqlHandle
|
||||
SqlHStmt* = SqlHandle
|
||||
SqlHDesc* = SqlHandle
|
||||
TSqlInteger* = int32
|
||||
SqlUInteger* = int32
|
||||
TSqlLen* = int
|
||||
TSqlULen* = uint
|
||||
SqlPointer* = pointer
|
||||
TSqlReal* = cfloat
|
||||
TSqlDouble* = cdouble
|
||||
TSqlFloat* = cdouble
|
||||
SqlHWND* = pointer
|
||||
PSQLCHAR* = cstring
|
||||
PSQLINTEGER* = ptr TSqlInteger
|
||||
PSQLUINTEGER* = ptr SqlUInteger
|
||||
PSQLSMALLINT* = ptr TSqlSmallInt
|
||||
PSQLUSMALLINT* = ptr SqlUSmallInt
|
||||
PSQLREAL* = ptr TSqlReal
|
||||
PSQLDOUBLE* = ptr TSqlDouble
|
||||
PSQLFLOAT* = ptr TSqlFloat
|
||||
PSQLHANDLE* = ptr SqlHandle
|
||||
|
||||
const # SQL data type codes
|
||||
SQL_UNKNOWN_TYPE* = 0
|
||||
SQL_LONGVARCHAR* = (- 1)
|
||||
SQL_BINARY* = (- 2)
|
||||
SQL_VARBINARY* = (- 3)
|
||||
SQL_LONGVARBINARY* = (- 4)
|
||||
SQL_BIGINT* = (- 5)
|
||||
SQL_TINYINT* = (- 6)
|
||||
SQL_BIT* = (- 7)
|
||||
SQL_WCHAR* = (- 8)
|
||||
SQL_WVARCHAR* = (- 9)
|
||||
SQL_WLONGVARCHAR* = (- 10)
|
||||
SQL_CHAR* = 1
|
||||
SQL_NUMERIC* = 2
|
||||
SQL_DECIMAL* = 3
|
||||
SQL_INTEGER* = 4
|
||||
SQL_SMALLINT* = 5
|
||||
SQL_FLOAT* = 6
|
||||
SQL_REAL* = 7
|
||||
SQL_DOUBLE* = 8
|
||||
SQL_DATETIME* = 9
|
||||
SQL_VARCHAR* = 12
|
||||
SQL_TYPE_DATE* = 91
|
||||
SQL_TYPE_TIME* = 92
|
||||
SQL_TYPE_TIMESTAMP* = 93
|
||||
SQL_DATE* = 9
|
||||
SQL_TIME* = 10
|
||||
SQL_TIMESTAMP* = 11
|
||||
SQL_INTERVAL* = 10
|
||||
SQL_GUID* = - 11 # interval codes
|
||||
|
||||
when ODBCVER >= 0x0300:
|
||||
const
|
||||
SQL_CODE_YEAR* = 1
|
||||
SQL_CODE_MONTH* = 2
|
||||
SQL_CODE_DAY* = 3
|
||||
SQL_CODE_HOUR* = 4
|
||||
SQL_CODE_MINUTE* = 5
|
||||
SQL_CODE_SECOND* = 6
|
||||
SQL_CODE_YEAR_TO_MONTH* = 7
|
||||
SQL_CODE_DAY_TO_HOUR* = 8
|
||||
SQL_CODE_DAY_TO_MINUTE* = 9
|
||||
SQL_CODE_DAY_TO_SECOND* = 10
|
||||
SQL_CODE_HOUR_TO_MINUTE* = 11
|
||||
SQL_CODE_HOUR_TO_SECOND* = 12
|
||||
SQL_CODE_MINUTE_TO_SECOND* = 13
|
||||
SQL_INTERVAL_YEAR* = 100 + SQL_CODE_YEAR
|
||||
SQL_INTERVAL_MONTH* = 100 + SQL_CODE_MONTH
|
||||
SQL_INTERVAL_DAY* = 100 + SQL_CODE_DAY
|
||||
SQL_INTERVAL_HOUR* = 100 + SQL_CODE_HOUR
|
||||
SQL_INTERVAL_MINUTE* = 100 + SQL_CODE_MINUTE
|
||||
SQL_INTERVAL_SECOND* = 100 + SQL_CODE_SECOND
|
||||
SQL_INTERVAL_YEAR_TO_MONTH* = 100 + SQL_CODE_YEAR_TO_MONTH
|
||||
SQL_INTERVAL_DAY_TO_HOUR* = 100 + SQL_CODE_DAY_TO_HOUR
|
||||
SQL_INTERVAL_DAY_TO_MINUTE* = 100 + SQL_CODE_DAY_TO_MINUTE
|
||||
SQL_INTERVAL_DAY_TO_SECOND* = 100 + SQL_CODE_DAY_TO_SECOND
|
||||
SQL_INTERVAL_HOUR_TO_MINUTE* = 100 + SQL_CODE_HOUR_TO_MINUTE
|
||||
SQL_INTERVAL_HOUR_TO_SECOND* = 100 + SQL_CODE_HOUR_TO_SECOND
|
||||
SQL_INTERVAL_MINUTE_TO_SECOND* = 100 + SQL_CODE_MINUTE_TO_SECOND
|
||||
else:
|
||||
const
|
||||
SQL_INTERVAL_YEAR* = - 80
|
||||
SQL_INTERVAL_MONTH* = - 81
|
||||
SQL_INTERVAL_YEAR_TO_MONTH* = - 82
|
||||
SQL_INTERVAL_DAY* = - 83
|
||||
SQL_INTERVAL_HOUR* = - 84
|
||||
SQL_INTERVAL_MINUTE* = - 85
|
||||
SQL_INTERVAL_SECOND* = - 86
|
||||
SQL_INTERVAL_DAY_TO_HOUR* = - 87
|
||||
SQL_INTERVAL_DAY_TO_MINUTE* = - 88
|
||||
SQL_INTERVAL_DAY_TO_SECOND* = - 89
|
||||
SQL_INTERVAL_HOUR_TO_MINUTE* = - 90
|
||||
SQL_INTERVAL_HOUR_TO_SECOND* = - 91
|
||||
SQL_INTERVAL_MINUTE_TO_SECOND* = - 92
|
||||
|
||||
|
||||
when ODBCVER < 0x0300:
|
||||
const
|
||||
SQL_UNICODE* = - 95
|
||||
SQL_UNICODE_VARCHAR* = - 96
|
||||
SQL_UNICODE_LONGVARCHAR* = - 97
|
||||
SQL_UNICODE_CHAR* = SQL_UNICODE
|
||||
else:
|
||||
# The previous definitions for SQL_UNICODE_ are historical and obsolete
|
||||
const
|
||||
SQL_UNICODE* = SQL_WCHAR
|
||||
SQL_UNICODE_VARCHAR* = SQL_WVARCHAR
|
||||
SQL_UNICODE_LONGVARCHAR* = SQL_WLONGVARCHAR
|
||||
SQL_UNICODE_CHAR* = SQL_WCHAR
|
||||
const # C datatype to SQL datatype mapping
|
||||
SQL_C_CHAR* = SQL_CHAR
|
||||
SQL_C_LONG* = SQL_INTEGER
|
||||
SQL_C_SHORT* = SQL_SMALLINT
|
||||
SQL_C_FLOAT* = SQL_REAL
|
||||
SQL_C_DOUBLE* = SQL_DOUBLE
|
||||
SQL_C_NUMERIC* = SQL_NUMERIC
|
||||
SQL_C_DEFAULT* = 99
|
||||
SQL_SIGNED_OFFSET* = - 20
|
||||
SQL_UNSIGNED_OFFSET* = - 22
|
||||
SQL_C_DATE* = SQL_DATE
|
||||
SQL_C_TIME* = SQL_TIME
|
||||
SQL_C_TIMESTAMP* = SQL_TIMESTAMP
|
||||
SQL_C_TYPE_DATE* = SQL_TYPE_DATE
|
||||
SQL_C_TYPE_TIME* = SQL_TYPE_TIME
|
||||
SQL_C_TYPE_TIMESTAMP* = SQL_TYPE_TIMESTAMP
|
||||
SQL_C_INTERVAL_YEAR* = SQL_INTERVAL_YEAR
|
||||
SQL_C_INTERVAL_MONTH* = SQL_INTERVAL_MONTH
|
||||
SQL_C_INTERVAL_DAY* = SQL_INTERVAL_DAY
|
||||
SQL_C_INTERVAL_HOUR* = SQL_INTERVAL_HOUR
|
||||
SQL_C_INTERVAL_MINUTE* = SQL_INTERVAL_MINUTE
|
||||
SQL_C_INTERVAL_SECOND* = SQL_INTERVAL_SECOND
|
||||
SQL_C_INTERVAL_YEAR_TO_MONTH* = SQL_INTERVAL_YEAR_TO_MONTH
|
||||
SQL_C_INTERVAL_DAY_TO_HOUR* = SQL_INTERVAL_DAY_TO_HOUR
|
||||
SQL_C_INTERVAL_DAY_TO_MINUTE* = SQL_INTERVAL_DAY_TO_MINUTE
|
||||
SQL_C_INTERVAL_DAY_TO_SECOND* = SQL_INTERVAL_DAY_TO_SECOND
|
||||
SQL_C_INTERVAL_HOUR_TO_MINUTE* = SQL_INTERVAL_HOUR_TO_MINUTE
|
||||
SQL_C_INTERVAL_HOUR_TO_SECOND* = SQL_INTERVAL_HOUR_TO_SECOND
|
||||
SQL_C_INTERVAL_MINUTE_TO_SECOND* = SQL_INTERVAL_MINUTE_TO_SECOND
|
||||
SQL_C_BINARY* = SQL_BINARY
|
||||
SQL_C_BIT* = SQL_BIT
|
||||
SQL_C_SBIGINT* = SQL_BIGINT + SQL_SIGNED_OFFSET # SIGNED BIGINT
|
||||
SQL_C_UBIGINT* = SQL_BIGINT + SQL_UNSIGNED_OFFSET # UNSIGNED BIGINT
|
||||
SQL_C_TINYINT* = SQL_TINYINT
|
||||
SQL_C_SLONG* = SQL_C_LONG + SQL_SIGNED_OFFSET # SIGNED INTEGER
|
||||
SQL_C_SSHORT* = SQL_C_SHORT + SQL_SIGNED_OFFSET # SIGNED SMALLINT
|
||||
SQL_C_STINYINT* = SQL_TINYINT + SQL_SIGNED_OFFSET # SIGNED TINYINT
|
||||
SQL_C_ULONG* = SQL_C_LONG + SQL_UNSIGNED_OFFSET # UNSIGNED INTEGER
|
||||
SQL_C_USHORT* = SQL_C_SHORT + SQL_UNSIGNED_OFFSET # UNSIGNED SMALLINT
|
||||
SQL_C_UTINYINT* = SQL_TINYINT + SQL_UNSIGNED_OFFSET # UNSIGNED TINYINT
|
||||
SQL_C_BOOKMARK* = SQL_C_ULONG # BOOKMARK
|
||||
SQL_C_GUID* = SQL_GUID
|
||||
SQL_TYPE_NULL* = 0
|
||||
|
||||
when ODBCVER < 0x0300:
|
||||
const
|
||||
SQL_TYPE_MIN* = SQL_BIT
|
||||
SQL_TYPE_MAX* = SQL_VARCHAR
|
||||
|
||||
const
|
||||
SQL_C_VARBOOKMARK* = SQL_C_BINARY
|
||||
SQL_API_SQLDESCRIBEPARAM* = 58
|
||||
SQL_NO_TOTAL* = - 4
|
||||
|
||||
type
|
||||
SQL_DATE_STRUCT* {.final, pure.} = object
|
||||
Year*: TSqlSmallInt
|
||||
Month*: SqlUSmallInt
|
||||
Day*: SqlUSmallInt
|
||||
|
||||
PSQL_DATE_STRUCT* = ptr SQL_DATE_STRUCT
|
||||
SQL_TIME_STRUCT* {.final, pure.} = object
|
||||
Hour*: SqlUSmallInt
|
||||
Minute*: SqlUSmallInt
|
||||
Second*: SqlUSmallInt
|
||||
|
||||
PSQL_TIME_STRUCT* = ptr SQL_TIME_STRUCT
|
||||
SQL_TIMESTAMP_STRUCT* {.final, pure.} = object
|
||||
Year*: SqlUSmallInt
|
||||
Month*: SqlUSmallInt
|
||||
Day*: SqlUSmallInt
|
||||
Hour*: SqlUSmallInt
|
||||
Minute*: SqlUSmallInt
|
||||
Second*: SqlUSmallInt
|
||||
Fraction*: SqlUInteger
|
||||
|
||||
PSQL_TIMESTAMP_STRUCT* = ptr SQL_TIMESTAMP_STRUCT
|
||||
|
||||
const
|
||||
SQL_NAME_LEN* = 128
|
||||
SQL_OV_ODBC3* = 3
|
||||
SQL_OV_ODBC2* = 2
|
||||
SQL_ATTR_ODBC_VERSION* = 200 # Options for SQLDriverConnect
|
||||
SQL_DRIVER_NOPROMPT* = 0
|
||||
SQL_DRIVER_COMPLETE* = 1
|
||||
SQL_DRIVER_PROMPT* = 2
|
||||
SQL_DRIVER_COMPLETE_REQUIRED* = 3
|
||||
SQL_IS_POINTER* = (- 4) # whether an attribute is a pointer or not
|
||||
SQL_IS_UINTEGER* = (- 5)
|
||||
SQL_IS_INTEGER* = (- 6)
|
||||
SQL_IS_USMALLINT* = (- 7)
|
||||
SQL_IS_SMALLINT* = (- 8) # SQLExtendedFetch "fFetchType" values
|
||||
SQL_FETCH_BOOKMARK* = 8
|
||||
SQL_SCROLL_OPTIONS* = 44 # SQL_USE_BOOKMARKS options
|
||||
SQL_UB_OFF* = 0
|
||||
SQL_UB_ON* = 1
|
||||
SQL_UB_DEFAULT* = SQL_UB_OFF
|
||||
SQL_UB_FIXED* = SQL_UB_ON
|
||||
SQL_UB_VARIABLE* = 2 # SQL_SCROLL_OPTIONS masks
|
||||
SQL_SO_FORWARD_ONLY* = 0x00000001
|
||||
SQL_SO_KEYSET_DRIVEN* = 0x00000002
|
||||
SQL_SO_DYNAMIC* = 0x00000004
|
||||
SQL_SO_MIXED* = 0x00000008
|
||||
SQL_SO_STATIC* = 0x00000010
|
||||
SQL_BOOKMARK_PERSISTENCE* = 82
|
||||
SQL_STATIC_SENSITIVITY* = 83 # SQL_BOOKMARK_PERSISTENCE values
|
||||
SQL_BP_CLOSE* = 0x00000001
|
||||
SQL_BP_DELETE* = 0x00000002
|
||||
SQL_BP_DROP* = 0x00000004
|
||||
SQL_BP_TRANSACTION* = 0x00000008
|
||||
SQL_BP_UPDATE* = 0x00000010
|
||||
SQL_BP_OTHER_HSTMT* = 0x00000020
|
||||
SQL_BP_SCROLL* = 0x00000040
|
||||
SQL_DYNAMIC_CURSOR_ATTRIBUTES1* = 144
|
||||
SQL_DYNAMIC_CURSOR_ATTRIBUTES2* = 145
|
||||
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1* = 146
|
||||
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2* = 147
|
||||
SQL_INDEX_KEYWORDS* = 148
|
||||
SQL_INFO_SCHEMA_VIEWS* = 149
|
||||
SQL_KEYSET_CURSOR_ATTRIBUTES1* = 150
|
||||
SQL_KEYSET_CURSOR_ATTRIBUTES2* = 151
|
||||
SQL_STATIC_CURSOR_ATTRIBUTES1* = 167
|
||||
SQL_STATIC_CURSOR_ATTRIBUTES2* = 168 # supported SQLFetchScroll FetchOrientation's
|
||||
SQL_CA1_NEXT* = 1
|
||||
SQL_CA1_ABSOLUTE* = 2
|
||||
SQL_CA1_RELATIVE* = 4
|
||||
SQL_CA1_BOOKMARK* = 8 # supported SQLSetPos LockType's
|
||||
SQL_CA1_LOCK_NO_CHANGE* = 0x00000040
|
||||
SQL_CA1_LOCK_EXCLUSIVE* = 0x00000080
|
||||
SQL_CA1_LOCK_UNLOCK* = 0x00000100 # supported SQLSetPos Operations
|
||||
SQL_CA1_POS_POSITION* = 0x00000200
|
||||
SQL_CA1_POS_UPDATE* = 0x00000400
|
||||
SQL_CA1_POS_DELETE* = 0x00000800
|
||||
SQL_CA1_POS_REFRESH* = 0x00001000 # positioned updates and deletes
|
||||
SQL_CA1_POSITIONED_UPDATE* = 0x00002000
|
||||
SQL_CA1_POSITIONED_DELETE* = 0x00004000
|
||||
SQL_CA1_SELECT_FOR_UPDATE* = 0x00008000 # supported SQLBulkOperations operations
|
||||
SQL_CA1_BULK_ADD* = 0x00010000
|
||||
SQL_CA1_BULK_UPDATE_BY_BOOKMARK* = 0x00020000
|
||||
SQL_CA1_BULK_DELETE_BY_BOOKMARK* = 0x00040000
|
||||
SQL_CA1_BULK_FETCH_BY_BOOKMARK* = 0x00080000 # supported values for SQL_ATTR_SCROLL_CONCURRENCY
|
||||
SQL_CA2_READ_ONLY_CONCURRENCY* = 1
|
||||
SQL_CA2_LOCK_CONCURRENCY* = 2
|
||||
SQL_CA2_OPT_ROWVER_CONCURRENCY* = 4
|
||||
SQL_CA2_OPT_VALUES_CONCURRENCY* = 8 # sensitivity of the cursor to its own inserts, deletes, and updates
|
||||
SQL_CA2_SENSITIVITY_ADDITIONS* = 0x00000010
|
||||
SQL_CA2_SENSITIVITY_DELETIONS* = 0x00000020
|
||||
SQL_CA2_SENSITIVITY_UPDATES* = 0x00000040 # semantics of SQL_ATTR_MAX_ROWS
|
||||
SQL_CA2_MAX_ROWS_SELECT* = 0x00000080
|
||||
SQL_CA2_MAX_ROWS_INSERT* = 0x00000100
|
||||
SQL_CA2_MAX_ROWS_DELETE* = 0x00000200
|
||||
SQL_CA2_MAX_ROWS_UPDATE* = 0x00000400
|
||||
SQL_CA2_MAX_ROWS_CATALOG* = 0x00000800
|
||||
SQL_CA2_MAX_ROWS_AFFECTS_ALL* = (SQL_CA2_MAX_ROWS_SELECT or
|
||||
SQL_CA2_MAX_ROWS_INSERT or SQL_CA2_MAX_ROWS_DELETE or
|
||||
SQL_CA2_MAX_ROWS_UPDATE or SQL_CA2_MAX_ROWS_CATALOG) # semantics of
|
||||
# SQL_DIAG_CURSOR_ROW_COUNT
|
||||
SQL_CA2_CRC_EXACT* = 0x00001000
|
||||
SQL_CA2_CRC_APPROXIMATE* = 0x00002000 # the kinds of positioned statements that can be simulated
|
||||
SQL_CA2_SIMULATE_NON_UNIQUE* = 0x00004000
|
||||
SQL_CA2_SIMULATE_TRY_UNIQUE* = 0x00008000
|
||||
SQL_CA2_SIMULATE_UNIQUE* = 0x00010000 # Operations in SQLBulkOperations
|
||||
SQL_ADD* = 4
|
||||
SQL_SETPOS_MAX_OPTION_VALUE* = SQL_ADD
|
||||
SQL_UPDATE_BY_BOOKMARK* = 5
|
||||
SQL_DELETE_BY_BOOKMARK* = 6
|
||||
SQL_FETCH_BY_BOOKMARK* = 7 # Operations in SQLSetPos
|
||||
SQL_POSITION* = 0
|
||||
SQL_REFRESH* = 1
|
||||
SQL_UPDATE* = 2
|
||||
SQL_DELETE* = 3 # Lock options in SQLSetPos
|
||||
SQL_LOCK_NO_CHANGE* = 0
|
||||
SQL_LOCK_EXCLUSIVE* = 1
|
||||
SQL_LOCK_UNLOCK* = 2 # SQLExtendedFetch "rgfRowStatus" element values
|
||||
SQL_ROW_SUCCESS* = 0
|
||||
SQL_ROW_DELETED* = 1
|
||||
SQL_ROW_UPDATED* = 2
|
||||
SQL_ROW_NOROW* = 3
|
||||
SQL_ROW_ADDED* = 4
|
||||
SQL_ROW_ERROR* = 5
|
||||
SQL_ROW_SUCCESS_WITH_INFO* = 6
|
||||
SQL_ROW_PROCEED* = 0
|
||||
SQL_ROW_IGNORE* = 1
|
||||
SQL_MAX_DSN_LENGTH* = 32 # maximum data source name size
|
||||
SQL_MAX_OPTION_STRING_LENGTH* = 256
|
||||
SQL_ODBC_CURSORS* = 110
|
||||
SQL_ATTR_ODBC_CURSORS* = SQL_ODBC_CURSORS # SQL_ODBC_CURSORS options
|
||||
SQL_CUR_USE_IF_NEEDED* = 0
|
||||
SQL_CUR_USE_ODBC* = 1
|
||||
SQL_CUR_USE_DRIVER* = 2
|
||||
SQL_CUR_DEFAULT* = SQL_CUR_USE_DRIVER
|
||||
SQL_PARAM_TYPE_UNKNOWN* = 0
|
||||
SQL_PARAM_INPUT* = 1
|
||||
SQL_PARAM_INPUT_OUTPUT* = 2
|
||||
SQL_RESULT_COL* = 3
|
||||
SQL_PARAM_OUTPUT* = 4
|
||||
SQL_RETURN_VALUE* = 5 # special length/indicator values
|
||||
SQL_NULL_DATA* = (- 1)
|
||||
SQL_DATA_AT_EXEC* = (- 2)
|
||||
SQL_SUCCESS* = 0
|
||||
SQL_SUCCESS_WITH_INFO* = 1
|
||||
SQL_NO_DATA* = 100
|
||||
SQL_ERROR* = (- 1)
|
||||
SQL_INVALID_HANDLE* = (- 2)
|
||||
SQL_STILL_EXECUTING* = 2
|
||||
SQL_NEED_DATA* = 99 # flags for null-terminated string
|
||||
SQL_NTS* = (- 3) # maximum message length
|
||||
SQL_MAX_MESSAGE_LENGTH* = 512 # date/time length constants
|
||||
SQL_DATE_LEN* = 10
|
||||
SQL_TIME_LEN* = 8 # add P+1 if precision is nonzero
|
||||
SQL_TIMESTAMP_LEN* = 19 # add P+1 if precision is nonzero
|
||||
# handle type identifiers
|
||||
SQL_HANDLE_ENV* = 1
|
||||
SQL_HANDLE_DBC* = 2
|
||||
SQL_HANDLE_STMT* = 3
|
||||
SQL_HANDLE_DESC* = 4 # environment attribute
|
||||
SQL_ATTR_OUTPUT_NTS* = 10001 # connection attributes
|
||||
SQL_ATTR_AUTO_IPD* = 10001
|
||||
SQL_ATTR_METADATA_ID* = 10014 # statement attributes
|
||||
SQL_ATTR_APP_ROW_DESC* = 10010
|
||||
SQL_ATTR_APP_PARAM_DESC* = 10011
|
||||
SQL_ATTR_IMP_ROW_DESC* = 10012
|
||||
SQL_ATTR_IMP_PARAM_DESC* = 10013
|
||||
SQL_ATTR_CURSOR_SCROLLABLE* = (- 1)
|
||||
SQL_ATTR_CURSOR_SENSITIVITY* = (- 2)
|
||||
SQL_QUERY_TIMEOUT* = 0
|
||||
SQL_MAX_ROWS* = 1
|
||||
SQL_NOSCAN* = 2
|
||||
SQL_MAX_LENGTH* = 3
|
||||
SQL_ASYNC_ENABLE* = 4 # same as SQL_ATTR_ASYNC_ENABLE */
|
||||
SQL_BIND_TYPE* = 5
|
||||
SQL_CURSOR_TYPE* = 6
|
||||
SQL_CONCURRENCY* = 7
|
||||
SQL_KEYSET_SIZE* = 8
|
||||
SQL_ROWSET_SIZE* = 9
|
||||
SQL_SIMULATE_CURSOR* = 10
|
||||
SQL_RETRIEVE_DATA* = 11
|
||||
SQL_USE_BOOKMARKS* = 12
|
||||
SQL_GET_BOOKMARK* = 13 # GetStmtOption Only */
|
||||
SQL_ROW_NUMBER* = 14 # GetStmtOption Only */
|
||||
SQL_ATTR_CURSOR_TYPE* = SQL_CURSOR_TYPE
|
||||
SQL_ATTR_CONCURRENCY* = SQL_CONCURRENCY
|
||||
SQL_ATTR_FETCH_BOOKMARK_PTR* = 16
|
||||
SQL_ATTR_ROW_STATUS_PTR* = 25
|
||||
SQL_ATTR_ROWS_FETCHED_PTR* = 26
|
||||
SQL_AUTOCOMMIT* = 102
|
||||
SQL_ATTR_AUTOCOMMIT* = SQL_AUTOCOMMIT
|
||||
SQL_ATTR_ROW_NUMBER* = SQL_ROW_NUMBER
|
||||
SQL_TXN_ISOLATION* = 108
|
||||
SQL_ATTR_TXN_ISOLATION* = SQL_TXN_ISOLATION
|
||||
SQL_ATTR_MAX_ROWS* = SQL_MAX_ROWS
|
||||
SQL_ATTR_USE_BOOKMARKS* = SQL_USE_BOOKMARKS #* connection attributes */
|
||||
SQL_ACCESS_MODE* = 101 # SQL_AUTOCOMMIT =102;
|
||||
SQL_LOGIN_TIMEOUT* = 103
|
||||
SQL_OPT_TRACE* = 104
|
||||
SQL_OPT_TRACEFILE* = 105
|
||||
SQL_TRANSLATE_DLL* = 106
|
||||
SQL_TRANSLATE_OPTION* = 107 # SQL_TXN_ISOLATION =108;
|
||||
SQL_CURRENT_QUALIFIER* = 109 # SQL_ODBC_CURSORS =110;
|
||||
SQL_QUIET_MODE* = 111
|
||||
SQL_PACKET_SIZE* = 112 #* connection attributes with new names */
|
||||
SQL_ATTR_ACCESS_MODE* = SQL_ACCESS_MODE # SQL_ATTR_AUTOCOMMIT =SQL_AUTOCOMMIT;
|
||||
SQL_ATTR_CONNECTION_DEAD* = 1209 #* GetConnectAttr only */
|
||||
SQL_ATTR_CONNECTION_TIMEOUT* = 113
|
||||
SQL_ATTR_CURRENT_CATALOG* = SQL_CURRENT_QUALIFIER
|
||||
SQL_ATTR_DISCONNECT_BEHAVIOR* = 114
|
||||
SQL_ATTR_ENLIST_IN_DTC* = 1207
|
||||
SQL_ATTR_ENLIST_IN_XA* = 1208
|
||||
SQL_ATTR_LOGIN_TIMEOUT* = SQL_LOGIN_TIMEOUT # SQL_ATTR_ODBC_CURSORS =SQL_ODBC_CURSORS;
|
||||
SQL_ATTR_PACKET_SIZE* = SQL_PACKET_SIZE
|
||||
SQL_ATTR_QUIET_MODE* = SQL_QUIET_MODE
|
||||
SQL_ATTR_TRACE* = SQL_OPT_TRACE
|
||||
SQL_ATTR_TRACEFILE* = SQL_OPT_TRACEFILE
|
||||
SQL_ATTR_TRANSLATE_LIB* = SQL_TRANSLATE_DLL
|
||||
SQL_ATTR_TRANSLATE_OPTION* = SQL_TRANSLATE_OPTION # SQL_ATTR_TXN_ISOLATION =SQL_TXN_ISOLATION;
|
||||
#* SQL_ACCESS_MODE options */
|
||||
SQL_MODE_READ_WRITE* = 0
|
||||
SQL_MODE_READ_ONLY* = 1
|
||||
SQL_MODE_DEFAULT* = SQL_MODE_READ_WRITE #* SQL_AUTOCOMMIT options */
|
||||
SQL_AUTOCOMMIT_OFF* = 0
|
||||
SQL_AUTOCOMMIT_ON* = 1
|
||||
SQL_AUTOCOMMIT_DEFAULT* = SQL_AUTOCOMMIT_ON # SQL_ATTR_CURSOR_SCROLLABLE values
|
||||
SQL_NONSCROLLABLE* = 0
|
||||
SQL_SCROLLABLE* = 1 # SQL_CURSOR_TYPE options
|
||||
SQL_CURSOR_FORWARD_ONLY* = 0
|
||||
SQL_CURSOR_KEYSET_DRIVEN* = 1
|
||||
SQL_CURSOR_DYNAMIC* = 2
|
||||
SQL_CURSOR_STATIC* = 3
|
||||
SQL_CURSOR_TYPE_DEFAULT* = SQL_CURSOR_FORWARD_ONLY # Default value
|
||||
# SQL_CONCURRENCY options
|
||||
SQL_CONCUR_READ_ONLY* = 1
|
||||
SQL_CONCUR_LOCK* = 2
|
||||
SQL_CONCUR_ROWVER* = 3
|
||||
SQL_CONCUR_VALUES* = 4
|
||||
SQL_CONCUR_DEFAULT* = SQL_CONCUR_READ_ONLY # Default value
|
||||
# identifiers of fields in the SQL descriptor
|
||||
SQL_DESC_COUNT* = 1001
|
||||
SQL_DESC_TYPE* = 1002
|
||||
SQL_DESC_LENGTH* = 1003
|
||||
SQL_DESC_OCTET_LENGTH_PTR* = 1004
|
||||
SQL_DESC_PRECISION* = 1005
|
||||
SQL_DESC_SCALE* = 1006
|
||||
SQL_DESC_DATETIME_INTERVAL_CODE* = 1007
|
||||
SQL_DESC_NULLABLE* = 1008
|
||||
SQL_DESC_INDICATOR_PTR* = 1009
|
||||
SQL_DESC_DATA_PTR* = 1010
|
||||
SQL_DESC_NAME* = 1011
|
||||
SQL_DESC_UNNAMED* = 1012
|
||||
SQL_DESC_OCTET_LENGTH* = 1013
|
||||
SQL_DESC_ALLOC_TYPE* = 1099 # identifiers of fields in the diagnostics area
|
||||
SQL_DIAG_RETURNCODE* = 1
|
||||
SQL_DIAG_NUMBER* = 2
|
||||
SQL_DIAG_ROW_COUNT* = 3
|
||||
SQL_DIAG_SQLSTATE* = 4
|
||||
SQL_DIAG_NATIVE* = 5
|
||||
SQL_DIAG_MESSAGE_TEXT* = 6
|
||||
SQL_DIAG_DYNAMIC_FUNCTION* = 7
|
||||
SQL_DIAG_CLASS_ORIGIN* = 8
|
||||
SQL_DIAG_SUBCLASS_ORIGIN* = 9
|
||||
SQL_DIAG_CONNECTION_NAME* = 10
|
||||
SQL_DIAG_SERVER_NAME* = 11
|
||||
SQL_DIAG_DYNAMIC_FUNCTION_CODE* = 12 # dynamic function codes
|
||||
SQL_DIAG_ALTER_TABLE* = 4
|
||||
SQL_DIAG_CREATE_INDEX* = (- 1)
|
||||
SQL_DIAG_CREATE_TABLE* = 77
|
||||
SQL_DIAG_CREATE_VIEW* = 84
|
||||
SQL_DIAG_DELETE_WHERE* = 19
|
||||
SQL_DIAG_DROP_INDEX* = (- 2)
|
||||
SQL_DIAG_DROP_TABLE* = 32
|
||||
SQL_DIAG_DROP_VIEW* = 36
|
||||
SQL_DIAG_DYNAMIC_DELETE_CURSOR* = 38
|
||||
SQL_DIAG_DYNAMIC_UPDATE_CURSOR* = 81
|
||||
SQL_DIAG_GRANT* = 48
|
||||
SQL_DIAG_INSERT* = 50
|
||||
SQL_DIAG_REVOKE* = 59
|
||||
SQL_DIAG_SELECT_CURSOR* = 85
|
||||
SQL_DIAG_UNKNOWN_STATEMENT* = 0
|
||||
SQL_DIAG_UPDATE_WHERE* = 82 # Statement attribute values for cursor sensitivity
|
||||
SQL_UNSPECIFIED* = 0
|
||||
SQL_INSENSITIVE* = 1
|
||||
SQL_SENSITIVE* = 2 # GetTypeInfo() request for all data types
|
||||
SQL_ALL_TYPES* = 0 # Default conversion code for SQLBindCol(), SQLBindParam() and SQLGetData()
|
||||
SQL_DEFAULT* = 99 # SQLGetData() code indicating that the application row descriptor
|
||||
# specifies the data type
|
||||
SQL_ARD_TYPE* = (- 99) # SQL date/time type subcodes
|
||||
SQL_CODE_DATE* = 1
|
||||
SQL_CODE_TIME* = 2
|
||||
SQL_CODE_TIMESTAMP* = 3 # CLI option values
|
||||
SQL_FALSE* = 0
|
||||
SQL_TRUE* = 1 # values of NULLABLE field in descriptor
|
||||
SQL_NO_NULLS* = 0
|
||||
SQL_NULLABLE* = 1 # Value returned by SQLGetTypeInfo() to denote that it is
|
||||
# not known whether or not a data type supports null values.
|
||||
SQL_NULLABLE_UNKNOWN* = 2
|
||||
SQL_CLOSE* = 0
|
||||
SQL_DROP* = 1
|
||||
SQL_UNBIND* = 2
|
||||
SQL_RESET_PARAMS* = 3 # Codes used for FetchOrientation in SQLFetchScroll(),
|
||||
# and in SQLDataSources()
|
||||
SQL_FETCH_NEXT* = 1
|
||||
SQL_FETCH_FIRST* = 2
|
||||
SQL_FETCH_FIRST_USER* = 31
|
||||
SQL_FETCH_FIRST_SYSTEM* = 32 # Other codes used for FetchOrientation in SQLFetchScroll()
|
||||
SQL_FETCH_LAST* = 3
|
||||
SQL_FETCH_PRIOR* = 4
|
||||
SQL_FETCH_ABSOLUTE* = 5
|
||||
SQL_FETCH_RELATIVE* = 6
|
||||
SQL_NULL_HENV* = SqlHEnv(nil)
|
||||
SQL_NULL_HDBC* = SqlHDBC(nil)
|
||||
SQL_NULL_HSTMT* = SqlHStmt(nil)
|
||||
SQL_NULL_HDESC* = SqlHDesc(nil) #* null handle used in place of parent handle when allocating HENV */
|
||||
SQL_NULL_HANDLE* = SqlHandle(nil) #* Values that may appear in the result set of SQLSpecialColumns() */
|
||||
SQL_SCOPE_CURROW* = 0
|
||||
SQL_SCOPE_TRANSACTION* = 1
|
||||
SQL_SCOPE_SESSION* = 2 #* Column types and scopes in SQLSpecialColumns. */
|
||||
SQL_BEST_ROWID* = 1
|
||||
SQL_ROWVER* = 2
|
||||
SQL_ROW_IDENTIFIER* = 1 #* Reserved values for UNIQUE argument of SQLStatistics() */
|
||||
SQL_INDEX_UNIQUE* = 0
|
||||
SQL_INDEX_ALL* = 1 #* Reserved values for RESERVED argument of SQLStatistics() */
|
||||
SQL_QUICK* = 0
|
||||
SQL_ENSURE* = 1 #* Values that may appear in the result set of SQLStatistics() */
|
||||
SQL_TABLE_STAT* = 0
|
||||
SQL_INDEX_CLUSTERED* = 1
|
||||
SQL_INDEX_HASHED* = 2
|
||||
SQL_INDEX_OTHER* = 3
|
||||
SQL_SCROLL_CONCURRENCY* = 43
|
||||
SQL_TXN_CAPABLE* = 46
|
||||
SQL_TRANSACTION_CAPABLE* = SQL_TXN_CAPABLE
|
||||
SQL_USER_NAME* = 47
|
||||
SQL_TXN_ISOLATION_OPTION* = 72
|
||||
SQL_TRANSACTION_ISOLATION_OPTION* = SQL_TXN_ISOLATION_OPTION
|
||||
SQL_OJ_CAPABILITIES* = 115
|
||||
SQL_OUTER_JOIN_CAPABILITIES* = SQL_OJ_CAPABILITIES
|
||||
SQL_XOPEN_CLI_YEAR* = 10000
|
||||
SQL_CURSOR_SENSITIVITY* = 10001
|
||||
SQL_DESCRIBE_PARAMETER* = 10002
|
||||
SQL_CATALOG_NAME* = 10003
|
||||
SQL_COLLATION_SEQ* = 10004
|
||||
SQL_MAX_IDENTIFIER_LEN* = 10005
|
||||
SQL_MAXIMUM_IDENTIFIER_LENGTH* = SQL_MAX_IDENTIFIER_LEN
|
||||
SQL_SCCO_READ_ONLY* = 1
|
||||
SQL_SCCO_LOCK* = 2
|
||||
SQL_SCCO_OPT_ROWVER* = 4
|
||||
SQL_SCCO_OPT_VALUES* = 8 #* SQL_TXN_CAPABLE values */
|
||||
SQL_TC_NONE* = 0
|
||||
SQL_TC_DML* = 1
|
||||
SQL_TC_ALL* = 2
|
||||
SQL_TC_DDL_COMMIT* = 3
|
||||
SQL_TC_DDL_IGNORE* = 4 #* SQL_TXN_ISOLATION_OPTION bitmasks */
|
||||
SQL_TXN_READ_UNCOMMITTED* = 1
|
||||
SQL_TRANSACTION_READ_UNCOMMITTED* = SQL_TXN_READ_UNCOMMITTED
|
||||
SQL_TXN_READ_COMMITTED* = 2
|
||||
SQL_TRANSACTION_READ_COMMITTED* = SQL_TXN_READ_COMMITTED
|
||||
SQL_TXN_REPEATABLE_READ* = 4
|
||||
SQL_TRANSACTION_REPEATABLE_READ* = SQL_TXN_REPEATABLE_READ
|
||||
SQL_TXN_SERIALIZABLE* = 8
|
||||
SQL_TRANSACTION_SERIALIZABLE* = SQL_TXN_SERIALIZABLE
|
||||
SQL_SS_ADDITIONS* = 1
|
||||
SQL_SS_DELETIONS* = 2
|
||||
SQL_SS_UPDATES* = 4 # SQLColAttributes defines
|
||||
SQL_COLUMN_COUNT* = 0
|
||||
SQL_COLUMN_NAME* = 1
|
||||
SQL_COLUMN_TYPE* = 2
|
||||
SQL_COLUMN_LENGTH* = 3
|
||||
SQL_COLUMN_PRECISION* = 4
|
||||
SQL_COLUMN_SCALE* = 5
|
||||
SQL_COLUMN_DISPLAY_SIZE* = 6
|
||||
SQL_COLUMN_NULLABLE* = 7
|
||||
SQL_COLUMN_UNSIGNED* = 8
|
||||
SQL_COLUMN_MONEY* = 9
|
||||
SQL_COLUMN_UPDATABLE* = 10
|
||||
SQL_COLUMN_AUTO_INCREMENT* = 11
|
||||
SQL_COLUMN_CASE_SENSITIVE* = 12
|
||||
SQL_COLUMN_SEARCHABLE* = 13
|
||||
SQL_COLUMN_TYPE_NAME* = 14
|
||||
SQL_COLUMN_TABLE_NAME* = 15
|
||||
SQL_COLUMN_OWNER_NAME* = 16
|
||||
SQL_COLUMN_QUALIFIER_NAME* = 17
|
||||
SQL_COLUMN_LABEL* = 18
|
||||
SQL_COLATT_OPT_MAX* = SQL_COLUMN_LABEL
|
||||
SQL_COLUMN_DRIVER_START* = 1000
|
||||
SQL_DESC_ARRAY_SIZE* = 20
|
||||
SQL_DESC_ARRAY_STATUS_PTR* = 21
|
||||
SQL_DESC_AUTO_UNIQUE_VALUE* = SQL_COLUMN_AUTO_INCREMENT
|
||||
SQL_DESC_BASE_COLUMN_NAME* = 22
|
||||
SQL_DESC_BASE_TABLE_NAME* = 23
|
||||
SQL_DESC_BIND_OFFSET_PTR* = 24
|
||||
SQL_DESC_BIND_TYPE* = 25
|
||||
SQL_DESC_CASE_SENSITIVE* = SQL_COLUMN_CASE_SENSITIVE
|
||||
SQL_DESC_CATALOG_NAME* = SQL_COLUMN_QUALIFIER_NAME
|
||||
SQL_DESC_CONCISE_TYPE* = SQL_COLUMN_TYPE
|
||||
SQL_DESC_DATETIME_INTERVAL_PRECISION* = 26
|
||||
SQL_DESC_DISPLAY_SIZE* = SQL_COLUMN_DISPLAY_SIZE
|
||||
SQL_DESC_FIXED_PREC_SCALE* = SQL_COLUMN_MONEY
|
||||
SQL_DESC_LABEL* = SQL_COLUMN_LABEL
|
||||
SQL_DESC_LITERAL_PREFIX* = 27
|
||||
SQL_DESC_LITERAL_SUFFIX* = 28
|
||||
SQL_DESC_LOCAL_TYPE_NAME* = 29
|
||||
SQL_DESC_MAXIMUM_SCALE* = 30
|
||||
SQL_DESC_MINIMUM_SCALE* = 31
|
||||
SQL_DESC_NUM_PREC_RADIX* = 32
|
||||
SQL_DESC_PARAMETER_TYPE* = 33
|
||||
SQL_DESC_ROWS_PROCESSED_PTR* = 34
|
||||
SQL_DESC_SCHEMA_NAME* = SQL_COLUMN_OWNER_NAME
|
||||
SQL_DESC_SEARCHABLE* = SQL_COLUMN_SEARCHABLE
|
||||
SQL_DESC_TYPE_NAME* = SQL_COLUMN_TYPE_NAME
|
||||
SQL_DESC_TABLE_NAME* = SQL_COLUMN_TABLE_NAME
|
||||
SQL_DESC_UNSIGNED* = SQL_COLUMN_UNSIGNED
|
||||
SQL_DESC_UPDATABLE* = SQL_COLUMN_UPDATABLE #* SQLEndTran() options */
|
||||
SQL_COMMIT* = 0
|
||||
SQL_ROLLBACK* = 1
|
||||
SQL_ATTR_ROW_ARRAY_SIZE* = 27 #* SQLConfigDataSource() options */
|
||||
ODBC_ADD_DSN* = 1
|
||||
ODBC_CONFIG_DSN* = 2
|
||||
ODBC_REMOVE_DSN* = 3
|
||||
ODBC_ADD_SYS_DSN* = 4
|
||||
ODBC_CONFIG_SYS_DSN* = 5
|
||||
ODBC_REMOVE_SYS_DSN* = 6
|
||||
|
||||
SQL_ACTIVE_CONNECTIONS* = 0 # SQLGetInfo
|
||||
SQL_DATA_SOURCE_NAME* = 2
|
||||
SQL_DATA_SOURCE_READ_ONLY* = 25
|
||||
SQL_DATABASE_NAME* = 2
|
||||
SQL_DBMS_NAME* = 17
|
||||
SQL_DBMS_VERSION* = 18
|
||||
SQL_DRIVER_HDBC* = 3
|
||||
SQL_DRIVER_HENV* = 4
|
||||
SQL_DRIVER_HSTMT* = 5
|
||||
SQL_DRIVER_NAME* = 6
|
||||
SQL_DRIVER_VER* = 7
|
||||
SQL_FETCH_DIRECTION* = 8
|
||||
SQL_ODBC_VER* = 10
|
||||
SQL_DRIVER_ODBC_VER* = 77
|
||||
SQL_SERVER_NAME* = 13
|
||||
SQL_ACTIVE_ENVIRONMENTS* = 116
|
||||
SQL_ACTIVE_STATEMENTS* = 1
|
||||
SQL_SQL_CONFORMANCE* = 118
|
||||
SQL_DATETIME_LITERALS* = 119
|
||||
SQL_ASYNC_MODE* = 10021
|
||||
SQL_BATCH_ROW_COUNT* = 120
|
||||
SQL_BATCH_SUPPORT* = 121
|
||||
SQL_CATALOG_LOCATION* = 114
|
||||
#SQL_CATALOG_NAME* = 10003
|
||||
SQL_CATALOG_NAME_SEPARATOR* = 41
|
||||
SQL_CATALOG_TERM* = 42
|
||||
SQL_CATALOG_USAGE* = 92
|
||||
#SQL_COLLATION_SEQ* = 10004
|
||||
SQL_COLUMN_ALIAS* = 87
|
||||
#SQL_USER_NAME* = 47
|
||||
|
||||
proc SQLAllocHandle*(HandleType: TSqlSmallInt, InputHandle: SqlHandle,
|
||||
OutputHandlePtr: var SqlHandle): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, BufferLength: TSqlInteger,
|
||||
StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLFreeHandle*(HandleType: TSqlSmallInt, Handle: SqlHandle): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetDiagRec*(HandleType: TSqlSmallInt, Handle: SqlHandle,
|
||||
RecNumber: TSqlSmallInt, Sqlstate: PSQLCHAR,
|
||||
NativeError: var TSqlInteger, MessageText: PSQLCHAR,
|
||||
BufferLength: TSqlSmallInt, TextLength: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetDiagField*(HandleType: TSqlSmallInt, Handle: SqlHandle,
|
||||
RecNumber: TSqlSmallInt, DiagIdentifier: TSqlSmallInt,
|
||||
DiagInfoPtr: SqlPointer, BufferLength: TSqlSmallInt,
|
||||
StringLengthPtr: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLConnect*(ConnectionHandle: SqlHDBC, ServerName: PSQLCHAR,
|
||||
NameLength1: TSqlSmallInt, UserName: PSQLCHAR,
|
||||
NameLength2: TSqlSmallInt, Authentication: PSQLCHAR,
|
||||
NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLDisconnect*(ConnectionHandle: SqlHDBC): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLDriverConnect*(hdbc: SqlHDBC, hwnd: SqlHWND, szCsin: cstring,
|
||||
szCLen: TSqlSmallInt, szCsout: cstring,
|
||||
cbCSMax: TSqlSmallInt, cbCsOut: var TSqlSmallInt,
|
||||
f: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLBrowseConnect*(hdbc: SqlHDBC, szConnStrIn: PSQLCHAR,
|
||||
cbConnStrIn: TSqlSmallInt, szConnStrOut: PSQLCHAR,
|
||||
cbConnStrOutMax: TSqlSmallInt,
|
||||
cbConnStrOut: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLExecDirect*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
|
||||
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLExecDirectW*(StatementHandle: SqlHStmt, StatementText: WideCString,
|
||||
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLPrepare*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
|
||||
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLPrepareW*(StatementHandle: SqlHStmt, StatementText: WideCString,
|
||||
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLCloseCursor*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLExecute*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLFetch*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLNumResultCols*(StatementHandle: SqlHStmt, ColumnCount: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLDescribeCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
ColumnName: PSQLCHAR, BufferLength: TSqlSmallInt,
|
||||
NameLength: var TSqlSmallInt, DataType: var TSqlSmallInt,
|
||||
ColumnSize: var TSqlULen,
|
||||
DecimalDigits: var TSqlSmallInt, Nullable: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLFetchScroll*(StatementHandle: SqlHStmt, FetchOrientation: TSqlSmallInt,
|
||||
FetchOffset: TSqlLen): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLExtendedFetch*(hstmt: SqlHStmt, fFetchType: SqlUSmallInt,
|
||||
irow: TSqlLen, pcrow: var TSqlULen,
|
||||
rgfRowStatus: PSQLUSMALLINT): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLGetData*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
TargetType: TSqlSmallInt, TargetValue: SqlPointer,
|
||||
BufferLength: TSqlLen, StrLen_or_Ind: ptr TSqlLen): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, BufferLength: TSqlInteger,
|
||||
StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLGetInfo*(ConnectionHandle: SqlHDBC, InfoType: SqlUSmallInt,
|
||||
InfoValue: SqlPointer, BufferLength: TSqlSmallInt,
|
||||
StringLength: PSQLSMALLINT): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLBulkOperations*(StatementHandle: SqlHStmt, Operation: SqlUSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLPutData*(StatementHandle: SqlHStmt, Data: SqlPointer,
|
||||
StrLen_or_Ind: TSQLLEN): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLBindCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
TargetType: TSqlSmallInt, TargetValue: SqlPointer,
|
||||
BufferLength: TSqlLEN, StrLen_or_Ind: PSQLINTEGER): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetPos*(hstmt: SqlHStmt, irow: SqlUSmallInt, fOption: SqlUSmallInt,
|
||||
fLock: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLDataSources*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
|
||||
ServerName: PSQLCHAR, BufferLength1: TSqlSmallInt,
|
||||
NameLength1: PSQLSMALLINT, Description: PSQLCHAR,
|
||||
BufferLength2: TSqlSmallInt, NameLength2: PSQLSMALLINT): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLDrivers*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
|
||||
DriverDescription: PSQLCHAR, BufferLength1: TSqlSmallInt,
|
||||
DescriptionLength1: PSQLSMALLINT, DriverAttributes: PSQLCHAR,
|
||||
BufferLength2: TSqlSmallInt, AttributesLength2: PSQLSMALLINT): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetConnectAttr*(ConnectionHandle: SqlHDBC, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
|
||||
BufferLength: TSqlSmallInt, NameLength: PSQLSMALLINT): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
|
||||
NameLength: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLRowCount*(StatementHandle: SqlHStmt, RowCount: var TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLBindParameter*(hstmt: SqlHStmt, ipar: SqlUSmallInt,
|
||||
fParamType: TSqlSmallInt, fCType: TSqlSmallInt,
|
||||
fSqlType: TSqlSmallInt, cbColDef: TSQLULEN,
|
||||
ibScale: TSqlSmallInt, rgbValue: SqlPointer,
|
||||
cbValueMax: TSQLLEN, pcbValue: var TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLFreeStmt*(StatementHandle: SqlHStmt, Option: SqlUSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLColAttribute*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
FieldIdentifier: SqlUSmallInt,
|
||||
CharacterAttribute: PSQLCHAR, BufferLength: TSqlSmallInt,
|
||||
StringLength: PSQLSMALLINT,
|
||||
NumericAttribute: TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLEndTran*(HandleType: TSqlSmallInt, Handle: SqlHandle,
|
||||
CompletionType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLTables*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
|
||||
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
|
||||
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
|
||||
cbTableName: TSqlSmallInt, szTableType: PSQLCHAR,
|
||||
cbTableType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLColumns*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
|
||||
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
|
||||
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
|
||||
cbTableName: TSqlSmallInt, szColumnName: PSQLCHAR,
|
||||
cbColumnName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLSpecialColumns*(StatementHandle: SqlHStmt, IdentifierType: SqlUSmallInt,
|
||||
CatalogName: PSQLCHAR, NameLength1: TSqlSmallInt,
|
||||
SchemaName: PSQLCHAR, NameLength2: TSqlSmallInt,
|
||||
TableName: PSQLCHAR, NameLength3: TSqlSmallInt,
|
||||
Scope: SqlUSmallInt,
|
||||
Nullable: SqlUSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLProcedures*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
|
||||
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
|
||||
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
|
||||
cbTableName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLPrimaryKeys*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
|
||||
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
|
||||
NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
|
||||
NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLProcedureColumns*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
|
||||
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
|
||||
NameLength2: TSqlSmallInt, ProcName: PSQLCHAR,
|
||||
NameLength3: TSqlSmallInt, ColumnName: PSQLCHAR,
|
||||
NameLength4: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLStatistics*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
|
||||
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
|
||||
NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
|
||||
NameLength3: TSqlSmallInt, Unique: SqlUSmallInt,
|
||||
Reserved: SqlUSmallInt): TSqlSmallInt {.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLErr*(henv: SqlHEnv, hdbc: SqlHDBC, hstmt: SqlHStmt,
|
||||
szSqlState, pfNativeError, szErrorMsg: PSQLCHAR,
|
||||
cbErrorMsgMax: TSqlSmallInt,
|
||||
pcbErrorMsg: PSQLSMALLINT): TSqlSmallInt {.
|
||||
dynlib: odbclib, importc: "SQLError".}
|
||||
|
||||
{.pop.}
|
||||
when defined(nimHasStyleChecks):
|
||||
{.pop.}
|
||||
@@ -1,378 +0,0 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2015 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module contains the definitions for structures and externs for
|
||||
# functions used by frontend postgres applications. It is based on
|
||||
# Postgresql's libpq-fe.h.
|
||||
#
|
||||
# It is for postgreSQL version 7.4 and higher with support for the v3.0
|
||||
# connection-protocol.
|
||||
#
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
when defined(windows):
|
||||
const
|
||||
dllName = "libpq.dll"
|
||||
elif defined(macosx):
|
||||
const
|
||||
dllName = "libpq.dylib"
|
||||
else:
|
||||
const
|
||||
dllName = "libpq.so(.5|)"
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
type
|
||||
POid* = ptr Oid
|
||||
Oid* = int32
|
||||
|
||||
const
|
||||
ERROR_MSG_LENGTH* = 4096
|
||||
CMDSTATUS_LEN* = 40
|
||||
|
||||
type
|
||||
SockAddr* = array[1..112, int8]
|
||||
PGresAttDesc*{.pure, final.} = object
|
||||
name*: cstring
|
||||
adtid*: Oid
|
||||
adtsize*: int
|
||||
|
||||
PPGresAttDesc* = ptr PGresAttDesc
|
||||
PPPGresAttDesc* = ptr PPGresAttDesc
|
||||
PGresAttValue*{.pure, final.} = object
|
||||
length*: int32
|
||||
value*: cstring
|
||||
|
||||
PPGresAttValue* = ptr PGresAttValue
|
||||
PPPGresAttValue* = ptr PPGresAttValue
|
||||
PExecStatusType* = ptr ExecStatusType
|
||||
ExecStatusType* = enum
|
||||
PGRES_EMPTY_QUERY = 0, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PGRES_COPY_OUT,
|
||||
PGRES_COPY_IN, PGRES_BAD_RESPONSE, PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR,
|
||||
PGRES_COPY_BOTH, PGRES_SINGLE_TUPLE
|
||||
PGlobjfuncs*{.pure, final.} = object
|
||||
fn_lo_open*: Oid
|
||||
fn_lo_close*: Oid
|
||||
fn_lo_creat*: Oid
|
||||
fn_lo_unlink*: Oid
|
||||
fn_lo_lseek*: Oid
|
||||
fn_lo_tell*: Oid
|
||||
fn_lo_read*: Oid
|
||||
fn_lo_write*: Oid
|
||||
|
||||
PPGlobjfuncs* = ptr PGlobjfuncs
|
||||
PConnStatusType* = ptr ConnStatusType
|
||||
ConnStatusType* = enum
|
||||
CONNECTION_OK, CONNECTION_BAD, CONNECTION_STARTED, CONNECTION_MADE,
|
||||
CONNECTION_AWAITING_RESPONSE, CONNECTION_AUTH_OK, CONNECTION_SETENV,
|
||||
CONNECTION_SSL_STARTUP, CONNECTION_NEEDED, CONNECTION_CHECK_WRITABLE,
|
||||
CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_CHECK_TARGET
|
||||
PGconn*{.pure, final.} = object
|
||||
pghost*: cstring
|
||||
pgtty*: cstring
|
||||
pgport*: cstring
|
||||
pgoptions*: cstring
|
||||
dbName*: cstring
|
||||
status*: ConnStatusType
|
||||
errorMessage*: array[0..(ERROR_MSG_LENGTH) - 1, char]
|
||||
Pfin*: File
|
||||
Pfout*: File
|
||||
Pfdebug*: File
|
||||
sock*: int32
|
||||
laddr*: SockAddr
|
||||
raddr*: SockAddr
|
||||
salt*: array[0..(2) - 1, char]
|
||||
asyncNotifyWaiting*: int32
|
||||
notifyList*: pointer
|
||||
pguser*: cstring
|
||||
pgpass*: cstring
|
||||
lobjfuncs*: PPGlobjfuncs
|
||||
|
||||
PPGconn* = ptr PGconn
|
||||
PGresult*{.pure, final.} = object
|
||||
ntups*: int32
|
||||
numAttributes*: int32
|
||||
attDescs*: PPGresAttDesc
|
||||
tuples*: PPPGresAttValue
|
||||
tupArrSize*: int32
|
||||
resultStatus*: ExecStatusType
|
||||
cmdStatus*: array[0..(CMDSTATUS_LEN) - 1, char]
|
||||
binary*: int32
|
||||
conn*: PPGconn
|
||||
|
||||
PPGresult* = ptr PGresult
|
||||
PPostgresPollingStatusType* = ptr PostgresPollingStatusType
|
||||
PostgresPollingStatusType* = enum
|
||||
PGRES_POLLING_FAILED = 0, PGRES_POLLING_READING, PGRES_POLLING_WRITING,
|
||||
PGRES_POLLING_OK, PGRES_POLLING_ACTIVE
|
||||
PPGTransactionStatusType* = ptr PGTransactionStatusType
|
||||
PGTransactionStatusType* = enum
|
||||
PQTRANS_IDLE, PQTRANS_ACTIVE, PQTRANS_INTRANS, PQTRANS_INERROR,
|
||||
PQTRANS_UNKNOWN
|
||||
PPGVerbosity* = ptr PGVerbosity
|
||||
PGVerbosity* = enum
|
||||
PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE, PQERRORS_SQLSTATE
|
||||
PPGNotify* = ptr pgNotify
|
||||
pgNotify*{.pure, final.} = object
|
||||
relname*: cstring
|
||||
be_pid*: int32
|
||||
extra*: cstring
|
||||
|
||||
PQnoticeReceiver* = proc (arg: pointer, res: PPGresult){.cdecl.}
|
||||
PQnoticeProcessor* = proc (arg: pointer, message: cstring){.cdecl.}
|
||||
Ppqbool* = ptr pqbool
|
||||
pqbool* = char
|
||||
PPQprintOpt* = ptr PQprintOpt
|
||||
PQprintOpt*{.pure, final.} = object
|
||||
header*: pqbool
|
||||
align*: pqbool
|
||||
standard*: pqbool
|
||||
html3*: pqbool
|
||||
expanded*: pqbool
|
||||
pager*: pqbool
|
||||
fieldSep*: cstring
|
||||
tableOpt*: cstring
|
||||
caption*: cstring
|
||||
fieldName*: ptr cstring
|
||||
|
||||
PPQconninfoOption* = ptr PQconninfoOption
|
||||
PQconninfoOption*{.pure, final.} = object
|
||||
keyword*: cstring
|
||||
envvar*: cstring
|
||||
compiled*: cstring
|
||||
val*: cstring
|
||||
label*: cstring
|
||||
dispchar*: cstring
|
||||
dispsize*: int32
|
||||
|
||||
PPQArgBlock* = ptr PQArgBlock
|
||||
PQArgBlock*{.pure, final.} = object
|
||||
length*: int32
|
||||
isint*: int32
|
||||
p*: pointer
|
||||
|
||||
proc pqinitOpenSSL*(do_ssl: int32, do_crypto: int32) {.cdecl, dynlib: dllName,
|
||||
importc: "PQinitOpenSSL".}
|
||||
proc pqconnectStart*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
|
||||
importc: "PQconnectStart".}
|
||||
proc pqconnectPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
|
||||
dynlib: dllName, importc: "PQconnectPoll".}
|
||||
proc pqconnectdb*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
|
||||
importc: "PQconnectdb".}
|
||||
proc pqsetdbLogin*(pghost: cstring, pgport: cstring, pgoptions: cstring,
|
||||
pgtty: cstring, dbName: cstring, login: cstring, pwd: cstring): PPGconn{.
|
||||
cdecl, dynlib: dllName, importc: "PQsetdbLogin".}
|
||||
proc pqsetdb*(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn
|
||||
proc pqfinish*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQfinish".}
|
||||
proc pqconndefaults*(): PPQconninfoOption{.cdecl, dynlib: dllName,
|
||||
importc: "PQconndefaults".}
|
||||
proc pqconninfoFree*(connOptions: PPQconninfoOption){.cdecl, dynlib: dllName,
|
||||
importc: "PQconninfoFree".}
|
||||
proc pqresetStart*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQresetStart".}
|
||||
proc pqresetPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
|
||||
dynlib: dllName, importc: "PQresetPoll".}
|
||||
proc pqreset*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQreset".}
|
||||
proc pqrequestCancel*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQrequestCancel".}
|
||||
proc pqdb*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQdb".}
|
||||
proc pquser*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQuser".}
|
||||
proc pqpass*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQpass".}
|
||||
proc pqhost*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQhost".}
|
||||
proc pqport*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQport".}
|
||||
proc pqtty*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQtty".}
|
||||
proc pqoptions*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQoptions".}
|
||||
proc pqstatus*(conn: PPGconn): ConnStatusType{.cdecl, dynlib: dllName,
|
||||
importc: "PQstatus".}
|
||||
proc pqtransactionStatus*(conn: PPGconn): PGTransactionStatusType{.cdecl,
|
||||
dynlib: dllName, importc: "PQtransactionStatus".}
|
||||
proc pqparameterStatus*(conn: PPGconn, paramName: cstring): cstring{.cdecl,
|
||||
dynlib: dllName, importc: "PQparameterStatus".}
|
||||
proc pqserverVersion*(conn: PPGconn): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQserverVersion".}
|
||||
proc pqprotocolVersion*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQprotocolVersion".}
|
||||
proc pqerrorMessage*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQerrorMessage".}
|
||||
proc pqsocket*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQsocket".}
|
||||
proc pqbackendPID*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQbackendPID".}
|
||||
proc pqconnectionNeedsPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQconnectionNeedsPassword".}
|
||||
proc pqconnectionUsedPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQconnectionUsedPassword".}
|
||||
proc pqclientEncoding*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQclientEncoding".}
|
||||
proc pqsetClientEncoding*(conn: PPGconn, encoding: cstring): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQsetClientEncoding".}
|
||||
proc pqsetErrorVerbosity*(conn: PPGconn, verbosity: PGVerbosity): PGVerbosity{.
|
||||
cdecl, dynlib: dllName, importc: "PQsetErrorVerbosity".}
|
||||
proc pqtrace*(conn: PPGconn, debug_port: File){.cdecl, dynlib: dllName,
|
||||
importc: "PQtrace".}
|
||||
proc pquntrace*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQuntrace".}
|
||||
proc pqsetNoticeReceiver*(conn: PPGconn, theProc: PQnoticeReceiver, arg: pointer): PQnoticeReceiver{.
|
||||
cdecl, dynlib: dllName, importc: "PQsetNoticeReceiver".}
|
||||
proc pqsetNoticeProcessor*(conn: PPGconn, theProc: PQnoticeProcessor,
|
||||
arg: pointer): PQnoticeProcessor{.cdecl,
|
||||
dynlib: dllName, importc: "PQsetNoticeProcessor".}
|
||||
proc pqexec*(conn: PPGconn, query: cstring): PPGresult{.cdecl, dynlib: dllName,
|
||||
importc: "PQexec".}
|
||||
proc pqexecParams*(conn: PPGconn, command: cstring, nParams: int32,
|
||||
paramTypes: POid, paramValues: cstringArray,
|
||||
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
||||
cdecl, dynlib: dllName, importc: "PQexecParams".}
|
||||
proc pqprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
|
||||
paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
|
||||
proc pqexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
|
||||
paramValues: cstringArray,
|
||||
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
||||
cdecl, dynlib: dllName, importc: "PQexecPrepared".}
|
||||
proc pqsendQuery*(conn: PPGconn, query: cstring): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQsendQuery".}
|
||||
## See also https://www.postgresql.org/docs/current/libpq-async.html
|
||||
proc pqsendQueryParams*(conn: PPGconn, command: cstring, nParams: int32,
|
||||
paramTypes: POid, paramValues: cstringArray,
|
||||
paramLengths, paramFormats: ptr int32,
|
||||
resultFormat: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQsendQueryParams".}
|
||||
proc pqsendQueryPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
|
||||
paramValues: cstringArray,
|
||||
paramLengths, paramFormats: ptr int32,
|
||||
resultFormat: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQsendQueryPrepared".}
|
||||
proc pqSetSingleRowMode*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQsetSingleRowMode".}
|
||||
## See also https://www.postgresql.org/docs/current/libpq-single-row-mode.html
|
||||
proc pqgetResult*(conn: PPGconn): PPGresult{.cdecl, dynlib: dllName,
|
||||
importc: "PQgetResult".}
|
||||
proc pqisBusy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQisBusy".}
|
||||
proc pqconsumeInput*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQconsumeInput".}
|
||||
proc pqnotifies*(conn: PPGconn): PPGNotify{.cdecl, dynlib: dllName,
|
||||
importc: "PQnotifies".}
|
||||
proc pqputCopyData*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "PQputCopyData".}
|
||||
proc pqputCopyEnd*(conn: PPGconn, errormsg: cstring): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQputCopyEnd".}
|
||||
proc pqgetCopyData*(conn: PPGconn, buffer: cstringArray, async: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "PQgetCopyData".}
|
||||
proc pqgetline*(conn: PPGconn, str: cstring, len: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQgetline".}
|
||||
proc pqputline*(conn: PPGconn, str: cstring): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQputline".}
|
||||
proc pqgetlineAsync*(conn: PPGconn, buffer: cstring, bufsize: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "PQgetlineAsync".}
|
||||
proc pqputnbytes*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQputnbytes".}
|
||||
proc pqendcopy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQendcopy".}
|
||||
proc pqsetnonblocking*(conn: PPGconn, arg: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQsetnonblocking".}
|
||||
proc pqisnonblocking*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQisnonblocking".}
|
||||
proc pqflush*(conn: PPGconn): int32{.cdecl, dynlib: dllName, importc: "PQflush".}
|
||||
proc pqfn*(conn: PPGconn, fnid: int32, result_buf, result_len: ptr int32,
|
||||
result_is_int: int32, args: PPQArgBlock, nargs: int32): PPGresult{.
|
||||
cdecl, dynlib: dllName, importc: "PQfn".}
|
||||
proc pqresultStatus*(res: PPGresult): ExecStatusType{.cdecl, dynlib: dllName,
|
||||
importc: "PQresultStatus".}
|
||||
proc pqresStatus*(status: ExecStatusType): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQresStatus".}
|
||||
proc pqresultErrorMessage*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQresultErrorMessage".}
|
||||
proc pqresultErrorField*(res: PPGresult, fieldcode: int32): cstring{.cdecl,
|
||||
dynlib: dllName, importc: "PQresultErrorField".}
|
||||
proc pqntuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQntuples".}
|
||||
proc pqnfields*(res: PPGresult): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQnfields".}
|
||||
proc pqbinaryTuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQbinaryTuples".}
|
||||
proc pqfname*(res: PPGresult, field_num: int32): cstring{.cdecl,
|
||||
dynlib: dllName, importc: "PQfname".}
|
||||
proc pqfnumber*(res: PPGresult, field_name: cstring): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQfnumber".}
|
||||
proc pqftable*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
|
||||
importc: "PQftable".}
|
||||
proc pqftablecol*(res: PPGresult, field_num: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQftablecol".}
|
||||
proc pqfformat*(res: PPGresult, field_num: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "PQfformat".}
|
||||
proc pqftype*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
|
||||
importc: "PQftype".}
|
||||
proc pqfsize*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQfsize".}
|
||||
proc pqfmod*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQfmod".}
|
||||
proc pqcmdStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQcmdStatus".}
|
||||
proc pqoidStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQoidStatus".}
|
||||
proc pqoidValue*(res: PPGresult): Oid{.cdecl, dynlib: dllName,
|
||||
importc: "PQoidValue".}
|
||||
proc pqcmdTuples*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
|
||||
importc: "PQcmdTuples".}
|
||||
proc pqgetvalue*(res: PPGresult, tup_num: int32, field_num: int32): cstring{.
|
||||
cdecl, dynlib: dllName, importc: "PQgetvalue".}
|
||||
proc pqgetlength*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "PQgetlength".}
|
||||
proc pqgetisnull*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "PQgetisnull".}
|
||||
proc pqclear*(res: PPGresult){.cdecl, dynlib: dllName, importc: "PQclear".}
|
||||
proc pqfreemem*(p: pointer){.cdecl, dynlib: dllName, importc: "PQfreemem".}
|
||||
proc pqmakeEmptyPGresult*(conn: PPGconn, status: ExecStatusType): PPGresult{.
|
||||
cdecl, dynlib: dllName, importc: "PQmakeEmptyPGresult".}
|
||||
proc pqescapeString*(till, `from`: cstring, len: int): int{.cdecl,
|
||||
dynlib: dllName, importc: "PQescapeString".}
|
||||
proc pqescapeBytea*(bintext: cstring, binlen: int, bytealen: var int): cstring{.
|
||||
cdecl, dynlib: dllName, importc: "PQescapeBytea".}
|
||||
proc pqunescapeBytea*(strtext: cstring, retbuflen: var int): cstring{.cdecl,
|
||||
dynlib: dllName, importc: "PQunescapeBytea".}
|
||||
proc pqprint*(fout: File, res: PPGresult, ps: PPQprintOpt){.cdecl,
|
||||
dynlib: dllName, importc: "PQprint".}
|
||||
proc pqdisplayTuples*(res: PPGresult, fp: File, fillAlign: int32,
|
||||
fieldSep: cstring, printHeader: int32, quiet: int32){.
|
||||
cdecl, dynlib: dllName, importc: "PQdisplayTuples".}
|
||||
proc pqprintTuples*(res: PPGresult, fout: File, printAttName: int32,
|
||||
terseOutput: int32, width: int32){.cdecl, dynlib: dllName,
|
||||
importc: "PQprintTuples".}
|
||||
proc lo_open*(conn: PPGconn, lobjId: Oid, mode: int32): int32{.cdecl,
|
||||
dynlib: dllName, importc: "lo_open".}
|
||||
proc lo_close*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "lo_close".}
|
||||
proc lo_read*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
|
||||
cdecl, dynlib: dllName, importc: "lo_read".}
|
||||
proc lo_write*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
|
||||
cdecl, dynlib: dllName, importc: "lo_write".}
|
||||
proc lo_lseek*(conn: PPGconn, fd: int32, offset: int32, whence: int32): int32{.
|
||||
cdecl, dynlib: dllName, importc: "lo_lseek".}
|
||||
proc lo_creat*(conn: PPGconn, mode: int32): Oid{.cdecl, dynlib: dllName,
|
||||
importc: "lo_creat".}
|
||||
proc lo_tell*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "lo_tell".}
|
||||
proc lo_unlink*(conn: PPGconn, lobjId: Oid): int32{.cdecl, dynlib: dllName,
|
||||
importc: "lo_unlink".}
|
||||
proc lo_import*(conn: PPGconn, filename: cstring): Oid{.cdecl, dynlib: dllName,
|
||||
importc: "lo_import".}
|
||||
proc lo_export*(conn: PPGconn, lobjId: Oid, filename: cstring): int32{.cdecl,
|
||||
dynlib: dllName, importc: "lo_export".}
|
||||
proc pqmblen*(s: cstring, encoding: int32): int32{.cdecl, dynlib: dllName,
|
||||
importc: "PQmblen".}
|
||||
proc pqenv2encoding*(): int32{.cdecl, dynlib: dllName, importc: "PQenv2encoding".}
|
||||
proc pqsetdb(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn =
|
||||
result = pqsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, "", "")
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.pop.}
|
||||
@@ -1,392 +0,0 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
when defined(windows):
|
||||
when defined(nimOldDlls):
|
||||
const Lib = "sqlite3.dll"
|
||||
elif defined(cpu64):
|
||||
const Lib = "sqlite3_64.dll"
|
||||
else:
|
||||
const Lib = "sqlite3_32.dll"
|
||||
elif defined(macosx):
|
||||
const
|
||||
Lib = "libsqlite3(|.0).dylib"
|
||||
else:
|
||||
const
|
||||
Lib = "libsqlite3.so(|.0)"
|
||||
|
||||
when defined(staticSqlite):
|
||||
{.pragma: mylib.}
|
||||
{.compile("sqlite3.c", "-O3").}
|
||||
else:
|
||||
{.pragma: mylib, dynlib: Lib.}
|
||||
|
||||
const
|
||||
SQLITE_INTEGER* = 1
|
||||
SQLITE_FLOAT* = 2
|
||||
SQLITE_BLOB* = 4
|
||||
SQLITE_NULL* = 5
|
||||
SQLITE_TEXT* = 3
|
||||
SQLITE_UTF8* = 1
|
||||
SQLITE_UTF16LE* = 2
|
||||
SQLITE_UTF16BE* = 3 # Use native byte order
|
||||
SQLITE_UTF16* = 4 # sqlite3_create_function only
|
||||
SQLITE_ANY* = 5 #sqlite_exec return values
|
||||
SQLITE_OK* = 0
|
||||
SQLITE_ERROR* = 1 # SQL error or missing database
|
||||
SQLITE_INTERNAL* = 2 # An internal logic error in SQLite
|
||||
SQLITE_PERM* = 3 # Access permission denied
|
||||
SQLITE_ABORT* = 4 # Callback routine requested an abort
|
||||
SQLITE_BUSY* = 5 # The database file is locked
|
||||
SQLITE_LOCKED* = 6 # A table in the database is locked
|
||||
SQLITE_NOMEM* = 7 # A malloc() failed
|
||||
SQLITE_READONLY* = 8 # Attempt to write a readonly database
|
||||
SQLITE_INTERRUPT* = 9 # Operation terminated by sqlite3_interrupt()
|
||||
SQLITE_IOERR* = 10 # Some kind of disk I/O error occurred
|
||||
SQLITE_CORRUPT* = 11 # The database disk image is malformed
|
||||
SQLITE_NOTFOUND* = 12 # (Internal Only) Table or record not found
|
||||
SQLITE_FULL* = 13 # Insertion failed because database is full
|
||||
SQLITE_CANTOPEN* = 14 # Unable to open the database file
|
||||
SQLITE_PROTOCOL* = 15 # Database lock protocol error
|
||||
SQLITE_EMPTY* = 16 # Database is empty
|
||||
SQLITE_SCHEMA* = 17 # The database schema changed
|
||||
SQLITE_TOOBIG* = 18 # Too much data for one row of a table
|
||||
SQLITE_CONSTRAINT* = 19 # Abort due to constraint violation
|
||||
SQLITE_MISMATCH* = 20 # Data type mismatch
|
||||
SQLITE_MISUSE* = 21 # Library used incorrectly
|
||||
SQLITE_NOLFS* = 22 # Uses OS features not supported on host
|
||||
SQLITE_AUTH* = 23 # Authorization denied
|
||||
SQLITE_FORMAT* = 24 # Auxiliary database format error
|
||||
SQLITE_RANGE* = 25 # 2nd parameter to sqlite3_bind out of range
|
||||
SQLITE_NOTADB* = 26 # File opened that is not a database file
|
||||
SQLITE_ROW* = 100 # sqlite3_step() has another row ready
|
||||
SQLITE_DONE* = 101 # sqlite3_step() has finished executing
|
||||
SQLITE_COPY* = 0
|
||||
SQLITE_CREATE_INDEX* = 1
|
||||
SQLITE_CREATE_TABLE* = 2
|
||||
SQLITE_CREATE_TEMP_INDEX* = 3
|
||||
SQLITE_CREATE_TEMP_TABLE* = 4
|
||||
SQLITE_CREATE_TEMP_TRIGGER* = 5
|
||||
SQLITE_CREATE_TEMP_VIEW* = 6
|
||||
SQLITE_CREATE_TRIGGER* = 7
|
||||
SQLITE_CREATE_VIEW* = 8
|
||||
SQLITE_DELETE* = 9
|
||||
SQLITE_DROP_INDEX* = 10
|
||||
SQLITE_DROP_TABLE* = 11
|
||||
SQLITE_DROP_TEMP_INDEX* = 12
|
||||
SQLITE_DROP_TEMP_TABLE* = 13
|
||||
SQLITE_DROP_TEMP_TRIGGER* = 14
|
||||
SQLITE_DROP_TEMP_VIEW* = 15
|
||||
SQLITE_DROP_TRIGGER* = 16
|
||||
SQLITE_DROP_VIEW* = 17
|
||||
SQLITE_INSERT* = 18
|
||||
SQLITE_PRAGMA* = 19
|
||||
SQLITE_READ* = 20
|
||||
SQLITE_SELECT* = 21
|
||||
SQLITE_TRANSACTION* = 22
|
||||
SQLITE_UPDATE* = 23
|
||||
SQLITE_ATTACH* = 24
|
||||
SQLITE_DETACH* = 25
|
||||
SQLITE_ALTER_TABLE* = 26
|
||||
SQLITE_REINDEX* = 27
|
||||
SQLITE_DENY* = 1
|
||||
SQLITE_IGNORE* = 2 # Original from sqlite3.h:
|
||||
#define SQLITE_STATIC ((void(*)(void *))0)
|
||||
#define SQLITE_TRANSIENT ((void(*)(void *))-1)
|
||||
SQLITE_DETERMINISTIC* = 0x800
|
||||
|
||||
type
|
||||
Sqlite3 {.pure, final.} = object
|
||||
PSqlite3* = ptr Sqlite3
|
||||
PPSqlite3* = ptr PSqlite3
|
||||
Sqlite3_Backup {.pure, final.} = object
|
||||
PSqlite3_Backup* = ptr Sqlite3_Backup
|
||||
PPSqlite3_Backup* = ptr PSqlite3_Backup
|
||||
Context{.pure, final.} = object
|
||||
Pcontext* = ptr Context
|
||||
TStmt{.pure, final.} = object
|
||||
PStmt* = ptr TStmt
|
||||
Value{.pure, final.} = object
|
||||
PValue* = ptr Value
|
||||
PValueArg* = array[0..127, PValue]
|
||||
|
||||
Callback* = proc (para1: pointer, para2: int32, para3,
|
||||
para4: cstringArray): int32{.cdecl.}
|
||||
Tbind_destructor_func* = proc (para1: pointer){.cdecl, tags: [], gcsafe.}
|
||||
Create_function_step_func* = proc (para1: Pcontext, para2: int32,
|
||||
para3: PValueArg){.cdecl.}
|
||||
Create_function_func_func* = proc (para1: Pcontext, para2: int32,
|
||||
para3: PValueArg){.cdecl.}
|
||||
Create_function_final_func* = proc (para1: Pcontext){.cdecl.}
|
||||
Result_func* = proc (para1: pointer){.cdecl.}
|
||||
Create_collation_func* = proc (para1: pointer, para2: int32, para3: pointer,
|
||||
para4: int32, para5: pointer): int32{.cdecl.}
|
||||
Collation_needed_func* = proc (para1: pointer, para2: PSqlite3, eTextRep: int32,
|
||||
para4: cstring){.cdecl.}
|
||||
|
||||
const
|
||||
SQLITE_STATIC* = nil
|
||||
SQLITE_TRANSIENT* = cast[Tbind_destructor_func](-1)
|
||||
|
||||
proc close*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_close".}
|
||||
proc exec*(para1: PSqlite3, sql: cstring, para3: Callback, para4: pointer,
|
||||
errmsg: var cstring): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_exec".}
|
||||
proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, mylib,
|
||||
importc: "sqlite3_last_insert_rowid".}
|
||||
proc changes*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_changes".}
|
||||
proc total_changes*(para1: PSqlite3): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_total_changes".}
|
||||
proc interrupt*(para1: PSqlite3){.cdecl, mylib, importc: "sqlite3_interrupt".}
|
||||
proc complete*(sql: cstring): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_complete".}
|
||||
proc complete16*(sql: pointer): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_complete16".}
|
||||
proc busy_handler*(para1: PSqlite3,
|
||||
para2: proc (para1: pointer, para2: int32): int32{.cdecl.},
|
||||
para3: pointer): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_busy_handler".}
|
||||
proc busy_timeout*(para1: PSqlite3, ms: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_busy_timeout".}
|
||||
proc get_table*(para1: PSqlite3, sql: cstring, resultp: var cstringArray,
|
||||
nrow, ncolumn: var cint, errmsg: ptr cstring): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_get_table".}
|
||||
proc free_table*(result: cstringArray){.cdecl, mylib,
|
||||
importc: "sqlite3_free_table".}
|
||||
# Todo: see how translate sqlite3_mprintf, sqlite3_vmprintf, sqlite3_snprintf
|
||||
# function sqlite3_mprintf(_para1:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_mprintf';
|
||||
proc mprintf*(para1: cstring): cstring{.cdecl, varargs, mylib,
|
||||
importc: "sqlite3_mprintf".}
|
||||
#function sqlite3_vmprintf(_para1:Pchar; _para2:va_list):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_vmprintf';
|
||||
proc free*(z: cstring){.cdecl, mylib, importc: "sqlite3_free".}
|
||||
#function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_snprintf';
|
||||
proc snprintf*(para1: int32, para2: cstring, para3: cstring): cstring{.cdecl,
|
||||
mylib, varargs, importc: "sqlite3_snprintf".}
|
||||
proc set_authorizer*(para1: PSqlite3, xAuth: proc (para1: pointer, para2: int32,
|
||||
para3: cstring, para4: cstring, para5: cstring, para6: cstring): int32{.
|
||||
cdecl.}, pUserData: pointer): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_set_authorizer".}
|
||||
proc trace*(para1: PSqlite3, xTrace: proc (para1: pointer, para2: cstring){.cdecl.},
|
||||
para3: pointer): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_trace".}
|
||||
proc progress_handler*(para1: PSqlite3, para2: int32,
|
||||
para3: proc (para1: pointer): int32{.cdecl.},
|
||||
para4: pointer){.cdecl, mylib,
|
||||
importc: "sqlite3_progress_handler".}
|
||||
proc commit_hook*(para1: PSqlite3, para2: proc (para1: pointer): int32{.cdecl.},
|
||||
para3: pointer): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_commit_hook".}
|
||||
proc open*(filename: cstring, ppDb: var PSqlite3): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_open".}
|
||||
proc open16*(filename: pointer, ppDb: var PSqlite3): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_open16".}
|
||||
proc errcode*(db: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_errcode".}
|
||||
proc errmsg*(para1: PSqlite3): cstring{.cdecl, mylib, importc: "sqlite3_errmsg".}
|
||||
proc errmsg16*(para1: PSqlite3): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_errmsg16".}
|
||||
proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var PStmt,
|
||||
pzTail: ptr cstring): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_prepare".}
|
||||
|
||||
proc prepare_v2*(db: PSqlite3, zSql: cstring, nByte: cint, ppStmt: var PStmt,
|
||||
pzTail: ptr cstring): cint {.
|
||||
importc: "sqlite3_prepare_v2", cdecl, mylib.}
|
||||
|
||||
proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var PStmt,
|
||||
pzTail: var pointer): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_prepare16".}
|
||||
proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
|
||||
para5: Tbind_destructor_func): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_blob".}
|
||||
proc bind_double*(para1: PStmt, para2: int32, para3: float64): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_bind_double".}
|
||||
proc bind_int*(para1: PStmt, para2: int32, para3: int32): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_bind_int".}
|
||||
proc bind_int64*(para1: PStmt, para2: int32, para3: int64): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_bind_int64".}
|
||||
proc bind_null*(para1: PStmt, para2: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_null".}
|
||||
proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
|
||||
para5: Tbind_destructor_func): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_text".}
|
||||
proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
|
||||
para5: Tbind_destructor_func): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_text16".}
|
||||
#function sqlite3_bind_value(_para1:Psqlite3_stmt; _para2:longint; _para3:Psqlite3_value):longint;cdecl; external Sqlite3Lib name 'sqlite3_bind_value';
|
||||
#These overloaded functions were introduced to allow the use of SQLITE_STATIC and SQLITE_TRANSIENT
|
||||
#It's the c world man ;-)
|
||||
proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
|
||||
para5: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_blob".}
|
||||
proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
|
||||
para5: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_text".}
|
||||
proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
|
||||
para5: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_text16".}
|
||||
proc bind_parameter_count*(para1: PStmt): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_bind_parameter_count".}
|
||||
proc bind_parameter_name*(para1: PStmt, para2: int32): cstring{.cdecl,
|
||||
mylib, importc: "sqlite3_bind_parameter_name".}
|
||||
proc bind_parameter_index*(para1: PStmt, zName: cstring): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_bind_parameter_index".}
|
||||
proc clear_bindings*(para1: PStmt): int32 {.cdecl,
|
||||
mylib, importc: "sqlite3_clear_bindings".}
|
||||
proc column_count*(PStmt: PStmt): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_column_count".}
|
||||
proc column_name*(para1: PStmt, para2: int32): cstring{.cdecl, mylib,
|
||||
importc: "sqlite3_column_name".}
|
||||
proc column_table_name*(para1: PStmt; para2: int32): cstring{.cdecl, mylib,
|
||||
importc: "sqlite3_column_table_name".}
|
||||
proc column_name16*(para1: PStmt, para2: int32): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_column_name16".}
|
||||
proc column_decltype*(para1: PStmt, i: int32): cstring{.cdecl, mylib,
|
||||
importc: "sqlite3_column_decltype".}
|
||||
proc column_decltype16*(para1: PStmt, para2: int32): pointer{.cdecl,
|
||||
mylib, importc: "sqlite3_column_decltype16".}
|
||||
proc step*(para1: PStmt): int32{.cdecl, mylib, importc: "sqlite3_step".}
|
||||
proc data_count*(PStmt: PStmt): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_data_count".}
|
||||
proc column_blob*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_column_blob".}
|
||||
proc column_bytes*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_column_bytes".}
|
||||
proc column_bytes16*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_column_bytes16".}
|
||||
proc column_double*(para1: PStmt, iCol: int32): float64{.cdecl, mylib,
|
||||
importc: "sqlite3_column_double".}
|
||||
proc column_int*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_column_int".}
|
||||
proc column_int64*(para1: PStmt, iCol: int32): int64{.cdecl, mylib,
|
||||
importc: "sqlite3_column_int64".}
|
||||
proc column_text*(para1: PStmt, iCol: int32): cstring{.cdecl, mylib,
|
||||
importc: "sqlite3_column_text".}
|
||||
proc column_text16*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_column_text16".}
|
||||
proc column_type*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_column_type".}
|
||||
proc finalize*(PStmt: PStmt): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_finalize".}
|
||||
proc reset*(PStmt: PStmt): int32{.cdecl, mylib, importc: "sqlite3_reset".}
|
||||
proc create_function*(para1: PSqlite3, zFunctionName: cstring, nArg: int32,
|
||||
eTextRep: int32, para5: pointer,
|
||||
xFunc: Create_function_func_func,
|
||||
xStep: Create_function_step_func,
|
||||
xFinal: Create_function_final_func): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_create_function".}
|
||||
proc create_function16*(para1: PSqlite3, zFunctionName: pointer, nArg: int32,
|
||||
eTextRep: int32, para5: pointer,
|
||||
xFunc: Create_function_func_func,
|
||||
xStep: Create_function_step_func,
|
||||
xFinal: Create_function_final_func): int32{.cdecl,
|
||||
mylib, importc: "sqlite3_create_function16".}
|
||||
proc aggregate_count*(para1: Pcontext): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_aggregate_count".}
|
||||
proc value_blob*(para1: PValue): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_value_blob".}
|
||||
proc value_bytes*(para1: PValue): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_value_bytes".}
|
||||
proc value_bytes16*(para1: PValue): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_value_bytes16".}
|
||||
proc value_double*(para1: PValue): float64{.cdecl, mylib,
|
||||
importc: "sqlite3_value_double".}
|
||||
proc value_int*(para1: PValue): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_value_int".}
|
||||
proc value_int64*(para1: PValue): int64{.cdecl, mylib,
|
||||
importc: "sqlite3_value_int64".}
|
||||
proc value_text*(para1: PValue): cstring{.cdecl, mylib,
|
||||
importc: "sqlite3_value_text".}
|
||||
proc value_text16*(para1: PValue): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_value_text16".}
|
||||
proc value_text16le*(para1: PValue): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_value_text16le".}
|
||||
proc value_text16be*(para1: PValue): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_value_text16be".}
|
||||
proc value_type*(para1: PValue): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_value_type".}
|
||||
proc aggregate_context*(para1: Pcontext, nBytes: int32): pointer{.cdecl,
|
||||
mylib, importc: "sqlite3_aggregate_context".}
|
||||
proc user_data*(para1: Pcontext): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_user_data".}
|
||||
proc get_auxdata*(para1: Pcontext, para2: int32): pointer{.cdecl, mylib,
|
||||
importc: "sqlite3_get_auxdata".}
|
||||
proc set_auxdata*(para1: Pcontext, para2: int32, para3: pointer,
|
||||
para4: proc (para1: pointer){.cdecl.}){.cdecl, mylib,
|
||||
importc: "sqlite3_set_auxdata".}
|
||||
proc result_blob*(para1: Pcontext, para2: pointer, para3: int32,
|
||||
para4: Result_func){.cdecl, mylib,
|
||||
importc: "sqlite3_result_blob".}
|
||||
proc result_double*(para1: Pcontext, para2: float64){.cdecl, mylib,
|
||||
importc: "sqlite3_result_double".}
|
||||
proc result_error*(para1: Pcontext, para2: cstring, para3: int32){.cdecl,
|
||||
mylib, importc: "sqlite3_result_error".}
|
||||
proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl,
|
||||
mylib, importc: "sqlite3_result_error16".}
|
||||
proc result_int*(para1: Pcontext, para2: int32){.cdecl, mylib,
|
||||
importc: "sqlite3_result_int".}
|
||||
proc result_int64*(para1: Pcontext, para2: int64){.cdecl, mylib,
|
||||
importc: "sqlite3_result_int64".}
|
||||
proc result_null*(para1: Pcontext){.cdecl, mylib,
|
||||
importc: "sqlite3_result_null".}
|
||||
proc result_text*(para1: Pcontext, para2: cstring, para3: int32,
|
||||
para4: Result_func){.cdecl, mylib,
|
||||
importc: "sqlite3_result_text".}
|
||||
proc result_text16*(para1: Pcontext, para2: pointer, para3: int32,
|
||||
para4: Result_func){.cdecl, mylib,
|
||||
importc: "sqlite3_result_text16".}
|
||||
proc result_text16le*(para1: Pcontext, para2: pointer, para3: int32,
|
||||
para4: Result_func){.cdecl, mylib,
|
||||
importc: "sqlite3_result_text16le".}
|
||||
proc result_text16be*(para1: Pcontext, para2: pointer, para3: int32,
|
||||
para4: Result_func){.cdecl, mylib,
|
||||
importc: "sqlite3_result_text16be".}
|
||||
proc result_value*(para1: Pcontext, para2: PValue){.cdecl, mylib,
|
||||
importc: "sqlite3_result_value".}
|
||||
proc create_collation*(para1: PSqlite3, zName: cstring, eTextRep: int32,
|
||||
para4: pointer, xCompare: Create_collation_func): int32{.
|
||||
cdecl, mylib, importc: "sqlite3_create_collation".}
|
||||
proc create_collation16*(para1: PSqlite3, zName: cstring, eTextRep: int32,
|
||||
para4: pointer, xCompare: Create_collation_func): int32{.
|
||||
cdecl, mylib, importc: "sqlite3_create_collation16".}
|
||||
proc collation_needed*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
|
||||
cdecl, mylib, importc: "sqlite3_collation_needed".}
|
||||
proc collation_needed16*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
|
||||
cdecl, mylib, importc: "sqlite3_collation_needed16".}
|
||||
proc libversion*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
|
||||
#Alias for allowing better code portability (win32 is not working with external variables)
|
||||
proc version*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
|
||||
# Not published functions
|
||||
proc libversion_number*(): int32{.cdecl, mylib,
|
||||
importc: "sqlite3_libversion_number".}
|
||||
|
||||
proc backup_init*(pDest: PSqlite3, zDestName: cstring, pSource: PSqlite3, zSourceName: cstring): PSqlite3_Backup {.
|
||||
cdecl, mylib, importc: "sqlite3_backup_init".}
|
||||
|
||||
proc backup_step*(pBackup: PSqlite3_Backup, nPage: int32): int32 {.cdecl, mylib, importc: "sqlite3_backup_step".}
|
||||
|
||||
proc backup_finish*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_finish".}
|
||||
|
||||
proc backup_pagecount*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_pagecount".}
|
||||
|
||||
proc backup_remaining*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_remaining".}
|
||||
|
||||
proc sqlite3_sleep*(t: int64): int64 {.cdecl, mylib, importc: "sqlite3_sleep".}
|
||||
|
||||
#function sqlite3_key(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_key';
|
||||
#function sqlite3_rekey(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_rekey';
|
||||
#function sqlite3_sleep(_para1:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_sleep';
|
||||
#function sqlite3_expired(_para1:Psqlite3_stmt):longint;cdecl; external Sqlite3Lib name 'sqlite3_expired';
|
||||
#function sqlite3_global_recover:longint;cdecl; external Sqlite3Lib name 'sqlite3_global_recover';
|
||||
# implementation
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.pop.}
|
||||
@@ -116,7 +116,8 @@
|
||||
|
||||
</ul>
|
||||
<ul class="simple nested-toc-section">bar
|
||||
<li><a class="reference" href="#bar%2CT%2CT" title="bar[T](a, b: T): T">bar[T](a, b: T): T</a></li>
|
||||
<li><a class="reference" href="#bar" title="bar(f: FooBuzz)">bar(f: FooBuzz)</a></li>
|
||||
<li><a class="reference" href="#bar%2CT%2CT" title="bar[T](a, b: T): T">bar[T](a, b: T): T</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="simple nested-toc-section">baz
|
||||
@@ -539,7 +540,15 @@
|
||||
|
||||
</div>
|
||||
<div id="bar-procs-all">
|
||||
<div id="bar,T,T">
|
||||
<div id="bar">
|
||||
<dt><pre><span class="Keyword">proc</span> <a href="#bar"><span class="Identifier">bar</span></a><span class="Other">(</span><span class="Identifier">f</span><span class="Other">:</span> <a href="testproject.html#FooBuzz"><span class="Identifier">FooBuzz</span></a><span class="Other">)</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
|
||||
<dd>
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</div>
|
||||
<div id="bar,T,T">
|
||||
<dt><pre><span class="Keyword">proc</span> <a href="#bar%2CT%2CT"><span class="Identifier">bar</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">a</span><span class="Other">,</span> <span class="Identifier">b</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">T</span></pre></dt>
|
||||
<dd>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ bar testproject.html#bar,T,T testproject: bar[T](a, b: T): T
|
||||
baz testproject.html#baz,T,T testproject: baz[T](a, b: T): T
|
||||
buzz testproject.html#buzz,T,T testproject: buzz[T](a, b: T): T
|
||||
FooBuzz testproject.html#FooBuzz testproject: FooBuzz
|
||||
bar testproject.html#bar testproject: bar(f: FooBuzz)
|
||||
aVariable testproject.html#aVariable testproject: aVariable
|
||||
A testproject.html#A testproject: A
|
||||
B testproject.html#B testproject: B
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
</ul></dd>
|
||||
<dt><a name="bar" href="#bar"><span>bar:</span></a></dt><dd><ul class="simple">
|
||||
<li><a class="reference external"
|
||||
data-doc-search-tag="testproject: bar(f: FooBuzz)" href="testproject.html#bar">testproject: bar(f: FooBuzz)</a></li>
|
||||
<li><a class="reference external"
|
||||
data-doc-search-tag="testproject: bar[T](a, b: T): T" href="testproject.html#bar%2CT%2CT">testproject: bar[T](a, b: T): T</a></li>
|
||||
<li><a class="reference external"
|
||||
data-doc-search-tag="testproject: bar(): untyped" href="testproject.html#bar.m">testproject: bar(): untyped</a></li>
|
||||
|
||||
@@ -42,6 +42,11 @@ proc buzz*[T](a, b: T): T {.deprecated: "since v0.20".} =
|
||||
type
|
||||
FooBuzz* {.deprecated: "FooBuzz msg".} = int
|
||||
|
||||
using f: FooBuzz
|
||||
|
||||
proc bar*(f) = # `f` should be expanded to `f: FooBuzz`
|
||||
discard
|
||||
|
||||
import std/macros
|
||||
|
||||
var aVariable*: array[1, int]
|
||||
|
||||
@@ -27,7 +27,7 @@ import compiler / [options, commands, modules, sem,
|
||||
passes, passaux, msgs,
|
||||
sigmatch, ast,
|
||||
idents, modulegraphs, prefixmatches, lineinfos, cmdlinehelper,
|
||||
pathutils]
|
||||
pathutils, condsyms]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/typedthreads
|
||||
@@ -553,6 +553,7 @@ proc mainCommand(graph: ModuleGraph) =
|
||||
registerPass graph, verbosePass
|
||||
registerPass graph, semPass
|
||||
conf.setCmd cmdIdeTools
|
||||
defineSymbol(conf.symbols, $conf.backend)
|
||||
wantMainModule(conf)
|
||||
|
||||
if not fileExists(conf.projectFull):
|
||||
@@ -952,10 +953,12 @@ else:
|
||||
proc mockCommand(graph: ModuleGraph) =
|
||||
retval = graph
|
||||
let conf = graph.config
|
||||
conf.setCmd cmdIdeTools
|
||||
defineSymbol(conf.symbols, $conf.backend)
|
||||
clearPasses(graph)
|
||||
registerPass graph, verbosePass
|
||||
registerPass graph, semPass
|
||||
conf.setCmd cmdIdeTools
|
||||
|
||||
wantMainModule(conf)
|
||||
|
||||
if not fileExists(conf.projectFull):
|
||||
|
||||
7
nimsuggest/tests/t20440.nim
Normal file
7
nimsuggest/tests/t20440.nim
Normal file
@@ -0,0 +1,7 @@
|
||||
when not defined(js):
|
||||
{.fatal: "Crash".}
|
||||
echo 4
|
||||
|
||||
discard """
|
||||
$nimsuggest --v3 --tester $file
|
||||
"""
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user