mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 11:23:40 +00:00
Compare commits
4 Commits
pr_remove_
...
pr_ungedul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b36dc53bf2 | ||
|
|
8e7afb6bd6 | ||
|
|
3aeea1f014 | ||
|
|
591168002a |
11
.github/workflows/bisects.yml
vendored
11
.github/workflows/bisects.yml
vendored
@@ -15,16 +15,9 @@ jobs:
|
||||
name: ${{ matrix.platform }}-bisects
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install OpenSSL (Windows)
|
||||
if: |
|
||||
runner.os == 'Windows'
|
||||
run: choco install openssl.light --version=1.1.1.0 # OpenSSL 3.x removed SSL_library_init
|
||||
shell: 'powershell'
|
||||
|
||||
# v2 wont work here, because uses "hardcoded" nim versions, action "dynamically" finds version with bug.
|
||||
- uses: jiro4989/setup-nim-action@v1
|
||||
- uses: jiro4989/setup-nim-action@v1
|
||||
with:
|
||||
nim-version: 'devel'
|
||||
|
||||
|
||||
2
.github/workflows/ci_docs.yml
vendored
2
.github/workflows/ci_docs.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
- target: windows
|
||||
os: windows-latest
|
||||
- target: osx
|
||||
os: macos-15
|
||||
os: macos-13
|
||||
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
14
.github/workflows/ci_packages.yml
vendored
14
.github/workflows/ci_packages.yml
vendored
@@ -18,13 +18,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-14]
|
||||
os: [ubuntu-22.04, macos-13]
|
||||
cpu: [amd64]
|
||||
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cpu: amd64
|
||||
- os: macos-14
|
||||
cpu: arm64
|
||||
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60 # refs bug #18178
|
||||
@@ -45,11 +41,11 @@ jobs:
|
||||
- name: 'Install dependencies (Linux amd64)'
|
||||
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-fast update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
sudo apt-get install --no-install-recommends -yq \
|
||||
sudo apt-fast install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
|
||||
valgrind libc6-dbg libblas-dev liblapack-dev libpcre3 xorg-dev
|
||||
valgrind libc6-dbg libblas-dev xorg-dev
|
||||
- name: 'Install dependencies (macOS)'
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install boehmgc make sfml gtk+3
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -68,7 +68,6 @@ testament.db
|
||||
/csources
|
||||
/csources_v1
|
||||
/csources_v2
|
||||
/csources_v3
|
||||
|
||||
/dist/
|
||||
# /lib/fusion # fusion is now unbundled; `git status` should reveal if it's there so users can act on it
|
||||
|
||||
@@ -28,12 +28,12 @@ jobs:
|
||||
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
|
||||
# vmImage: 'ubuntu-18.04'
|
||||
# CPU: i386
|
||||
OSX_arm64:
|
||||
vmImage: 'macos-15'
|
||||
CPU: arm64
|
||||
OSX_arm64_cpp:
|
||||
vmImage: 'macos-15'
|
||||
CPU: arm64
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-13'
|
||||
CPU: amd64
|
||||
OSX_amd64_cpp:
|
||||
vmImage: 'macOS-13'
|
||||
CPU: amd64
|
||||
NIM_COMPILE_TO_CPP: true
|
||||
Windows_amd64_batch0_3:
|
||||
vmImage: 'windows-2025'
|
||||
|
||||
18
changelog.md
18
changelog.md
@@ -23,16 +23,6 @@ errors.
|
||||
|
||||
- With `-d:nimPreviewCStringComparisons`, comparsions (`<`, `>`, `<=`, `>=`) between cstrings switch from reference semantics to value semantics like `==` and `!=`.
|
||||
|
||||
- `std/parsesql` has been moved to a nimble package, use `nimble` or `atlas` to install it.
|
||||
|
||||
- With `-d:nimPreviewDuplicateModuleError`, importing two modules that share the same name becomes a compile-time error. This includes importing the same module more than once. Use `import foo as foo1` (or other aliases) to avoid collisions.
|
||||
|
||||
- Adds the switch `--mangle:nim|cpp`, which selects `nim` or `cpp` style name mangling when used with `debuginfo` on, defaults to `cpp`.
|
||||
|
||||
- The second parameter of `succ`, `pred`, `inc`, and `dec` in `system` now accepts `SomeInteger` (previously `Ordinal`).
|
||||
|
||||
- Bitshift operators (`shl`, `shr`, `ashr`) now apply bitmasking to the right operand in the C/C++/VM/JS backends.
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Additions:"
|
||||
@@ -105,15 +95,7 @@ errors.
|
||||
|
||||
## Compiler changes
|
||||
|
||||
- Fixed a bug where `sizeof(T)` inside a `typedesc` template called from a generic type's
|
||||
`when` clause would error with "'sizeof' requires '.importc' types to be '.completeStruct'".
|
||||
The issue was that `hasValuelessStatics` in `semtypinst.nim` didn't recognize
|
||||
`tyTypeDesc(tyGenericParam)` as an unresolved generic parameter.
|
||||
|
||||
## Tool changes
|
||||
|
||||
- Added `--stdinfile` flag to name of the file used when running program from stdin (defaults to `stdinfile.nim`)
|
||||
|
||||
## Documentation changes
|
||||
|
||||
- Added documentation for the `completeStruct` pragma in the manual.
|
||||
|
||||
1766
compiler/ast.nim
1766
compiler/ast.nim
File diff suppressed because it is too large
Load Diff
1681
compiler/ast2nif.nim
1681
compiler/ast2nif.nim
File diff suppressed because it is too large
Load Diff
@@ -68,6 +68,8 @@ template mdbg*: bool {.deprecated.} =
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc lookupInRecord*(n: PNode, field: PIdent): PSym
|
||||
proc mustRehash*(length, counter: int): bool
|
||||
proc nextTry*(h, maxHash: Hash): Hash {.inline.}
|
||||
|
||||
# ------------- table[int, int] ---------------------------------------------
|
||||
const
|
||||
@@ -214,6 +216,10 @@ proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
|
||||
proc hashNode(p: RootRef): Hash =
|
||||
result = hash(cast[pointer](p))
|
||||
|
||||
proc mustRehash(length, counter: int): bool =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
import std/tables
|
||||
|
||||
const backrefStyle = "\e[90m"
|
||||
@@ -478,6 +484,12 @@ proc debug(n: PNode; conf: ConfigRef) =
|
||||
this.value(n)
|
||||
echo($this.res)
|
||||
|
||||
proc nextTry(h, maxHash: Hash): Hash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
# For any initial h in range(maxHash), repeating that maxHash times
|
||||
# generates each int in range(maxHash) exactly once (see any text on
|
||||
# random-number generation for proof).
|
||||
|
||||
proc objectSetContains*(t: TObjectSet, obj: RootRef): bool =
|
||||
# returns true whether n is in t
|
||||
var h: Hash = hashNode(obj) and high(t.data) # start with real hash value
|
||||
@@ -525,6 +537,95 @@ proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool =
|
||||
inc(t.counter)
|
||||
result = false
|
||||
|
||||
proc strTableContains*(t: TStrTable, n: PSym): bool =
|
||||
var h: Hash = n.name.h and high(t.data) # start with real hash value
|
||||
while t.data[h] != nil:
|
||||
if (t.data[h] == n):
|
||||
return true
|
||||
h = nextTry(h, high(t.data))
|
||||
result = false
|
||||
|
||||
proc strTableRawInsert(data: var seq[PSym], n: PSym) =
|
||||
var h: Hash = n.name.h and high(data)
|
||||
while data[h] != nil:
|
||||
if data[h] == n:
|
||||
# allowed for 'export' feature:
|
||||
#InternalError(n.info, "StrTableRawInsert: " & n.name.s)
|
||||
return
|
||||
h = nextTry(h, high(data))
|
||||
assert(data[h] == nil)
|
||||
data[h] = n
|
||||
|
||||
proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) =
|
||||
assert prevSym.name.h == newSym.name.h
|
||||
var h: Hash = prevSym.name.h and high(data)
|
||||
while data[h] != nil:
|
||||
if data[h] == prevSym:
|
||||
data[h] = newSym
|
||||
return
|
||||
h = nextTry(h, high(data))
|
||||
assert false
|
||||
|
||||
proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
|
||||
symTabReplaceRaw(t.data, prevSym, newSym)
|
||||
|
||||
proc strTableEnlarge(t: var TStrTable) =
|
||||
var n: seq[PSym]
|
||||
newSeq(n, t.data.len * GrowthFactor)
|
||||
for i in 0..high(t.data):
|
||||
if t.data[i] != nil: strTableRawInsert(n, t.data[i])
|
||||
swap(t.data, n)
|
||||
|
||||
proc strTableAdd*(t: var TStrTable, n: PSym) =
|
||||
if mustRehash(t.data.len, t.counter): strTableEnlarge(t)
|
||||
strTableRawInsert(t.data, n)
|
||||
inc(t.counter)
|
||||
|
||||
proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
|
||||
onConflictKeepOld = false): PSym =
|
||||
# if `t` has a conflicting symbol (same identifier as `n`), return it
|
||||
# otherwise return `nil`. Incl `n` to `t` unless `onConflictKeepOld = true`
|
||||
# and a conflict was found.
|
||||
assert n.name != nil
|
||||
var h: Hash = n.name.h and high(t.data)
|
||||
var replaceSlot = -1
|
||||
while true:
|
||||
var it = t.data[h]
|
||||
if it == nil: break
|
||||
# Semantic checking can happen multiple times thanks to templates
|
||||
# and overloading: (var x=@[]; x).mapIt(it).
|
||||
# So it is possible the very same sym is added multiple
|
||||
# times to the symbol table which we allow here with the 'it == n' check.
|
||||
if it.name.id == n.name.id:
|
||||
if it == n: return nil
|
||||
replaceSlot = h
|
||||
h = nextTry(h, high(t.data))
|
||||
if replaceSlot >= 0:
|
||||
result = t.data[replaceSlot] # found it
|
||||
if not onConflictKeepOld:
|
||||
t.data[replaceSlot] = n # overwrite it with newer definition!
|
||||
return result # but return the old one
|
||||
elif mustRehash(t.data.len, t.counter):
|
||||
strTableEnlarge(t)
|
||||
strTableRawInsert(t.data, n)
|
||||
else:
|
||||
assert(t.data[h] == nil)
|
||||
t.data[h] = n
|
||||
inc(t.counter)
|
||||
result = nil
|
||||
|
||||
proc strTableIncl*(t: var TStrTable, n: PSym;
|
||||
onConflictKeepOld = false): bool {.discardable.} =
|
||||
result = strTableInclReportConflict(t, n, onConflictKeepOld) != nil
|
||||
|
||||
proc strTableGet*(t: TStrTable, name: PIdent): PSym =
|
||||
var h: Hash = name.h and high(t.data)
|
||||
while true:
|
||||
result = t.data[h]
|
||||
if result == nil: break
|
||||
if result.name.id == name.id: break
|
||||
h = nextTry(h, high(t.data))
|
||||
|
||||
|
||||
type
|
||||
TIdentIter* = object # iterator over all syms with same identifier
|
||||
|
||||
1160
compiler/astdef.nim
1160
compiler/astdef.nim
File diff suppressed because it is too large
Load Diff
@@ -154,14 +154,14 @@ template addField(builder: var Builder, constr: var StructInitializer, name: str
|
||||
# no name, can just add value
|
||||
valueBody
|
||||
of siOrderedStruct:
|
||||
# positional init - name not used in output (empty allowed for anonymous unions)
|
||||
# no name, can just add value on C
|
||||
assert name.len != 0, "name has to be given for struct initializer field"
|
||||
valueBody
|
||||
of siNamedStruct:
|
||||
# designated init - empty name for anonymous unions (skips .name = prefix)
|
||||
if name.len != 0:
|
||||
builder.add(".")
|
||||
builder.add(name)
|
||||
builder.add(" = ")
|
||||
assert name.len != 0, "name has to be given for struct initializer field"
|
||||
builder.add(".")
|
||||
builder.add(name)
|
||||
builder.add(" = ")
|
||||
valueBody
|
||||
|
||||
proc finishStructInitializer(builder: var Builder, constr: StructInitializer) =
|
||||
|
||||
@@ -368,8 +368,8 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Builder; n
|
||||
# variable. Thus, we create a temporary pointer variable instead.
|
||||
let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray
|
||||
if needsIndirect:
|
||||
n.typ = n.typ.exactReplica
|
||||
n.typ.incl tfVarIsPtr
|
||||
n.typ() = n.typ.exactReplica
|
||||
n.typ.flags.incl tfVarIsPtr
|
||||
a = initLocExprSingleUse(p, n)
|
||||
a = withTmpIfNeeded(p, a, needsTmp)
|
||||
if needsIndirect: a.flags.incl lfIndirect
|
||||
@@ -498,7 +498,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
else:
|
||||
cCall(p, params, e)
|
||||
cIfExpr(e,
|
||||
eCall,
|
||||
eCall,
|
||||
cCall(cCast(pTyp, p), params))
|
||||
|
||||
template callIter(rp, params: Snippet): Snippet =
|
||||
|
||||
@@ -170,7 +170,7 @@ proc canMove(p: BProc, n: PNode; dest: TLoc): bool =
|
||||
template simpleAsgn(builder: var Builder, dest, src: TLoc) =
|
||||
let rd = rdLoc(dest)
|
||||
let rs = rdLoc(src)
|
||||
builder.addAssignment(rd, rs)
|
||||
builder.addAssignment(rd, rs)
|
||||
|
||||
proc genRefAssign(p: BProc, dest, src: TLoc) =
|
||||
if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config):
|
||||
@@ -675,7 +675,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
if e[2].kind in {nkIntLit..nkInt64Lit}:
|
||||
needsOverflowCheck = e[2].intVal == -1
|
||||
if canBeZero:
|
||||
# remove extra paren from `==` op here to avoid Wparentheses-equality:
|
||||
# remove extra paren from `==` op here to avoid Wparentheses-equality:
|
||||
p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, rdLoc(b), cIntValue(0)))):
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseDivByZero"))
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
@@ -696,7 +696,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
let ra = rdLoc(a)
|
||||
if optOverflowCheck in p.options:
|
||||
let first = cIntLiteral(firstOrd(p.config, t))
|
||||
# remove extra paren from `==` op here to avoid Wparentheses-equality:
|
||||
# remove extra paren from `==` op here to avoid Wparentheses-equality:
|
||||
p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, ra, first))):
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseOverflow"))
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
@@ -749,16 +749,16 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
let t = getType()
|
||||
let at = cUintType(k)
|
||||
let bt = cUintType(s)
|
||||
res = cCast(t, cOp(Shr, at, cCast(at, ra), cOp(BitAnd, at, cCast(bt, rb), cIntLiteral(k - 1))))
|
||||
res = cCast(t, cOp(Shr, at, cCast(at, ra), cCast(bt, rb)))
|
||||
of mShlI:
|
||||
let t = getType()
|
||||
let at = cUintType(s)
|
||||
res = cCast(t, cOp(Shl, at, cCast(at, ra), cOp(BitAnd, at, cCast(at, rb), cIntLiteral(k - 1))))
|
||||
res = cCast(t, cOp(Shl, at, cCast(at, ra), cCast(at, rb)))
|
||||
of mAshrI:
|
||||
let t = getType()
|
||||
let at = cIntType(s)
|
||||
let bt = cUintType(s)
|
||||
res = cCast(t, cOp(Shr, at, cCast(at, ra), cOp(BitAnd, at, cCast(bt, rb), cIntLiteral(k - 1))))
|
||||
res = cCast(t, cOp(Shr, at, cCast(at, ra), cCast(bt, rb)))
|
||||
of mBitandI:
|
||||
let t = getType()
|
||||
res = cCast(t, cOp(BitAnd, t, ra, rb))
|
||||
@@ -919,10 +919,6 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
return
|
||||
else:
|
||||
a = initLocExprSingleUse(p, e[0])
|
||||
|
||||
if e.typ != nil and e.typ.kind == tyObject:
|
||||
# bug #23453 #25265
|
||||
discard getTypeDesc(p.module, e.typ)
|
||||
if d.k == locNone:
|
||||
# dest = *a; <-- We do not know that 'dest' is on the heap!
|
||||
# It is completely wrong to set 'd.storage' here, unless it's not yet
|
||||
@@ -1006,7 +1002,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
i: int = 0
|
||||
var a: TLoc = initLocExpr(p, e[0])
|
||||
let tupType = a.t.skipTypes(abstractInst+{tyVar}+tyUserTypeClasses) # ref #25227
|
||||
let tupType = a.t.skipTypes(abstractInst+{tyVar})
|
||||
assert tupType.kind == tyTuple
|
||||
d.inheritLocation(a)
|
||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||
@@ -1916,7 +1912,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
var elem, arr: TLoc
|
||||
if n[1].kind == nkBracket:
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
genSeqConstr(p, n[1], d)
|
||||
return
|
||||
if d.k == locNone:
|
||||
@@ -3363,9 +3359,8 @@ proc genConstSetup(p: BProc; sym: PSym): bool =
|
||||
useHeader(m, sym)
|
||||
if sym.loc.k == locNone:
|
||||
fillBackendName(p.module, sym)
|
||||
backendEnsureMutable sym
|
||||
fillLoc(sym.locImpl, locData, sym.astdef, OnStatic)
|
||||
if m.hcrOn: incl(sym, lfIndirect)
|
||||
fillLoc(sym.loc, locData, sym.astdef, OnStatic)
|
||||
if m.hcrOn: incl(sym.loc.flags, lfIndirect)
|
||||
result = lfNoDecl notin sym.loc.flags
|
||||
|
||||
proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) =
|
||||
@@ -3435,7 +3430,7 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
|
||||
|
||||
proc genConstStmt(p: BProc, n: PNode) =
|
||||
# This code is only used in the new DCE implementation.
|
||||
assert delayedCodegen(p.module)
|
||||
assert useAliveDataFromDce in p.module.flags
|
||||
let m = p.module
|
||||
for it in n:
|
||||
if it[0].kind == nkSym:
|
||||
@@ -3453,7 +3448,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var sym = n.sym
|
||||
case sym.kind
|
||||
of skMethod:
|
||||
if delayedCodegen(p.module) or {sfDispatcher, sfForward} * sym.flags != {}:
|
||||
if useAliveDataFromDce in p.module.flags or {sfDispatcher, sfForward} * sym.flags != {}:
|
||||
# we cannot produce code for the dispatcher yet:
|
||||
fillProcLoc(p.module, n)
|
||||
genProcPrototype(p.module, sym)
|
||||
@@ -3466,15 +3461,11 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
if sfCompileTime in sym.flags:
|
||||
localError(p.config, n.info, "request to generate code for .compileTime proc: " &
|
||||
sym.name.s)
|
||||
if delayedCodegen(p.module) and sym.typ.callConv != ccInline:
|
||||
if useAliveDataFromDce in p.module.flags and sym.typ.callConv != ccInline:
|
||||
fillProcLoc(p.module, n)
|
||||
genProcPrototype(p.module, sym)
|
||||
else:
|
||||
genProc(p.module, sym)
|
||||
# For cross-module inline procs with optCompress, ensure prototype is emitted
|
||||
if sym.typ.callConv == ccInline and optCompress in p.config.globalOptions and
|
||||
sym.itemId.module != p.module.module.position:
|
||||
genProcPrototype(p.module, sym)
|
||||
if sym.loc.snippet == "" or sym.loc.lode == nil:
|
||||
internalError(p.config, n.info, "expr: proc not init " & sym.name.s)
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
@@ -3483,13 +3474,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var lit = newBuilder("")
|
||||
genLiteral(p, sym.astdef, sym.typ, lit)
|
||||
putIntoDest(p, d, n, extract(lit), OnStatic)
|
||||
elif optCompress in p.config.globalOptions:
|
||||
# With delayed codegen, we need to ensure the definition is generated
|
||||
# not just the extern header declaration
|
||||
requestConstImpl(p, sym)
|
||||
assert((sym.loc.snippet != "") and (sym.loc.t != nil))
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
elif delayedCodegen(p.module):
|
||||
elif useAliveDataFromDce in p.module.flags:
|
||||
genConstHeader(p.module, p.module, p, sym)
|
||||
assert((sym.loc.snippet != "") and (sym.loc.t != nil))
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
@@ -3621,7 +3606,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkWhileStmt: genWhileStmt(p, n)
|
||||
of nkVarSection, nkLetSection: genVarStmt(p, n)
|
||||
of nkConstSection:
|
||||
if delayedCodegen(p.module):
|
||||
if useAliveDataFromDce in p.module.flags:
|
||||
genConstStmt(p, n)
|
||||
else: # enforce addressable consts for exportc
|
||||
let m = p.module
|
||||
@@ -3687,10 +3672,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
|
||||
if n[genericParamsPos].kind == nkEmpty:
|
||||
var prc = n[namePos].sym
|
||||
if optCompress in p.config.globalOptions:
|
||||
if prc.magic in generatedMagics:
|
||||
genProc(p.module, prc)
|
||||
elif delayedCodegen(p.module):
|
||||
if useAliveDataFromDce in p.module.flags:
|
||||
if p.module.alive.contains(prc.itemId.item) and
|
||||
prc.magic in generatedMagics:
|
||||
genProc(p.module, prc)
|
||||
@@ -3710,67 +3692,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
inc p.splitDecls
|
||||
genGotoState(p, n)
|
||||
of nkBreakState: genBreakState(p, n, d)
|
||||
of nkMixinStmt, nkBindStmt, nkReplayAction: discard
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
||||
|
||||
proc isOpaqueImportcType(t: PType): bool =
|
||||
# importc type without completeStruct that can't use aggregate init (e.g. C11 _Atomic)
|
||||
if t.sym != nil and sfImportc in t.sym.flags:
|
||||
if tfCompleteStruct notin t.flags:
|
||||
if tfIncompleteStruct in t.flags:
|
||||
return true
|
||||
if t.kind == tyObject and (t.n == nil or t.n.len == 0):
|
||||
return true
|
||||
return false
|
||||
|
||||
proc containsOpaqueImportcField(typ: PType): bool
|
||||
|
||||
proc containsOpaqueImportcFieldAux(t: PType; n: PNode): bool =
|
||||
if n == nil: return false
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for child in n.sons:
|
||||
if containsOpaqueImportcFieldAux(t, child):
|
||||
return true
|
||||
of nkRecCase:
|
||||
if containsOpaqueImportcFieldAux(t, n[0]):
|
||||
return true
|
||||
for i in 1..<n.len:
|
||||
let branch = n[i]
|
||||
if branch.kind == nkOfBranch or branch.kind == nkElse:
|
||||
if containsOpaqueImportcFieldAux(t, branch.lastSon):
|
||||
return true
|
||||
of nkSym:
|
||||
if containsOpaqueImportcField(n.sym.typ):
|
||||
return true
|
||||
else:
|
||||
discard
|
||||
return false
|
||||
|
||||
proc containsOpaqueImportcField(typ: PType): bool =
|
||||
# Check if type contains opaque importc fields that need designated initializers
|
||||
if typ == nil: return false
|
||||
let t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
if isOpaqueImportcType(t):
|
||||
return true
|
||||
case t.kind
|
||||
of tyObject:
|
||||
if t.baseClass != nil:
|
||||
if containsOpaqueImportcField(t.baseClass):
|
||||
return true
|
||||
if containsOpaqueImportcFieldAux(t, t.n):
|
||||
return true
|
||||
of tyTuple:
|
||||
for i, a in t.ikids:
|
||||
if containsOpaqueImportcField(a):
|
||||
return true
|
||||
of tyArray:
|
||||
if containsOpaqueImportcField(t.elementType):
|
||||
return true
|
||||
else:
|
||||
discard
|
||||
return false
|
||||
|
||||
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Builder) =
|
||||
var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
case t.kind
|
||||
@@ -3801,34 +3725,24 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Builder)
|
||||
result.addField(closureInit, name = "ClE_0"):
|
||||
result.add(NimNil)
|
||||
of tyObject:
|
||||
# Use designated initializers when opaque importc fields present
|
||||
var objInit: StructInitializer
|
||||
let initKind = if containsOpaqueImportcField(t): siNamedStruct else: siOrderedStruct
|
||||
result.addStructInitializer(objInit, kind = initKind):
|
||||
result.addStructInitializer(objInit, kind = siOrderedStruct):
|
||||
getNullValueAuxT(p, t, t, t.n, nil, result, objInit, true, info)
|
||||
of tyTuple:
|
||||
# Use designated initializers when opaque importc fields present
|
||||
var tupleInit: StructInitializer
|
||||
let initKind = if containsOpaqueImportcField(t): siNamedStruct else: siOrderedStruct
|
||||
result.addStructInitializer(tupleInit, kind = initKind):
|
||||
result.addStructInitializer(tupleInit, kind = siOrderedStruct):
|
||||
if p.vccAndC and t.isEmptyTupleType:
|
||||
result.addField(tupleInit, name = "dummy"):
|
||||
result.addIntValue(0)
|
||||
for i, a in t.ikids:
|
||||
let elemTyp = skipTypes(a, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
if not isOpaqueImportcType(elemTyp):
|
||||
result.addField(tupleInit, name = "Field" & $i):
|
||||
getDefaultValue(p, a, info, result)
|
||||
result.addField(tupleInit, name = "Field" & $i):
|
||||
getDefaultValue(p, a, info, result)
|
||||
of tyArray:
|
||||
let elemTyp = skipTypes(t.elementType, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
if isOpaqueImportcType(elemTyp):
|
||||
result.add "{0}"
|
||||
else:
|
||||
var arrInit: StructInitializer
|
||||
result.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<toInt(lengthOrd(p.config, t.indexType)):
|
||||
result.addField(arrInit, name = ""):
|
||||
getDefaultValue(p, t.elementType, info, result)
|
||||
var arrInit: StructInitializer
|
||||
result.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<toInt(lengthOrd(p.config, t.indexType)):
|
||||
result.addField(arrInit, name = ""):
|
||||
getDefaultValue(p, t.elementType, info, result)
|
||||
#result = rope"{}"
|
||||
of tyOpenArray, tyVarargs:
|
||||
var openArrInit: StructInitializer
|
||||
@@ -3883,7 +3797,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
var fieldName: string = ""
|
||||
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
|
||||
fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch
|
||||
result.addField(init, name = ""): # anonymous union
|
||||
result.addField(init, name = "<anonymous union>"):
|
||||
# XXX figure out name for the union, see use of `addAnonUnion`
|
||||
var branchInit: StructInitializer
|
||||
result.addStructInitializer(branchInit, kind = siNamedStruct):
|
||||
result.addField(branchInit, name = fieldName):
|
||||
@@ -3892,7 +3807,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info)
|
||||
elif b.kind == nkSym:
|
||||
fieldName = mangleRecFieldName(p.module, b.sym)
|
||||
result.addField(init, name = ""): # anonymous union
|
||||
result.addField(init, name = "<anonymous union>"):
|
||||
# XXX figure out name for the union, see use of `addAnonUnion`
|
||||
var branchInit: StructInitializer
|
||||
result.addStructInitializer(branchInit, kind = siNamedStruct):
|
||||
result.addField(branchInit, name = fieldName):
|
||||
@@ -3907,9 +3823,6 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
|
||||
of nkSym:
|
||||
let field = obj.sym
|
||||
let fieldTyp = skipTypes(field.typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
if isOpaqueImportcType(fieldTyp):
|
||||
return # C zero-initializes omitted fields
|
||||
let sname = mangleRecFieldName(p.module, field)
|
||||
result.addField(init, name = sname):
|
||||
block fieldInit:
|
||||
@@ -3954,10 +3867,11 @@ proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
|
||||
|
||||
proc genConstObjConstr(p: BProc; n: PNode; isConst: bool; result: var Builder) =
|
||||
let t = n.typ.skipTypes(abstractInstOwned)
|
||||
# Use designated initializers when opaque importc fields present
|
||||
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||
# result.addf("{$1}", [genTypeInfo(p.module, t)])
|
||||
# inc count
|
||||
var objInit: StructInitializer
|
||||
let initKind = if t.kind == tyObject and containsOpaqueImportcField(t): siNamedStruct else: siOrderedStruct
|
||||
result.addStructInitializer(objInit, kind = initKind):
|
||||
result.addStructInitializer(objInit, kind = siOrderedStruct):
|
||||
if t.kind == tyObject:
|
||||
getNullValueAuxT(p, t, t, t.n, n, result, objInit, isConst, n.info)
|
||||
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
## implementation.
|
||||
|
||||
template detectVersion(field, corename) =
|
||||
if m.g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc, gcHooks}:
|
||||
result = 2
|
||||
else:
|
||||
result = 1
|
||||
if m.g.field == 0:
|
||||
let core = getCompilerProc(m.g.graph, corename)
|
||||
if core == nil or core.kind != skConst:
|
||||
m.g.field = 1
|
||||
else:
|
||||
m.g.field = toInt(ast.getInt(core.astdef))
|
||||
result = m.g.field
|
||||
|
||||
proc detectStrVersion(m: BModule): int =
|
||||
detectVersion(strVersion, "nimStrVersion")
|
||||
|
||||
@@ -67,14 +67,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
|
||||
var x = typ.baseClass
|
||||
if x != nil: x = x.skipTypes(skipPtrs)
|
||||
specializeResetT(p, accessor.parentObj(p.module), x)
|
||||
if typ.n != nil:
|
||||
if typ.sym != nil and sfImportc in typ.sym.flags:
|
||||
# imported C struct, nimZeroMem
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimZeroMem"),
|
||||
cCast(ptrType(CPointer), cAddr(accessor)),
|
||||
cSizeof(getTypeDesc(p.module, typ)))
|
||||
else:
|
||||
specializeResetN(p, accessor, typ.n, typ)
|
||||
if typ.n != nil: specializeResetN(p, accessor, typ.n, typ)
|
||||
of tyTuple:
|
||||
let typ = getUniqueType(typ)
|
||||
for i, a in typ.ikids:
|
||||
|
||||
@@ -126,26 +126,25 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
let vn = n[i]
|
||||
let v = vn.sym
|
||||
if sfCompileTime in v.flags: continue
|
||||
backendEnsureMutable v
|
||||
if sfGlobal in v.flags:
|
||||
assignGlobalVar(p, vn, "")
|
||||
genObjectInit(p, cpsInit, v.typ, v.locImpl, constructObj)
|
||||
genObjectInit(p, cpsInit, v.typ, v.loc, constructObj)
|
||||
registerTraverseProc(p, v)
|
||||
else:
|
||||
assignLocalVar(p, vn)
|
||||
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
|
||||
var field = initLoc(locExpr, vn, tup.storage)
|
||||
let rtup = rdLoc(tup)
|
||||
let fieldName =
|
||||
let fieldName =
|
||||
if t.kind == tyTuple:
|
||||
"Field" & $i
|
||||
else:
|
||||
if t.n[i].kind != nkSym: internalError(p.config, n.info, "genVarTuple")
|
||||
mangleRecFieldName(p.module, t.n[i].sym)
|
||||
field.snippet = dotField(rtup, fieldName)
|
||||
putLocIntoDest(p, v.locImpl, field)
|
||||
putLocIntoDest(p, v.loc, field)
|
||||
if forHcr or isGlobalInBlock:
|
||||
hcrGlobals.add((loc: v.locImpl, tp: CNil))
|
||||
hcrGlobals.add((loc: v.loc, tp: CNil))
|
||||
|
||||
if forHcr:
|
||||
# end the block where the tuple gets initialized
|
||||
@@ -226,7 +225,7 @@ proc genState(p: BProc, n: PNode) =
|
||||
elif n0.kind == nkStrLit:
|
||||
p.s(cpsStmts).addLabel(n0.strVal)
|
||||
|
||||
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int, isReturnStmt = false) =
|
||||
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
# Called by return and break stmts.
|
||||
# Deals with issues faced when jumping out of try/except/finally stmts.
|
||||
|
||||
@@ -258,7 +257,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int, isReturnStmt
|
||||
|
||||
# Pop exceptions that was handled by the
|
||||
# except-blocks we are in
|
||||
if noSafePoints notin p.flags and not (isReturnStmt and isClosureIterator(p.prc.typ)):
|
||||
if noSafePoints notin p.flags:
|
||||
for i in countdown(howManyExcepts-1, 0):
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "popCurrentException"))
|
||||
|
||||
@@ -366,7 +365,6 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||
value.kind == nkEmpty and
|
||||
v.loc.flags * {lfHeader, lfNoDecl} != {}:
|
||||
# IC XXX: this is bad, we should set v.loc regardless here
|
||||
return
|
||||
if sfPure in v.flags:
|
||||
# v.owner.kind != skModule:
|
||||
@@ -462,8 +460,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
if value.kind != nkEmpty and valueAsRope.len == 0:
|
||||
genLineDir(targetProc, vn)
|
||||
if not isCppCtorCall:
|
||||
backendEnsureMutable v
|
||||
loadInto(targetProc, vn, value, v.locImpl)
|
||||
loadInto(targetProc, vn, value, v.loc)
|
||||
if forHcr:
|
||||
endBlockWith(targetProc):
|
||||
finishBranch(p.s(cpsStmts), hcrInit)
|
||||
@@ -490,17 +487,14 @@ proc genClosureVar(p: BProc, a: PNode) =
|
||||
constructLoc(p, v)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
for it in n:
|
||||
case it.kind
|
||||
of nkCommentStmt: discard
|
||||
of nkIdentDefs:
|
||||
for it in n.sons:
|
||||
if it.kind == nkCommentStmt: continue
|
||||
if it.kind == nkIdentDefs:
|
||||
# can be a lifted var nowadays ...
|
||||
if it[0].kind == nkSym:
|
||||
genSingleVar(p, it)
|
||||
else:
|
||||
genClosureVar(p, it)
|
||||
of nkSym:
|
||||
genSingleVar(p, it.sym, newSymNode(it.sym), it.sym.astdef)
|
||||
else:
|
||||
genVarTuple(p, it)
|
||||
|
||||
@@ -560,8 +554,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||
if (t[0].kind != nkEmpty): genStmts(p, t[0])
|
||||
blockLeaveActions(p,
|
||||
howManyTrys = p.nestedTryStmts.len,
|
||||
howManyExcepts = p.inExceptBlockLen,
|
||||
isReturnStmt = true)
|
||||
howManyExcepts = p.inExceptBlockLen)
|
||||
if (p.finallySafePoints.len > 0) and noSafePoints notin p.flags:
|
||||
# If we're in a finally block, and we came here by exception
|
||||
# consume it before we return.
|
||||
@@ -743,10 +736,8 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
||||
# named block?
|
||||
assert(n[0].kind == nkSym)
|
||||
var sym = n[0].sym
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.k = locOther
|
||||
sym.positionImpl = p.breakIdx+1
|
||||
# ^ IC: review this
|
||||
sym.loc.k = locOther
|
||||
sym.position = p.breakIdx+1
|
||||
expr(p, n[1], d)
|
||||
endSimpleBlock(p, scope)
|
||||
|
||||
@@ -1259,8 +1250,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
initElifBranch(p.s(cpsStmts), ifStmt, orExpr)
|
||||
if exvar != nil:
|
||||
fillLocalName(p, exvar.sym)
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnStack)
|
||||
fillLoc(exvar.sym.loc, locTemp, exvar, OnStack)
|
||||
linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ),
|
||||
rdLoc(exvar.sym.loc), rope(etmp+1)])
|
||||
# we handled the error:
|
||||
@@ -1308,8 +1298,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
if isImportedException(typeNode.typ, p.config):
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLocalName(p, exvar.sym)
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnStack)
|
||||
fillLoc(exvar.sym.loc, locTemp, exvar, OnStack)
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1& $2) {$n", [getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc)])
|
||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||
@@ -1400,8 +1389,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
if t[i][j].isInfixAs():
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLocalName(p, exvar.sym)
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnUnknown)
|
||||
fillLoc(exvar.sym.loc, locTemp, exvar, OnUnknown)
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1& $2) {$n", [getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc)])
|
||||
else:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
# ------------------------- Name Mangling --------------------------------
|
||||
|
||||
import sighashes, std/strscans
|
||||
import sighashes, modulegraphs, std/strscans
|
||||
import ../dist/checksums/src/checksums/md5
|
||||
import std/sequtils
|
||||
|
||||
@@ -75,7 +75,7 @@ proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
|
||||
proc fillBackendName(m: BModule; s: PSym) =
|
||||
if s.loc.snippet == "":
|
||||
var result: Rope
|
||||
if s.kind in routineKinds and {optCDebug, optItaniumMangle} * m.g.config.globalOptions == {optCDebug, optItaniumMangle} and
|
||||
if not m.compileToCpp and s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
|
||||
m.g.config.symbolFiles == disabledSf:
|
||||
result = mangleProc(m, s, false).rope
|
||||
else:
|
||||
@@ -84,8 +84,7 @@ proc fillBackendName(m: BModule; s: PSym) =
|
||||
if m.hcrOn:
|
||||
result.add '_'
|
||||
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))
|
||||
backendEnsureMutable s
|
||||
s.locImpl.snippet = result
|
||||
s.loc.snippet = result
|
||||
|
||||
proc fillParamName(m: BModule; s: PSym) =
|
||||
if s.loc.snippet == "":
|
||||
@@ -108,8 +107,7 @@ proc fillParamName(m: BModule; s: PSym) =
|
||||
# and a function called in main or proxy uses `socket` as a parameter name.
|
||||
# That would lead to either needing to reload `proxy` or to overwrite the
|
||||
# executable file for the main module, which is running (or both!) -> error.
|
||||
backendEnsureMutable s
|
||||
s.locImpl.snippet = res.rope
|
||||
s.loc.snippet = res.rope
|
||||
|
||||
proc fillLocalName(p: BProc; s: PSym) =
|
||||
assert s.kind in skLocalVars+{skTemp}
|
||||
@@ -124,8 +122,7 @@ proc fillLocalName(p: BProc; s: PSym) =
|
||||
elif s.kind != skResult:
|
||||
result.add "_" & rope(counter+1)
|
||||
p.sigConflicts.inc(key)
|
||||
backendEnsureMutable s
|
||||
s.locImpl.snippet = result
|
||||
s.loc.snippet = result
|
||||
|
||||
proc scopeMangledParam(p: BProc; param: PSym) =
|
||||
## parameter generation only takes BModule, not a BProc, so we have to
|
||||
@@ -159,9 +156,8 @@ proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||
break
|
||||
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.elementType else: typ
|
||||
if typ.loc.snippet == "":
|
||||
backendEnsureMutable typ
|
||||
typ.typeName(typ.locImpl.snippet)
|
||||
typ.locImpl.snippet.add $sig
|
||||
typ.typeName(typ.loc.snippet)
|
||||
typ.loc.snippet.add $sig
|
||||
else:
|
||||
when defined(debugSigHashes):
|
||||
# check consistency:
|
||||
@@ -251,7 +247,6 @@ proc isOrHasImportedCppType(typ: PType): bool =
|
||||
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
|
||||
|
||||
proc hasNoInit(t: PType): bool =
|
||||
let t = skipTypes(t, {tyGenericInst})
|
||||
result = t.sym != nil and sfNoInit in t.sym.flags
|
||||
|
||||
proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDescKind): Rope
|
||||
@@ -304,13 +299,12 @@ proc addAbiCheck(m: BModule; t: PType, name: Rope) =
|
||||
|
||||
|
||||
proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) =
|
||||
ensureMutable param.sym
|
||||
fillLoc(param.sym.locImpl, locParam, param, "Result",
|
||||
fillLoc(param.sym.loc, locParam, param, "Result",
|
||||
OnStack)
|
||||
let t = param.sym.typ
|
||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype):
|
||||
incl(param.sym.locImpl.flags, lfIndirect)
|
||||
param.sym.locImpl.storage = OnUnknown
|
||||
incl(param.sym.loc.flags, lfIndirect)
|
||||
param.sym.loc.storage = OnUnknown
|
||||
|
||||
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
|
||||
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
|
||||
@@ -529,15 +523,14 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params
|
||||
var types, names, args: seq[string] = @[]
|
||||
if not isCtor:
|
||||
var this = t.n[1].sym
|
||||
ensureMutable this
|
||||
fillParamName(m, this)
|
||||
fillLoc(this.locImpl, locParam, t.n[1],
|
||||
fillLoc(this.loc, locParam, t.n[1],
|
||||
this.paramStorageLoc)
|
||||
if this.typ.kind == tyPtr:
|
||||
this.locImpl.snippet = "this"
|
||||
this.loc.snippet = "this"
|
||||
else:
|
||||
this.locImpl.snippet = "(*this)"
|
||||
names.add this.locImpl.snippet
|
||||
this.loc.snippet = "(*this)"
|
||||
names.add this.loc.snippet
|
||||
types.add getTypeDescWeak(m, this.typ, check, dkParam)
|
||||
|
||||
let firstParam = if isCtor: 1 else: 2
|
||||
@@ -551,14 +544,13 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params
|
||||
else:
|
||||
descKind = dkRefParam
|
||||
var typ, name: string
|
||||
ensureMutable param
|
||||
fillParamName(m, param)
|
||||
fillLoc(param.locImpl, locParam, t.n[i],
|
||||
fillLoc(param.loc, locParam, t.n[i],
|
||||
param.paramStorageLoc)
|
||||
if ccgIntroducedPtr(m.config, param, t.returnType) and descKind == dkParam:
|
||||
typ = getTypeDescWeak(m, param.typ, check, descKind) & "*"
|
||||
incl(param.locImpl.flags, lfIndirect)
|
||||
param.locImpl.storage = OnUnknown
|
||||
incl(param.loc.flags, lfIndirect)
|
||||
param.loc.storage = OnUnknown
|
||||
elif weakDep:
|
||||
typ = getTypeDescWeak(m, param.typ, check, descKind)
|
||||
else:
|
||||
@@ -566,7 +558,7 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params
|
||||
if sfNoalias in param.flags:
|
||||
typ.add("NIM_NOALIAS ")
|
||||
|
||||
name = param.locImpl.snippet
|
||||
name = param.loc.snippet
|
||||
types.add typ
|
||||
names.add name
|
||||
if sfCodegenDecl notin param.flags:
|
||||
@@ -608,15 +600,14 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder,
|
||||
else:
|
||||
descKind = dkRefParam
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
backendEnsureMutable param
|
||||
fillParamName(m, param)
|
||||
fillLoc(param.locImpl, locParam, t.n[i],
|
||||
fillLoc(param.loc, locParam, t.n[i],
|
||||
param.paramStorageLoc)
|
||||
var typ: Rope
|
||||
if ccgIntroducedPtr(m.config, param, t.returnType) and descKind == dkParam:
|
||||
typ = ptrType(getTypeDescWeak(m, param.typ, check, descKind))
|
||||
incl(param.locImpl.flags, lfIndirect)
|
||||
param.locImpl.storage = OnUnknown
|
||||
incl(param.loc.flags, lfIndirect)
|
||||
param.loc.storage = OnUnknown
|
||||
elif weakDep:
|
||||
typ = (getTypeDescWeak(m, param.typ, check, descKind))
|
||||
else:
|
||||
@@ -628,9 +619,9 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder,
|
||||
var j = 0
|
||||
while arr.kind in {tyOpenArray, tyVarargs}:
|
||||
# this fixes the 'sort' bug:
|
||||
if param.typ.kind in {tyVar, tyLent}: param.locImpl.storage = OnUnknown
|
||||
if param.typ.kind in {tyVar, tyLent}: param.loc.storage = OnUnknown
|
||||
# need to pass hidden parameter:
|
||||
params.addParam(paramBuilder, name = param.locImpl.snippet & "Len_" & $j, typ = NimInt)
|
||||
params.addParam(paramBuilder, name = param.loc.snippet & "Len_" & $j, typ = NimInt)
|
||||
inc(j)
|
||||
arr = arr[0].skipTypes({tySink})
|
||||
if t.returnType != nil and isInvalidReturnType(m.config, t):
|
||||
@@ -715,13 +706,12 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
if field.typ.kind == tyVoid: return
|
||||
#assert(field.ast == nil)
|
||||
let sname = mangleRecFieldName(m, field)
|
||||
backendEnsureMutable field
|
||||
fillLoc(field.locImpl, locField, n, unionPrefix & sname, OnUnknown)
|
||||
fillLoc(field.loc, locField, n, unionPrefix & sname, OnUnknown)
|
||||
# for importcpp'ed objects, we only need to set field.loc, but don't
|
||||
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
||||
# with heavily templatized C++ code:
|
||||
if not isImportedCppType(rectype):
|
||||
let fieldType = field.loc.t.skipTypes(abstractInst)
|
||||
let fieldType = field.loc.lode.typ.skipTypes(abstractInst)
|
||||
var typ: Rope = ""
|
||||
var isFlexArray = false
|
||||
var initializer = ""
|
||||
@@ -844,54 +834,6 @@ proc getOpenArrayDesc(m: BModule; t: PType, check: var IntSet; kind: TypeDescKin
|
||||
m.s[cfsTypes].addField(name = "Field0", typ = ptrType(elemType))
|
||||
m.s[cfsTypes].addField(name = "Field1", typ = NimInt)
|
||||
|
||||
proc importedCppObject(m: BModule; t, tt: PType; check: var IntSet; kind: TypeDescKind; sig: SigHash; result: var Rope) =
|
||||
let cppNameAsRope = getTypeName(m, t, sig)
|
||||
let cppName = $cppNameAsRope
|
||||
var i = 0
|
||||
var chunkStart = 0
|
||||
|
||||
template addResultType(ty: untyped) =
|
||||
if ty == nil or ty.kind == tyVoid:
|
||||
result.add(CVoid)
|
||||
elif ty.kind == tyStatic:
|
||||
internalAssert m.config, ty.n != nil
|
||||
result.add ty.n.renderTree
|
||||
else:
|
||||
result.add getTypeDescAux(m, ty, check, kind)
|
||||
|
||||
while i < cppName.len:
|
||||
if cppName[i] == '\'':
|
||||
var chunkEnd = i-1
|
||||
var idx, stars: int = 0
|
||||
if scanCppGenericSlot(cppName, i, idx, stars):
|
||||
result.add cppName.substr(chunkStart, chunkEnd)
|
||||
chunkStart = i
|
||||
|
||||
let typeInSlot = resolveStarsInCppType(tt, idx + 1, stars)
|
||||
addResultType(typeInSlot)
|
||||
else:
|
||||
inc i
|
||||
|
||||
if chunkStart != 0:
|
||||
result.add cppName.substr(chunkStart)
|
||||
else:
|
||||
result = cppNameAsRope & "<"
|
||||
for needsComma, a in tt.genericInstParams:
|
||||
if needsComma: result.add(" COMMA ")
|
||||
addResultType(a)
|
||||
result.add("> ")
|
||||
# always call for sideeffects:
|
||||
assert t.kind != tyTuple
|
||||
discard getRecordDesc(m, t, result, check)
|
||||
# The resulting type will include commas and these won't play well
|
||||
# with the C macros for defining procs such as N_NIMCALL. We must
|
||||
# create a typedef for the type and use it in the proc signature:
|
||||
let typedefName = "TY" & $sig
|
||||
m.s[cfsTypes].addTypedef(name = typedefName):
|
||||
m.s[cfsTypes].add(result)
|
||||
m.typeCache[sig] = typedefName
|
||||
result = typedefName
|
||||
|
||||
proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDescKind): Rope =
|
||||
# returns only the type's name
|
||||
var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned})
|
||||
@@ -907,7 +849,7 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
|
||||
# tyDistinct matters if it is an importc type
|
||||
result = getTypePre(m, origTyp.skipTypes(irrelevantForBackend-{tyOwned, tyDistinct}), sig)
|
||||
defer:
|
||||
defer: # defer is the simplest in this case
|
||||
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig):
|
||||
addAbiCheck(m, t, result)
|
||||
|
||||
@@ -1041,7 +983,7 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
m.s[cfsTypes].addArrayTypedef(name = result, len = 1):
|
||||
m.s[cfsTypes].add(et)
|
||||
of tyArray:
|
||||
var n = toInt64(lengthOrd(m.config, t))
|
||||
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
result = getTypeName(m, origTyp, sig)
|
||||
m.typeCache[sig] = result
|
||||
@@ -1052,7 +994,52 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
of tyObject, tyTuple:
|
||||
let tt = origTyp.skipTypes({tyDistinct})
|
||||
if isImportedCppType(t) and tt.kind == tyGenericInst:
|
||||
importedCppObject(m, t, tt, check, kind, sig, result)
|
||||
let cppNameAsRope = getTypeName(m, t, sig)
|
||||
let cppName = $cppNameAsRope
|
||||
var i = 0
|
||||
var chunkStart = 0
|
||||
|
||||
template addResultType(ty: untyped) =
|
||||
if ty == nil or ty.kind == tyVoid:
|
||||
result.add(CVoid)
|
||||
elif ty.kind == tyStatic:
|
||||
internalAssert m.config, ty.n != nil
|
||||
result.add ty.n.renderTree
|
||||
else:
|
||||
result.add getTypeDescAux(m, ty, check, kind)
|
||||
|
||||
while i < cppName.len:
|
||||
if cppName[i] == '\'':
|
||||
var chunkEnd = i-1
|
||||
var idx, stars: int = 0
|
||||
if scanCppGenericSlot(cppName, i, idx, stars):
|
||||
result.add cppName.substr(chunkStart, chunkEnd)
|
||||
chunkStart = i
|
||||
|
||||
let typeInSlot = resolveStarsInCppType(tt, idx + 1, stars)
|
||||
addResultType(typeInSlot)
|
||||
else:
|
||||
inc i
|
||||
|
||||
if chunkStart != 0:
|
||||
result.add cppName.substr(chunkStart)
|
||||
else:
|
||||
result = cppNameAsRope & "<"
|
||||
for needsComma, a in tt.genericInstParams:
|
||||
if needsComma: result.add(" COMMA ")
|
||||
addResultType(a)
|
||||
result.add("> ")
|
||||
# always call for sideeffects:
|
||||
assert t.kind != tyTuple
|
||||
discard getRecordDesc(m, t, result, check)
|
||||
# The resulting type will include commas and these won't play well
|
||||
# with the C macros for defining procs such as N_NIMCALL. We must
|
||||
# create a typedef for the type and use it in the proc signature:
|
||||
let typedefName = "TY" & $sig
|
||||
m.s[cfsTypes].addTypedef(name = typedefName):
|
||||
m.s[cfsTypes].add(result)
|
||||
m.typeCache[sig] = typedefName
|
||||
result = typedefName
|
||||
else:
|
||||
result = cacheGetType(m.forwTypeCache, sig)
|
||||
if result == "":
|
||||
@@ -1167,8 +1154,7 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Builder; asPtr: bool
|
||||
let isCtor = sfConstructor in prc.flags
|
||||
var check = initIntSet()
|
||||
fillBackendName(m, prc)
|
||||
ensureMutable prc
|
||||
fillLoc(prc.locImpl, locProc, prc.ast[namePos], OnUnknown)
|
||||
fillLoc(prc.loc, locProc, prc.ast[namePos], OnUnknown)
|
||||
var memberOp = "#." #only virtual
|
||||
var typ: PType
|
||||
if isCtor:
|
||||
@@ -1200,7 +1186,7 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Builder; asPtr: bool
|
||||
superCall = ""
|
||||
else:
|
||||
if not isCtor:
|
||||
prc.locImpl.snippet = "$1$2(@)" % [memberOp, name]
|
||||
prc.loc.snippet = "$1$2(@)" % [memberOp, name]
|
||||
elif superCall != "":
|
||||
superCall = " : " & superCall
|
||||
|
||||
@@ -1215,15 +1201,14 @@ proc genProcHeader(m: BModule; prc: PSym; result: var Builder; visibility: var D
|
||||
# using static is needed for inline procs
|
||||
var check = initIntSet()
|
||||
fillBackendName(m, prc)
|
||||
backendEnsureMutable prc
|
||||
fillLoc(prc.locImpl, locProc, prc.ast[namePos], OnUnknown)
|
||||
fillLoc(prc.loc, locProc, prc.ast[namePos], OnUnknown)
|
||||
var rettype: Snippet = ""
|
||||
var desc = newBuilder("")
|
||||
genProcParams(m, prc.typ, rettype, desc, check, true, false)
|
||||
let params = extract(desc)
|
||||
# handle the 2 options for hotcodereloading codegen - function pointer
|
||||
# (instead of forward declaration) or header for function body with "_actual" postfix
|
||||
var name = prc.locImpl.snippet
|
||||
var name = prc.loc.snippet
|
||||
if not asPtr and isReloadable(m, prc):
|
||||
name.add("_actual")
|
||||
# careful here! don't access ``prc.ast`` as that could reload large parts of
|
||||
@@ -1463,7 +1448,7 @@ proc genObjectInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo
|
||||
var t = typ.baseClass
|
||||
while t != nil:
|
||||
t = t.skipTypes(skipPtrs)
|
||||
t.incl tfObjHasKids
|
||||
t.flags.incl tfObjHasKids
|
||||
t = t.baseClass
|
||||
|
||||
proc genTupleInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo) =
|
||||
@@ -1659,8 +1644,8 @@ proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TType
|
||||
n[bodyPos] = body
|
||||
result.ast = n
|
||||
|
||||
incl result.flagsImpl, sfFromGeneric
|
||||
incl result.flagsImpl, sfGeneratedOp
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result: var Builder) =
|
||||
let theProc = getAttachedOp(m.g.graph, t, op)
|
||||
@@ -1865,12 +1850,6 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
if t.kind == tyObject and t.baseClass != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
|
||||
proc myModuleOpenForCodegen(m: BModule; idx: FileIndex): bool {.inline.} =
|
||||
if moduleOpenForCodegen(m.g.graph, idx):
|
||||
result = idx.int < m.g.mods.len and m.g.mods[idx.int] != nil
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc genTypeInfoV2(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
let origType = t
|
||||
# distinct types can have their own destructors
|
||||
@@ -1899,9 +1878,9 @@ proc genTypeInfoV2(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
m.typeInfoMarkerV2[sig] = result
|
||||
|
||||
let owner = t.skipTypes(typedescPtrs).itemId.module
|
||||
if owner != m.module.position and myModuleOpenForCodegen(m, FileIndex owner):
|
||||
if owner != m.module.position and moduleOpenForCodegen(m.g.graph, FileIndex owner):
|
||||
# make sure the type info is created in the owner module
|
||||
discard genTypeInfoV2(m.g.mods[owner], origType, info)
|
||||
discard genTypeInfoV2(m.g.modules[owner], origType, info)
|
||||
# reference the type info as extern here
|
||||
cgsym(m, "TNimTypeV2")
|
||||
declareNimType(m, "TNimTypeV2", result, owner)
|
||||
@@ -1984,9 +1963,9 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
return prefixTI(result)
|
||||
|
||||
var owner = t.skipTypes(typedescPtrs).itemId.module
|
||||
if owner != m.module.position and myModuleOpenForCodegen(m, FileIndex owner):
|
||||
if owner != m.module.position and moduleOpenForCodegen(m.g.graph, FileIndex owner):
|
||||
# make sure the type info is created in the owner module
|
||||
discard genTypeInfoV1(m.g.mods[owner], origType, info)
|
||||
discard genTypeInfoV1(m.g.modules[owner], origType, info)
|
||||
# reference the type info as extern here
|
||||
cgsym(m, "TNimType")
|
||||
cgsym(m, "TNimNode")
|
||||
@@ -2022,9 +2001,6 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
of tyRef:
|
||||
genTypeInfoAux(m, t, t, result, info)
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
|
||||
# it may not be used in other places except in `genTraverseProc`,
|
||||
# we have to generate a typedesc for this case, not a weak one
|
||||
discard getTypeDesc(m, origType.last)
|
||||
let markerProc = genTraverseProc(m, origType, sig)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker", markerProc)
|
||||
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
|
||||
@@ -2063,21 +2039,17 @@ proc genTypeInfo*(config: ConfigRef, m: BModule; t: PType; info: TLineInfo): Rop
|
||||
else:
|
||||
result = genTypeInfoV1(m, t, info)
|
||||
|
||||
proc retrieveSym(n: PNode): PSym =
|
||||
case n.kind
|
||||
of nkPostfix: result = retrieveSym(n[1])
|
||||
of nkPragmaExpr, nkTypeDef: result = retrieveSym(n[0])
|
||||
of nkSym: result = n.sym
|
||||
else: result = nil
|
||||
|
||||
proc genTypeSection(m: BModule, n: PNode) =
|
||||
var intSet = initIntSet()
|
||||
let compress = optCompress in m.config.globalOptions
|
||||
for typedef in n:
|
||||
let s = retrieveSym(typedef)
|
||||
if s != nil and ({sfExportc, sfCompilerProc} * s.flags == {sfExportc} or compress) and s.typ != nil and
|
||||
not containsGenericType(s.typ) and
|
||||
s.typ.kind notin {tyVoid, tyNot, tyAnything, tyOr, tyAnd, tyUntyped, tyTyped, tyNone, tyNil, tySink}:
|
||||
discard getTypeDescAux(m, s.typ, intSet, descKindFromSymKind(s.kind))
|
||||
if m.g.generatedHeader != nil:
|
||||
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.kind))
|
||||
for i in 0..<n.len:
|
||||
if len(n[i]) == 0: continue
|
||||
if n[i][0].kind != nkPragmaExpr: continue
|
||||
for p in 0..<n[i][0].len:
|
||||
if (n[i][0][p].kind notin {nkSym, nkPostfix}): continue
|
||||
var s = n[i][0][p]
|
||||
if s.kind == nkPostfix:
|
||||
s = n[i][0][p][1]
|
||||
if {sfExportc, sfCompilerProc} * s.sym.flags == {sfExportc}:
|
||||
discard getTypeDescAux(m, s.typ, intSet, descKindFromSymKind(s.sym.kind))
|
||||
if m.g.generatedHeader != nil:
|
||||
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.sym.kind))
|
||||
|
||||
@@ -16,7 +16,7 @@ import
|
||||
rodutils, renderer, cgendata, aliases,
|
||||
lowerings, lineinfos, pathutils, transf,
|
||||
injectdestructors, astmsgs, modulepaths, pushpoppragmas,
|
||||
mangleutils, cbuilderbase, modulegraphs
|
||||
mangleutils, cbuilderbase
|
||||
|
||||
from expanddefaults import caseObjDefaultBranch
|
||||
|
||||
@@ -61,25 +61,14 @@ proc hcrOn(p: BProc): bool = p.module.config.hcrOn
|
||||
proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
m.g.forwardedProcs.add(prc)
|
||||
|
||||
proc newModule*(g: BModuleList; module: PSym; conf: ConfigRef; idgen: IdGenerator): BModule
|
||||
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
# TODO fixme
|
||||
if m.config.symbolFiles == v2Sf or optCompress in m.config.globalOptions:
|
||||
if m.config.symbolFiles == v2Sf:
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.mods[ms]
|
||||
elif m.config.cmd in {cmdNifC, cmdM}:
|
||||
var ms = getModule(s)
|
||||
registerModule m.g.graph, ms
|
||||
if ms.position >= m.g.mods.len:
|
||||
result = newModule(m.g, ms, m.config, idGeneratorFromModule(ms))
|
||||
else:
|
||||
result = m.g.mods[ms.position]
|
||||
if result == nil:
|
||||
result = newModule(m.g, ms, m.config, idGeneratorFromModule(ms))
|
||||
result = m.g.modules[ms]
|
||||
else:
|
||||
var ms = getModule(s)
|
||||
result = m.g.mods[ms.position]
|
||||
result = m.g.modules[ms.position]
|
||||
|
||||
proc initLoc(k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}): TLoc =
|
||||
result = TLoc(k: k, storage: s, lode: lode,
|
||||
@@ -108,7 +97,7 @@ proc t(a: TLoc): PType {.inline.} =
|
||||
|
||||
proc lodeTyp(t: PType): PNode =
|
||||
result = newNode(nkEmpty)
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc isSimpleConst(typ: PType): bool =
|
||||
let t = skipTypes(typ, abstractVar)
|
||||
@@ -133,10 +122,10 @@ proc getModuleDllPath(m: BModule): Rope =
|
||||
result = makeCString(dir.string & "/" & filename)
|
||||
|
||||
proc getModuleDllPath(m: BModule, module: int): Rope =
|
||||
result = getModuleDllPath(m.g.mods[module])
|
||||
result = getModuleDllPath(m.g.modules[module])
|
||||
|
||||
proc getModuleDllPath(m: BModule, s: PSym): Rope =
|
||||
result = getModuleDllPath(m.g.mods[s.itemId.module])
|
||||
result = getModuleDllPath(m.g.modules[s.itemId.module])
|
||||
|
||||
import std/macros
|
||||
|
||||
@@ -337,10 +326,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||
let line = t.info.safeLineNm
|
||||
|
||||
if optEmbedOrigSrc in p.config.globalOptions:
|
||||
var code = sourceLine(p.config, t.info)
|
||||
if code.endsWith('\\'):
|
||||
code.add "#"
|
||||
p.s(cpsStmts).add("// " & code & "\L")
|
||||
p.s(cpsStmts).add("//" & sourceLine(p.config, t.info) & "\L")
|
||||
let lastFileIndex = p.lastLineInfo.fileIndex
|
||||
let freshLine = freshLineInfo(p, t.info)
|
||||
if freshLine:
|
||||
@@ -520,7 +506,7 @@ include ccgreset
|
||||
proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
let containsGcRef = optSeqDestructors notin p.config.globalOptions and containsGarbageCollectedRef(loc.t)
|
||||
let typ = skipTypes(loc.t, abstractVarRange)
|
||||
if isImportedCppType(typ):
|
||||
if isImportedCppType(typ):
|
||||
var didGenTemp = false
|
||||
let rl = rdLoc(loc)
|
||||
let init = genCppInitializer(p.module, p, typ, didGenTemp)
|
||||
@@ -614,8 +600,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||
# ``var v = X()`` gets transformed into ``X(&v)``.
|
||||
# Nowadays the logic in ccgcalls deals with this case however.
|
||||
if not immediateAsgn:
|
||||
backendEnsureMutable v
|
||||
constructLoc(p, v.locImpl)
|
||||
constructLoc(p, v.loc)
|
||||
|
||||
proc getTemp(p: BProc, t: PType, needsInit=false): TLoc =
|
||||
inc(p.labels)
|
||||
@@ -661,9 +646,8 @@ proc localVarDecl(res: var Builder, p: BProc; n: PNode,
|
||||
let s = n.sym
|
||||
if s.loc.k == locNone:
|
||||
fillLocalName(p, s)
|
||||
backendEnsureMutable s
|
||||
fillLoc(s.locImpl, locLocalVar, n, OnStack)
|
||||
if s.kind == skLet: incl(s, lfNoDeepCopy)
|
||||
fillLoc(s.loc, locLocalVar, n, OnStack)
|
||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||
|
||||
genCLineDir(res, p, n.info, p.config)
|
||||
|
||||
@@ -723,17 +707,15 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||
let s = n.sym
|
||||
if s.loc.k == locNone:
|
||||
fillBackendName(p.module, s)
|
||||
backendEnsureMutable s
|
||||
fillLoc(s.locImpl, locGlobalVar, n, OnHeap)
|
||||
if treatGlobalDifferentlyForHCR(p.module, s): incl(s, lfIndirect)
|
||||
fillLoc(s.loc, locGlobalVar, n, OnHeap)
|
||||
if treatGlobalDifferentlyForHCR(p.module, s): incl(s.loc.flags, lfIndirect)
|
||||
|
||||
if lfDynamicLib in s.loc.flags:
|
||||
var q = findPendingModule(p.module, s)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, s.id):
|
||||
varInDynamicLib(q, s)
|
||||
else:
|
||||
backendEnsureMutable s
|
||||
s.locImpl.snippet = mangleDynLibProc(s)
|
||||
s.loc.snippet = mangleDynLibProc(s)
|
||||
if value != "":
|
||||
internalError(p.config, n.info, ".dynlib variables cannot have a value")
|
||||
return
|
||||
@@ -773,14 +755,12 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||
genGlobalVarDecl(p.module.s[cfsVars], p, n, td, initializer = initializer)
|
||||
if p.withinLoop > 0 and value == "":
|
||||
# fixes tests/run/tzeroarray:
|
||||
backendEnsureMutable s
|
||||
resetLoc(p, s.locImpl)
|
||||
resetLoc(p, s.loc)
|
||||
|
||||
proc callGlobalVarCppCtor(p: BProc; v: PSym; vn, value: PNode; didGenTemp: var bool) =
|
||||
let s = vn.sym
|
||||
fillBackendName(p.module, s)
|
||||
backendEnsureMutable s
|
||||
fillLoc(s.locImpl, locGlobalVar, vn, OnHeap)
|
||||
fillLoc(s.loc, locGlobalVar, vn, OnHeap)
|
||||
let td = getTypeDesc(p.module, vn.sym.typ, dkVar)
|
||||
var val = genCppParamsForCtor(p, value, didGenTemp)
|
||||
if didGenTemp: return # generated in the caller
|
||||
@@ -799,8 +779,7 @@ proc fillProcLoc(m: BModule; n: PNode) =
|
||||
let sym = n.sym
|
||||
if sym.loc.k == locNone:
|
||||
fillBackendName(m, sym)
|
||||
backendEnsureMutable sym
|
||||
fillLoc(sym.locImpl, locProc, n, OnStack)
|
||||
fillLoc(sym.loc, locProc, n, OnStack)
|
||||
|
||||
proc getLabel(p: BProc): TLabel =
|
||||
inc(p.labels)
|
||||
@@ -969,8 +948,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
var extname = sym.loc.snippet
|
||||
if not isCall: loadDynamicLib(m, lib)
|
||||
var tmp = mangleDynLibProc(sym)
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.snippet = tmp # from now on we only need the internal name
|
||||
sym.loc.snippet = tmp # from now on we only need the internal name
|
||||
sym.typ.sym = nil # generate a new name
|
||||
inc(m.labels, 2)
|
||||
if isCall:
|
||||
@@ -1012,10 +990,9 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
|
||||
var lib = sym.annex
|
||||
var extname = sym.loc.snippet
|
||||
loadDynamicLib(m, lib)
|
||||
incl(sym, lfIndirect)
|
||||
incl(sym.loc.flags, lfIndirect)
|
||||
var tmp = mangleDynLibProc(sym)
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.snippet = tmp # from now on we only need the internal name
|
||||
sym.loc.snippet = tmp # from now on we only need the internal name
|
||||
inc(m.labels, 2)
|
||||
let t = ptrType(getTypeDesc(m, sym.typ, dkVar))
|
||||
# cgsym has side effects, do it first:
|
||||
@@ -1028,8 +1005,7 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
|
||||
m.s[cfsVars].addVar(name = sym.loc.snippet, typ = t)
|
||||
|
||||
proc symInDynamicLibPartial(m: BModule, sym: PSym) =
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.snippet = mangleDynLibProc(sym)
|
||||
sym.loc.snippet = mangleDynLibProc(sym)
|
||||
sym.typ.sym = nil # generate a new name
|
||||
|
||||
proc cgsymImpl(m: BModule; sym: PSym) {.inline.} =
|
||||
@@ -1262,11 +1238,6 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
(n[0].kind == nkSym and sfNoReturn in n[0].sym.flags):
|
||||
# requires initializations when encountering unreachable code
|
||||
result = InitRequired
|
||||
elif n[0].kind == nkSym and
|
||||
n[0].sym.magic in {mUnaryMinusI..mAbsI, mAddI..mPred} and
|
||||
optOverflowCheck in p.config.options:
|
||||
# arithmetic operations may raise exceptions
|
||||
result = InitRequired
|
||||
else:
|
||||
for i in 0..<n.safeLen:
|
||||
allPathsInBranch(n[i])
|
||||
@@ -1299,7 +1270,7 @@ proc genProcBody(p: BProc; procBody: PNode) =
|
||||
p.blocks[0].sections[cpsInit].addAssignmentWithValue("nimErr_"):
|
||||
p.blocks[0].sections[cpsInit].addCall(cgsymValue(p.module, "nimErrorFlag"))
|
||||
|
||||
proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
proc genProcAux*(m: BModule, prc: PSym) =
|
||||
var p = newProc(prc, m)
|
||||
var header = newBuilder("")
|
||||
let isCppMember = m.config.backend == backendCpp and sfCppMember * prc.flags != {}
|
||||
@@ -1324,7 +1295,7 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
let resNode = prc.ast[resultPos]
|
||||
let res = resNode.sym # get result symbol
|
||||
if not isInvalidReturnType(m.config, prc.typ) and sfConstructor notin prc.flags:
|
||||
if sfNoInit in prc.flags: incl(res, sfNoInit)
|
||||
if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
|
||||
if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil):
|
||||
var a: TLoc = initLocExprSingleUse(p, val)
|
||||
let ra = rdLoc(a)
|
||||
@@ -1345,11 +1316,9 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
returnBuilder.addReturn(rres)
|
||||
returnStmt = extract(returnBuilder)
|
||||
elif sfConstructor in prc.flags:
|
||||
resNode.sym.incl lfIndirect
|
||||
backendEnsureMutable resNode.sym
|
||||
fillLoc(resNode.sym.locImpl, locParam, resNode, "this", OnHeap)
|
||||
backendEnsureMutable prc
|
||||
prc.locImpl.snippet = getTypeDesc(m, resNode.sym.locImpl.t, dkVar)
|
||||
resNode.sym.loc.flags.incl lfIndirect
|
||||
fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)
|
||||
prc.loc.snippet = getTypeDesc(m, resNode.sym.loc.t, dkVar)
|
||||
else:
|
||||
fillResult(p.config, resNode, prc.typ)
|
||||
assignParam(p, res, prc.typ.returnType)
|
||||
@@ -1362,12 +1331,10 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
if sfNoInit in prc.flags: discard
|
||||
elif allPathsAsgnResult(p, procBody) == InitSkippable: discard
|
||||
else:
|
||||
backendEnsureMutable res
|
||||
resetLoc(p, res.locImpl)
|
||||
resetLoc(p, res.loc)
|
||||
if skipTypes(res.typ, abstractInst).kind == tyArray:
|
||||
#incl(res.loc.flags, lfIndirect)
|
||||
backendEnsureMutable res
|
||||
res.locImpl.storage = OnUnknown
|
||||
res.loc.storage = OnUnknown
|
||||
|
||||
for i in 1..<prc.typ.n.len:
|
||||
let param = prc.typ.n[i].sym
|
||||
@@ -1376,8 +1343,7 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
closureSetup(p, prc)
|
||||
genProcBody(p, procBody)
|
||||
|
||||
# IC: spurious write, seems fine for now:
|
||||
prc.infoImpl = tmpInfo
|
||||
prc.info = tmpInfo
|
||||
|
||||
var generatedProc = newBuilder("")
|
||||
generatedProc.genCLineDir prc.info, m.config
|
||||
@@ -1460,8 +1426,6 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
getModuleDllPath(m, sym),
|
||||
'"' & name & '"')
|
||||
elif not containsOrIncl(m.declaredProtos, sym.id):
|
||||
if optCompress in m.config.globalOptions:
|
||||
m.queue.add(sym)
|
||||
let asPtr = isReloadable(m, sym)
|
||||
var header = newBuilder("")
|
||||
var visibility: DeclVisibility = None
|
||||
@@ -1481,9 +1445,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
m.s[cfsProcHeaders].add(extract(header))
|
||||
m.s[cfsProcHeaders].finishProcHeaderAsProto()
|
||||
|
||||
include inliner
|
||||
|
||||
proc genProcLvl2(m: BModule, prc: PSym) =
|
||||
# TODO: figure out how to rename this - it DOES generate a forward declaration
|
||||
proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
if lfImportCompilerProc in prc.loc.flags:
|
||||
fillProcLoc(m, prc.ast[namePos])
|
||||
useHeader(m, prc)
|
||||
@@ -1520,22 +1483,16 @@ proc genProcLvl2(m: BModule, prc: PSym) =
|
||||
#if prc.loc.k == locNone:
|
||||
# mangle the inline proc based on the module where it is defined -
|
||||
# not on the first module that uses it
|
||||
if m.module.itemId.module != prc.itemId.module and optCompress in m.config.globalOptions:
|
||||
let prcCopy = prc # copyInlineProc(prc, m.idgen)
|
||||
fillProcLoc(m, prcCopy.ast[namePos])
|
||||
genProcPrototype(m, prcCopy)
|
||||
genProcLvl3(m, prcCopy)
|
||||
else:
|
||||
let m2 = if m.config.symbolFiles != disabledSf: m
|
||||
else: findPendingModule(m, prc)
|
||||
fillProcLoc(m2, prc.ast[namePos])
|
||||
#elif {sfExportc, sfImportc} * prc.flags == {}:
|
||||
# # reset name to restore consistency in case of hashing collisions:
|
||||
# #echo "resetting ", prc.id, " by ", m.module.name.s
|
||||
# #prc.loc.snippet = nil
|
||||
# #prc.loc.snippet = mangleName(m, prc)
|
||||
genProcPrototype(m, prc)
|
||||
genProcLvl3(m, prc)
|
||||
let m2 = if m.config.symbolFiles != disabledSf: m
|
||||
else: findPendingModule(m, prc)
|
||||
fillProcLoc(m2, prc.ast[namePos])
|
||||
#elif {sfExportc, sfImportc} * prc.flags == {}:
|
||||
# # reset name to restore consistency in case of hashing collisions:
|
||||
# echo "resetting ", prc.id, " by ", m.module.name.s
|
||||
# prc.loc.snippet = nil
|
||||
# prc.loc.snippet = mangleName(m, prc)
|
||||
genProcPrototype(m, prc)
|
||||
genProcAux(m, prc)
|
||||
elif sfImportc notin prc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
fillProcLoc(q, prc.ast[namePos])
|
||||
@@ -1543,7 +1500,7 @@ proc genProcLvl2(m: BModule, prc: PSym) =
|
||||
# externally-to-the-current-module defined proc, also important
|
||||
# to do the declaredProtos check before the call to genProcPrototype
|
||||
if isReloadable(m, prc) and prc.id notin m.declaredProtos and
|
||||
q != nil and not sameModules(q.module, m.module):
|
||||
q != nil and q.module.id != m.module.id:
|
||||
m.s[cfsDynLibInit].add('\t')
|
||||
m.s[cfsDynLibInit].addAssignment(prc.loc.snippet,
|
||||
cCast(getProcTypeCast(m, prc),
|
||||
@@ -1556,7 +1513,7 @@ proc genProcLvl2(m: BModule, prc: PSym) =
|
||||
# which will actually become a function pointer
|
||||
if isReloadable(m, prc):
|
||||
genProcPrototype(q, prc)
|
||||
genProcLvl3(q, prc)
|
||||
genProcAux(q, prc)
|
||||
else:
|
||||
fillProcLoc(m, prc.ast[namePos])
|
||||
useHeader(m, prc)
|
||||
@@ -1582,26 +1539,25 @@ proc genProc(m: BModule, prc: PSym) =
|
||||
addForwardedProc(m, prc)
|
||||
fillProcLoc(m, prc.ast[namePos])
|
||||
else:
|
||||
genProcLvl2(m, prc)
|
||||
genProcNoForward(m, prc)
|
||||
if {sfExportc, sfCompilerProc} * prc.flags == {sfExportc} and
|
||||
m.g.generatedHeader != nil and lfNoDecl notin prc.loc.flags:
|
||||
genProcPrototype(m.g.generatedHeader, prc)
|
||||
if prc.typ.callConv == ccInline:
|
||||
if not containsOrIncl(m.g.generatedHeader.declaredThings, prc.id):
|
||||
genProcLvl3(m.g.generatedHeader, prc)
|
||||
genProcAux(m.g.generatedHeader, prc)
|
||||
|
||||
proc genVarPrototype(m: BModule, n: PNode) =
|
||||
#assert(sfGlobal in sym.flags)
|
||||
let sym = n.sym
|
||||
useHeader(m, sym)
|
||||
fillBackendName(m, sym)
|
||||
backendEnsureMutable sym
|
||||
fillLoc(sym.locImpl, locGlobalVar, n, OnHeap)
|
||||
if treatGlobalDifferentlyForHCR(m, sym): incl(sym, lfIndirect)
|
||||
fillLoc(sym.loc, locGlobalVar, n, OnHeap)
|
||||
if treatGlobalDifferentlyForHCR(m, sym): incl(sym.loc.flags, lfIndirect)
|
||||
|
||||
if (lfNoDecl in sym.loc.flags) or contains(m.declaredThings, sym.id):
|
||||
return
|
||||
if not sameOwners(sym.owner, m.module):
|
||||
if sym.owner.id != m.module.id:
|
||||
# else we already have the symbol generated!
|
||||
assert(sym.loc.snippet != "")
|
||||
incl(m.declaredThings, sym.id)
|
||||
@@ -1720,12 +1676,9 @@ proc genMainProcs(m: BModule) =
|
||||
|
||||
proc genMainProcsWithResult(m: BModule) =
|
||||
genMainProcs(m)
|
||||
if m.config.cmd != cmdNifC:
|
||||
var res = "nim_program_result"
|
||||
if m.hcrOn: res = cDeref(res)
|
||||
m.s[cfsProcs].addReturn(res)
|
||||
else:
|
||||
m.s[cfsProcs].addReturn(cIntValue(0))
|
||||
var res = "nim_program_result"
|
||||
if m.hcrOn: res = cDeref(res)
|
||||
m.s[cfsProcs].addReturn(res)
|
||||
|
||||
proc genNimMainInner(m: BModule) =
|
||||
m.s[cfsProcs].addDeclWithVisibility(Private):
|
||||
@@ -1963,7 +1916,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
|
||||
if m.hcrOn:
|
||||
var hcrModuleMeta = newBuilder("")
|
||||
let systemModulePath = getModuleDllPath(m, g.mods[g.graph.config.m.systemFileIdx.int].module)
|
||||
let systemModulePath = getModuleDllPath(m, g.modules[g.graph.config.m.systemFileIdx.int].module)
|
||||
let mainModulePath = getModuleDllPath(m, m.module)
|
||||
hcrModuleMeta.addDeclWithVisibility(Private):
|
||||
hcrModuleMeta.addArrayVarWithInitializer(kind = Local,
|
||||
@@ -1980,7 +1933,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
g.graph.importDeps.withValue(FileIndex(m.module.position), deps):
|
||||
for curr in deps[]:
|
||||
hcrModuleMeta.addField(modules, ""):
|
||||
hcrModuleMeta.add(getModuleDllPath(m, g.mods[curr.int].module))
|
||||
hcrModuleMeta.add(getModuleDllPath(m, g.modules[curr.int].module))
|
||||
hcrModuleMeta.addField(modules, ""):
|
||||
hcrModuleMeta.add("\"\"")
|
||||
hcrModuleMeta.addDeclWithVisibility(ExportLib):
|
||||
@@ -2116,8 +2069,7 @@ proc hcrGetProcLoadCode(builder: var Builder, m: BModule, sym, prefix, handle, g
|
||||
|
||||
var extname = prefix & sym
|
||||
var tmp = mangleDynLibProc(prc)
|
||||
backendEnsureMutable prc
|
||||
prc.locImpl.snippet = tmp
|
||||
prc.loc.snippet = tmp
|
||||
prc.typ.sym = nil
|
||||
|
||||
if not containsOrIncl(m.declaredThings, prc.id):
|
||||
@@ -2173,8 +2125,6 @@ proc genInitCode(m: BModule) =
|
||||
else:
|
||||
prcBody.add(extract(m.thing.s(section)))
|
||||
|
||||
#echo "PRE INIT PROC ", m.module.name.s, " ", m.s[cfsVars].buf.len
|
||||
|
||||
if m.preInitProc.s(cpsInit).buf.len > 0 or m.preInitProc.s(cpsStmts).buf.len > 0:
|
||||
# Give this small function its own scope
|
||||
prcBody.addScope():
|
||||
@@ -2387,14 +2337,13 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
|
||||
proc rawNewModule(g: BModuleList; module: PSym; conf: ConfigRef): BModule =
|
||||
result = rawNewModule(g, module, AbsoluteFile toFullPath(conf, module.position.FileIndex))
|
||||
|
||||
proc newModule(g: BModuleList; module: PSym; conf: ConfigRef; idgen: IdGenerator): BModule =
|
||||
proc newModule*(g: BModuleList; module: PSym; conf: ConfigRef): BModule =
|
||||
# we should create only one cgen module for each module sym
|
||||
result = rawNewModule(g, module, conf)
|
||||
result.idgen = idgen
|
||||
if module.position >= g.mods.len:
|
||||
setLen(g.mods, module.position + 1)
|
||||
if module.position >= g.modules.len:
|
||||
setLen(g.modules, module.position + 1)
|
||||
#growCache g.modules, module.position
|
||||
g.mods[module.position] = result
|
||||
g.modules[module.position] = result
|
||||
|
||||
template injectG() {.dirty.} =
|
||||
if graph.backend == nil:
|
||||
@@ -2403,7 +2352,8 @@ template injectG() {.dirty.} =
|
||||
|
||||
proc setupCgen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||
injectG()
|
||||
result = newModule(g, module, graph.config, idgen)
|
||||
result = newModule(g, module, graph.config)
|
||||
result.idgen = idgen
|
||||
if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
|
||||
let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile
|
||||
else: graph.config.projectFull
|
||||
@@ -2478,10 +2428,7 @@ proc handleProcGlobals(m: BModule) =
|
||||
|
||||
# fixes recursive calls #24997
|
||||
swap stmts, m.preInitProc.s(cpsStmts)
|
||||
var transformedN = procGlobals[i]
|
||||
if sfInjectDestructors in m.module.flags:
|
||||
transformedN = injectDestructorCalls(m.g.graph, m.idgen, m.module, transformedN)
|
||||
genStmts(m.preInitProc, transformedN)
|
||||
genStmts(m.preInitProc, procGlobals[i])
|
||||
swap stmts, m.preInitProc.s(cpsStmts)
|
||||
|
||||
handleProcGlobals(m)
|
||||
@@ -2528,15 +2475,16 @@ proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
|
||||
result = true
|
||||
|
||||
proc writeModule(m: BModule) =
|
||||
# We need 2 different logics here: pending modules (including
|
||||
# 'nim__dat') may require file merging for the combination of dead code
|
||||
# elimination and incremental compilation! Non pending modules need no
|
||||
# such logic and in fact the logic hurts for the main module at least;
|
||||
# it would generate multiple 'main' procs, for instance.
|
||||
|
||||
proc writeModule(m: BModule, pending: bool) =
|
||||
let cfile = getCFile(m)
|
||||
if moduleHasChanged(m.g.graph, m.module):
|
||||
genInitCode(m)
|
||||
|
||||
while m.queue.len > 0:
|
||||
let sym = m.queue.pop()
|
||||
genProcLvl2(m, sym)
|
||||
|
||||
finishTypeDescriptions(m)
|
||||
if sfMainModule in m.module.flags:
|
||||
# generate main file:
|
||||
@@ -2571,11 +2519,10 @@ proc generateLibraryDestroyGlobals(graph: ModuleGraph; m: BModule; body: PNode;
|
||||
result = newSym(skProc, procname, m.idgen, m.module.owner, m.module.info)
|
||||
result.typ = newProcType(m.module.info, m.idgen, m.module.owner)
|
||||
result.typ.callConv = ccCDecl
|
||||
backendEnsureMutable result
|
||||
incl result.flagsImpl, sfExportc
|
||||
result.locImpl.snippet = prefixedName
|
||||
incl result.flags, sfExportc
|
||||
result.loc.snippet = prefixedName
|
||||
if isDynlib:
|
||||
incl(result.locImpl.flags, lfExportLib)
|
||||
incl(result.loc.flags, lfExportLib)
|
||||
|
||||
let theProc = newNodeI(nkProcDef, m.module.info, bodyPos+1)
|
||||
for i in 0..<theProc.len: theProc[i] = newNodeI(nkEmpty, m.module.info)
|
||||
@@ -2600,7 +2547,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||
body.add graph.globalDestructors[i]
|
||||
body.flags.incl nfTransf # should not be further transformed
|
||||
let dtor = generateLibraryDestroyGlobals(graph, m, body, optGenDynLib in m.config.globalOptions)
|
||||
genProcLvl3(m, dtor)
|
||||
genProcAux(m, dtor)
|
||||
if pipelineutils.skipCodegen(m.config, n): return
|
||||
if moduleHasChanged(graph, m.module):
|
||||
# if the module is cached, we don't regenerate the main proc
|
||||
@@ -2653,15 +2600,15 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||
proc genForwardedProcs(g: BModuleList) =
|
||||
# Forward declared proc:s lack bodies when first encountered, so they're given
|
||||
# a second pass here
|
||||
# Note: ``genProcLvl2`` may add to ``forwardedProcs``
|
||||
# Note: ``genProcNoForward`` may add to ``forwardedProcs``
|
||||
while g.forwardedProcs.len > 0:
|
||||
let
|
||||
prc = g.forwardedProcs.pop()
|
||||
m = g.mods[prc.itemId.module]
|
||||
m = g.modules[prc.itemId.module]
|
||||
if sfForward in prc.flags:
|
||||
internalError(m.config, prc.info, "still forwarded: " & prc.name.s)
|
||||
|
||||
genProcLvl2(m, prc)
|
||||
genProcNoForward(m, prc)
|
||||
|
||||
proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
|
||||
let g = BModuleList(backend)
|
||||
@@ -2673,6 +2620,6 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
|
||||
genForwardedProcs(g)
|
||||
|
||||
for m in cgenModules(g):
|
||||
m.writeModule()
|
||||
m.writeModule(pending=true)
|
||||
writeMapping(config, g.mapping)
|
||||
if g.generatedHeader != nil: writeHeader(g.generatedHeader)
|
||||
|
||||
@@ -117,9 +117,9 @@ type
|
||||
BModuleList* = ref object of RootObj
|
||||
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Builder
|
||||
mapping*: Rope # the generated mapping file (if requested)
|
||||
mods*: seq[BModule] # list of all compiled modules
|
||||
modules*: seq[BModule] # list of all compiled modules
|
||||
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
|
||||
forwardedProcs*: seq[PSym] # procs that did not yet have a body
|
||||
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
|
||||
generatedHeader*: BModule
|
||||
typeInfoMarker*: TypeCacheWithOwner
|
||||
typeInfoMarkerV2*: TypeCacheWithOwner
|
||||
@@ -155,7 +155,6 @@ type
|
||||
forwTypeCache*: TypeCache # cache for forward declarations of types
|
||||
declaredThings*: IntSet # things we have declared in this .c file
|
||||
declaredProtos*: IntSet # prototypes we have declared in this .c file
|
||||
queue*: seq[PSym] # queue of procs to generate
|
||||
alive*: IntSet # symbol IDs of alive data as computed by `dce.nim`
|
||||
headerFiles*: seq[string] # needed headers to include
|
||||
typeInfoMarker*: TypeCache # needed for generating type information
|
||||
@@ -179,9 +178,6 @@ template config*(m: BModule): ConfigRef = m.g.config
|
||||
template config*(p: BProc): ConfigRef = p.module.g.config
|
||||
template vccAndC*(p: BProc): bool = p.module.config.cCompiler == ccVcc and p.module.config.backend == backendC
|
||||
|
||||
proc delayedCodegen*(m: BModule): bool {.inline.} =
|
||||
useAliveDataFromDce in m.flags or m.config.globalOptions.contains(optCompress)
|
||||
|
||||
proc includeHeader*(this: BModule; header: string) =
|
||||
if not this.headerFiles.contains header:
|
||||
this.headerFiles.add header
|
||||
|
||||
@@ -55,7 +55,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode =
|
||||
# replace ordinary method by dispatcher method:
|
||||
let disp = getDispatcher(result[0].sym)
|
||||
if disp != nil:
|
||||
result[0].typ = disp.typ
|
||||
result[0].typ() = disp.typ
|
||||
result[0].sym = disp
|
||||
# change the arguments to up/downcasts to fit the dispatcher's parameters:
|
||||
for i in 1..<result.len:
|
||||
@@ -123,8 +123,8 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) =
|
||||
|
||||
proc createDispatcher(s: PSym; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||
var disp = copySym(s, idgen)
|
||||
incl(disp, sfDispatcher)
|
||||
excl(disp, sfExported)
|
||||
incl(disp.flags, sfDispatcher)
|
||||
excl(disp.flags, sfExported)
|
||||
let old = disp.typ
|
||||
disp.typ = copyType(disp.typ, idgen, disp.typ.owner)
|
||||
copyTypeProps(g, idgen.module, disp.typ, old)
|
||||
@@ -133,7 +133,7 @@ proc createDispatcher(s: PSym; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
|
||||
disp.ast = copyTree(s.ast)
|
||||
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
|
||||
disp.locImpl.snippet = ""
|
||||
disp.loc.snippet = ""
|
||||
if s.typ.returnType != nil:
|
||||
if disp.ast.len > resultPos:
|
||||
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, idgen)
|
||||
|
||||
@@ -64,8 +64,7 @@
|
||||
# the target state is `except` block. For all states in `except` block
|
||||
# the target state is `finally` block. For all other states there is no
|
||||
# target state (0, as the first state can never be except nor finally).
|
||||
# - env var :curExc is created, where "current" exception within the iterator is stored,
|
||||
# also finallies use it to decide their exit logic
|
||||
# - env var :curExcLevel is created, finallies use it to decide their exit logic
|
||||
# - if there are finallies, env var :finallyPath is created. It contains exit state labels
|
||||
# for every finally level, and is changed in runtime in try, except, break, and return
|
||||
# nodes to control finally exit behavior.
|
||||
@@ -112,6 +111,7 @@
|
||||
# :state = 2 # And we continue to our finally
|
||||
# break :stateLoop
|
||||
# of 1: # Except
|
||||
# inc(:curExcLevel, -1) # Exception is caught
|
||||
# yield 1
|
||||
# :tmpResult = 3 # Return
|
||||
# :finalyPath[LEVEL] = 0 # Configure finally path.
|
||||
@@ -123,7 +123,7 @@
|
||||
# of 2: # Finally
|
||||
# yield 2
|
||||
# if :finallyPath[LEVEL] == 0: # This node is created by `newEndFinallyNode`
|
||||
# if :curExc == nil:
|
||||
# if :curExcLevel == 0:
|
||||
# :state = -1
|
||||
# return result = :tmpResult
|
||||
# else:
|
||||
@@ -139,7 +139,8 @@
|
||||
|
||||
import
|
||||
ast, msgs, idents,
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
|
||||
options
|
||||
|
||||
import std/tables
|
||||
|
||||
@@ -164,8 +165,7 @@ type
|
||||
fn: PSym
|
||||
tmpResultSym: PSym # Used when we return, but finally has to interfere
|
||||
finallyPathSym: PSym
|
||||
curExcSym: PSym # Current exception
|
||||
externExcSym: PSym # Extern exception: what would getCurrentException() return outside of closure iter
|
||||
curExcLevelSym: PSym # Current exception level (because exceptions are stacked)
|
||||
|
||||
states: seq[State] # The resulting states. Label is int literal.
|
||||
finallyPathStack: seq[FinallyTarget] # Stack of split blocks, whiles and finallies
|
||||
@@ -178,9 +178,6 @@ type
|
||||
varStates: Table[ItemId, int] # Used to detect if local variable belongs to multiple states
|
||||
finallyPathLen: PNode # int literal
|
||||
|
||||
nullifyCurExc: PNode # Empty node, if no yields in tries
|
||||
restoreExternExc: PNode # Empty node, id no yields in tries
|
||||
|
||||
const
|
||||
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
|
||||
nkCommentStmt, nkMixinStmt, nkBindStmt, nkTypeOfExpr} + procDefs
|
||||
@@ -199,7 +196,7 @@ proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
|
||||
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.idgen, ctx.fn, ctx.fn.info)
|
||||
result.typ = typ
|
||||
result.flagsImpl.incl sfNoInit
|
||||
result.flags.incl sfNoInit
|
||||
assert(not typ.isNil, "Env var needs a type")
|
||||
|
||||
let envParam = getEnvParam(ctx.fn)
|
||||
@@ -245,11 +242,10 @@ proc newFinallyPathAssign(ctx: var Ctx, level: int, label: PNode, info: TLineInf
|
||||
let fp = newFinallyPathAccess(ctx, level, info)
|
||||
result = newTree(nkAsgn, fp, label)
|
||||
|
||||
proc newCurExcAccess(ctx: var Ctx): PNode =
|
||||
if ctx.curExcSym.isNil:
|
||||
let getCurExc = ctx.g.callCodegenProc("getCurrentException")
|
||||
ctx.curExcSym = ctx.newEnvVar(":curExc", getCurExc.typ)
|
||||
ctx.newEnvVarAccess(ctx.curExcSym)
|
||||
proc newCurExcLevelAccess(ctx: var Ctx): PNode =
|
||||
if ctx.curExcLevelSym.isNil:
|
||||
ctx.curExcLevelSym = ctx.newEnvVar(":curExcLevel", ctx.g.getSysType(ctx.fn.info, tyInt16))
|
||||
ctx.newEnvVarAccess(ctx.curExcLevelSym)
|
||||
|
||||
proc newStateLabel(ctx: Ctx): PNode =
|
||||
ctx.g.newIntLit(TLineInfo(), 0)
|
||||
@@ -288,15 +284,6 @@ proc newTempVar(ctx: var Ctx, typ: PType, parent: PNode, initialValue: PNode = n
|
||||
assert(not typ.isNil, "Temp var needs a type")
|
||||
parent.add(ctx.newTempVarDef(result, initialValue))
|
||||
|
||||
proc newExternExcAccess(ctx: var Ctx): PNode =
|
||||
if ctx.externExcSym == nil:
|
||||
ctx.externExcSym = newSym(skVar, getIdent(ctx.g.cache, ":externExc"), ctx.idgen, ctx.fn, ctx.fn.info)
|
||||
ctx.externExcSym.typ = ctx.curExcSym.typ
|
||||
newSymNode(ctx.externExcSym, ctx.fn.info)
|
||||
|
||||
proc newRestoreExternException(ctx: var Ctx): PNode =
|
||||
ctx.g.callCodegenProc("closureIterSetExc", ctx.fn.info, ctx.newExternExcAccess())
|
||||
|
||||
proc hasYields(n: PNode): bool =
|
||||
# TODO: This is very inefficient. It traverses the node, looking for nkYieldStmt.
|
||||
case n.kind
|
||||
@@ -311,13 +298,21 @@ proc hasYields(n: PNode): bool =
|
||||
result = true
|
||||
break
|
||||
|
||||
proc newNullifyCurExc(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
# :curExc = nil
|
||||
let curExc = ctx.newCurExcAccess()
|
||||
proc newNullifyCurExcLevel(ctx: var Ctx, info: TLineInfo, decrement = false): PNode =
|
||||
# :curEcx = 0
|
||||
let curExc = ctx.newCurExcLevelAccess()
|
||||
curExc.info = info
|
||||
let nilnode = newNodeIT(nkNilLit, info, getSysType(ctx.g, info, tyNil))
|
||||
let nilnode = ctx.g.newIntLit(info, 0)
|
||||
result = newTree(nkAsgn, curExc, nilnode)
|
||||
|
||||
proc newChangeCurExcLevel(ctx: var Ctx, info: TLineInfo, by: int): PNode =
|
||||
# inc(:curEcxLevel, by)
|
||||
let curExc = ctx.newCurExcLevelAccess()
|
||||
curExc.info = info
|
||||
result = newTreeIT(nkCall, info, ctx.g.getSysType(info, tyVoid),
|
||||
newSymNode(ctx.g.getSysMagic(info, "inc", mInc)), curExc,
|
||||
ctx.g.newIntLit(info, by))
|
||||
|
||||
proc newOr(g: ModuleGraph, a, b: PNode): PNode {.inline.} =
|
||||
result = newTreeIT(nkCall, a.info, g.getSysType(a.info, tyBool),
|
||||
newSymNode(g.getSysMagic(a.info, "or", mOr)), a, b)
|
||||
@@ -349,7 +344,7 @@ proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
else:
|
||||
ifBranch = newNodeI(nkElse, c.info)
|
||||
|
||||
ifBranch.add(c[^1])
|
||||
ifBranch.add(newTreeI(nkStmtList, c.info, ctx.newChangeCurExcLevel(c.info, -1), c[^1]))
|
||||
ifStmt.add(ifBranch)
|
||||
|
||||
if ifStmt.len != 0:
|
||||
@@ -357,10 +352,9 @@ proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
else:
|
||||
result = ctx.g.emptyNode
|
||||
|
||||
proc addElseToExcept(ctx: var Ctx, n, gotoOut: PNode): PNode =
|
||||
proc addElseToExcept(ctx: var Ctx, n, gotoOut: PNode) =
|
||||
# We should adjust finallyPath to gotoOut if exception is handled
|
||||
# if there is no finally node next to this except, gotoOut must be nil
|
||||
result = n
|
||||
if n.kind == nkStmtList:
|
||||
if n[0].kind == nkIfStmt and n[0][^1].kind != nkElse:
|
||||
# Not all cases are covered, which means exception is not handled
|
||||
@@ -383,7 +377,6 @@ proc addElseToExcept(ctx: var Ctx, n, gotoOut: PNode): PNode =
|
||||
# raised one.
|
||||
n.add newTree(nkCall,
|
||||
newSymNode(ctx.g.getCompilerProc("popCurrentException")))
|
||||
n.add ctx.newNullifyCurExc(n.info)
|
||||
if gotoOut != nil:
|
||||
# We have a finally node following this except block, and exception is handled
|
||||
# Configure its path to continue normally
|
||||
@@ -457,7 +450,7 @@ proc newNotCall(g: ModuleGraph; e: PNode): PNode =
|
||||
|
||||
proc boolLit(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
|
||||
result = newIntLit(g, info, ord value)
|
||||
result.typ = getSysType(g, info, tyBool)
|
||||
result.typ() = getSysType(g, info, tyBool)
|
||||
|
||||
proc captureVar(c: var Ctx, s: PSym) =
|
||||
if c.varStates.getOrDefault(s.itemId) != localRequiresLifting:
|
||||
@@ -818,7 +811,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let (st, ex) = exprToStmtList(n[1])
|
||||
n.transitionSonsKind(nkBlockStmt)
|
||||
n.typ = nil
|
||||
n.typ() = nil
|
||||
n[1] = st
|
||||
result.add(n)
|
||||
result.add(ex)
|
||||
@@ -830,7 +823,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
# Generate the following code:
|
||||
# if :finallyPath[FINALLY_LEVEL] == 0:
|
||||
# if :curExc == nil:
|
||||
# if :curExcLevel == 0:
|
||||
# :state = -1
|
||||
# return result = :tmpResult
|
||||
# else:
|
||||
@@ -844,9 +837,9 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
|
||||
let excNilCmp = newTreeIT(nkCall,
|
||||
info, ctx.g.getSysType(info, tyBool),
|
||||
newSymNode(ctx.g.getSysMagic(info, "==", mEqRef), info),
|
||||
ctx.newCurExcAccess(),
|
||||
newNodeIT(nkNilLit, info, getSysType(ctx.g, info, tyNil)))
|
||||
newSymNode(ctx.g.getSysMagic(info, "==", mEqI), info),
|
||||
ctx.newCurExcLevelAccess(),
|
||||
ctx.g.newIntLit(info, 0))
|
||||
|
||||
let retStmt =
|
||||
block:
|
||||
@@ -863,7 +856,7 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
retStmt.flags.incl(nfNoRewrite)
|
||||
|
||||
let ifBody = newTree(nkIfStmt,
|
||||
newTree(nkElifBranch, excNilCmp, newTree(nkStmtList, ctx.newRestoreExternException(), retStmt)),
|
||||
newTree(nkElifBranch, excNilCmp, retStmt),
|
||||
newTree(nkElse,
|
||||
newTree(nkStmtList,
|
||||
newTreeI(nkRaiseStmt, info, ctx.g.emptyNode))))
|
||||
@@ -918,15 +911,14 @@ proc transformBreakStmt(ctx: var Ctx, n: PNode): PNode =
|
||||
result = n
|
||||
|
||||
proc transformReturnStmt(ctx: var Ctx, n: PNode): PNode =
|
||||
# "Returning" involves jumping along all the current finally path.
|
||||
# "Returning" involves jumping along all the cureent finally path.
|
||||
# The last finally should exit to state 0 which is a special case for last exit
|
||||
# (either return or propagating exception to the caller).
|
||||
# It is eccounted for in newEndFinallyNode.
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
# Returns prevent exception propagation
|
||||
result.add(ctx.nullifyCurExc)
|
||||
|
||||
result.add(ctx.newNullifyCurExcLevel(n.info))
|
||||
|
||||
var finallyChain = newSeq[PNode]()
|
||||
|
||||
@@ -950,7 +942,6 @@ proc transformReturnStmt(ctx: var Ctx, n: PNode): PNode =
|
||||
result.add(ctx.newJumpAlongFinallyChain(finallyChain, n.info))
|
||||
else:
|
||||
# There are no (split) finallies on the path, so we can return right away
|
||||
result.add(ctx.restoreExternExc)
|
||||
result.add(n)
|
||||
|
||||
proc transformBreaksAndReturns(ctx: var Ctx, n: PNode): PNode =
|
||||
@@ -961,7 +952,7 @@ proc transformBreaksAndReturns(ctx: var Ctx, n: PNode): PNode =
|
||||
# of nkContinueStmt: # By this point all relevant continues should be
|
||||
# lowered to breaks in transf.nim.
|
||||
of nkReturnStmt:
|
||||
if nfNoRewrite notin n.flags:
|
||||
if ctx.curFinallyLevel > 0 and nfNoRewrite notin n.flags:
|
||||
result = ctx.transformReturnStmt(n)
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
@@ -995,7 +986,6 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
|
||||
|
||||
of nkYieldStmt:
|
||||
result = addGotoOut(result, gotoOut)
|
||||
result = newTree(nkStmtList, ctx.restoreExternExc, result)
|
||||
|
||||
of nkElse, nkElseExpr:
|
||||
result[0] = addGotoOut(result[0], gotoOut)
|
||||
@@ -1065,7 +1055,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
|
||||
result.add(tryLabel)
|
||||
var tryBody = toStmtList(n[0])
|
||||
|
||||
var exceptBody = ctx.collectExceptState(n)
|
||||
let exceptBody = ctx.collectExceptState(n)
|
||||
var finallyBody = ctx.getFinallyNode(n)
|
||||
var exceptLabel, finallyLabel = ctx.g.emptyNode
|
||||
|
||||
@@ -1104,7 +1094,8 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
|
||||
inc ctx.curFinallyLevel
|
||||
ctx.finallyPathStack.add(FinallyTarget(n: n[^1], label: finallyLabel))
|
||||
|
||||
tryBody = ctx.transformClosureIteratorBody(tryBody, tryOut)
|
||||
if ctx.transformClosureIteratorBody(tryBody, tryOut) != tryBody:
|
||||
internalError(ctx.g.config, "transformClosureIteratorBody != tryBody")
|
||||
|
||||
if exceptBody.kind != nkEmpty:
|
||||
ctx.curExcLandingState = if finallyBody.kind != nkEmpty: finallyLabel
|
||||
@@ -1112,9 +1103,10 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
|
||||
discard ctx.newState(exceptBody, false, exceptLabel)
|
||||
|
||||
let normalOut = if finallyBody.kind != nkEmpty: gotoOut else: nil
|
||||
exceptBody = ctx.addElseToExcept(exceptBody, normalOut)
|
||||
ctx.addElseToExcept(exceptBody, normalOut)
|
||||
# echo "EXCEPT: ", renderTree(exceptBody)
|
||||
exceptBody = ctx.transformClosureIteratorBody(exceptBody, tryOut)
|
||||
if ctx.transformClosureIteratorBody(exceptBody, tryOut) != exceptBody:
|
||||
internalError(ctx.g.config, "transformClosureIteratorBody != exceptBody")
|
||||
|
||||
ctx.curExcLandingState = oldExcLandingState
|
||||
|
||||
@@ -1122,7 +1114,8 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
|
||||
discard ctx.finallyPathStack.pop()
|
||||
discard ctx.newState(finallyBody, false, finallyLabel)
|
||||
let finallyExit = newTree(nkGotoState, ctx.newFinallyPathAccess(ctx.curFinallyLevel - 1, finallyBody.info))
|
||||
finallyBody = ctx.transformClosureIteratorBody(finallyBody, finallyExit)
|
||||
if ctx.transformClosureIteratorBody(finallyBody, finallyExit) != finallyBody:
|
||||
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
|
||||
dec ctx.curFinallyLevel
|
||||
|
||||
of nkGotoState, nkForStmt:
|
||||
@@ -1208,6 +1201,34 @@ proc createExceptionTable(ctx: var Ctx): PNode {.inline.} =
|
||||
for i in 0 .. ctx.states.high:
|
||||
result.add(ctx.states[i].excLandingState)
|
||||
|
||||
proc newExceptBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
# Generates code:
|
||||
# :state = exceptionTable[:state]
|
||||
# if :state == 0:
|
||||
# raise
|
||||
result = newNodeI(nkStmtList, info)
|
||||
|
||||
let intTyp = ctx.g.getSysType(info, tyInt)
|
||||
let boolTyp = ctx.g.getSysType(info, tyBool)
|
||||
|
||||
# :state = exceptionTable[:state]
|
||||
result.add ctx.newStateAssgn(
|
||||
newTreeIT(nkBracketExpr, info, intTyp,
|
||||
ctx.createExceptionTable(),
|
||||
ctx.newStateAccess()))
|
||||
|
||||
# if :state == 0: raise
|
||||
block:
|
||||
let cond = newTreeIT(nkCall, info, boolTyp,
|
||||
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(0, intTyp))
|
||||
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
|
||||
let ifBranch = newTree(nkElifBranch, cond, raiseStmt)
|
||||
let ifStmt = newTree(nkIfStmt, ifBranch)
|
||||
result.add(ifStmt)
|
||||
|
||||
proc wrapIntoTryExcept(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
# Generates code:
|
||||
# var :tmp = nil
|
||||
@@ -1215,45 +1236,24 @@ proc wrapIntoTryExcept(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
# body
|
||||
# except:
|
||||
# :state = exceptionTable[:state]
|
||||
# :curExc = getCurrentException()
|
||||
# if :state == 0:
|
||||
# closureIterSetExc(:externExc)
|
||||
# raise
|
||||
# if :state == 0:
|
||||
# raise
|
||||
# :tmp = getCurrentException()
|
||||
#
|
||||
# pushCurrentException(:curExc)
|
||||
# pushCurrentException(:tmp)
|
||||
|
||||
let info = ctx.fn.info
|
||||
let getCurExc = ctx.g.callCodegenProc("getCurrentException")
|
||||
let exceptBody = newTreeI(nkStmtList, info,
|
||||
ctx.newStateAssgn(
|
||||
newTreeIT(nkBracketExpr, info, ctx.g.getSysType(info, tyInt),
|
||||
ctx.createExceptionTable(),
|
||||
ctx.newStateAccess())),
|
||||
newTreeI(nkFastAsgn, info, ctx.newCurExcAccess(), getCurExc))
|
||||
let tryBody = newTree(nkStmtList, n)
|
||||
let exceptBody = ctx.newExceptBody(ctx.fn.info)
|
||||
let exceptBranch = newTree(nkExceptBranch, exceptBody)
|
||||
|
||||
result = newTree(nkStmtList)
|
||||
result.add newTree(nkTryStmt,
|
||||
newTree(nkStmtList, n),
|
||||
newTree(nkExceptBranch, exceptBody))
|
||||
let getCurExc = ctx.g.callCodegenProc("getCurrentException")
|
||||
let tempExc = ctx.newTempVar(getCurExc.typ, result)
|
||||
result.add newTree(nkTryStmt, tryBody, exceptBranch)
|
||||
exceptBody.add ctx.newTempVarAsgn(tempExc, getCurExc)
|
||||
|
||||
# if :state == 0:
|
||||
# closureIterSetExc(:externExc)
|
||||
# raise
|
||||
block:
|
||||
let boolTyp = ctx.g.getSysType(info, tyBool)
|
||||
let intTyp = ctx.g.getSysType(info, tyInt)
|
||||
let cond = newTreeIT(nkCall, info, boolTyp,
|
||||
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(0, intTyp))
|
||||
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.newCurExcAccess())
|
||||
let ifBody = newTree(nkStmtList, ctx.newRestoreExternException(), raiseStmt)
|
||||
let ifBranch = newTree(nkElifBranch, cond, ifBody)
|
||||
let ifStmt = newTree(nkIfStmt, ifBranch)
|
||||
result.add(ifStmt)
|
||||
|
||||
result.add newTree(nkCall, newSymNode(ctx.g.getCompilerProc("pushCurrentException")), ctx.newCurExcAccess())
|
||||
result.add newTree(nkCall, newSymNode(ctx.g.getCompilerProc("pushCurrentException")), ctx.newTempVarAccess(tempExc))
|
||||
result.add ctx.newChangeCurExcLevel(n.info, 1)
|
||||
|
||||
proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
|
||||
# while true:
|
||||
@@ -1276,19 +1276,6 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
|
||||
blockStmt.add(blockBody)
|
||||
loopBody.add(blockStmt)
|
||||
|
||||
if ctx.hasExceptions:
|
||||
# Since we have yields in tries, we must switch current exception
|
||||
# between the iter and "outer world"
|
||||
# var :externExc = getCurrentException()
|
||||
# closureIterSetExc(:curExc)
|
||||
let getCurExc = ctx.g.callCodegenProc("getCurrentException")
|
||||
discard ctx.newExternExcAccess()
|
||||
let setCurExc = ctx.g.callCodegenProc("closureIterSetExc", n.info, ctx.newCurExcAccess())
|
||||
result = newTreeI(nkStmtList, n.info,
|
||||
ctx.newTempVarDef(ctx.externExcSym, getCurExc),
|
||||
setCurExc,
|
||||
result)
|
||||
|
||||
proc countStateOccurences(ctx: var Ctx, n: PNode, stateOccurences: var openArray[int]) =
|
||||
## Find all nkGotoState(stateIdx) nodes that do not follow nkYield.
|
||||
## For every such node increment stateOccurences[stateIdx]
|
||||
@@ -1306,15 +1293,16 @@ proc countStateOccurences(ctx: var Ctx, n: PNode, stateOccurences: var openArray
|
||||
|
||||
proc replaceDeletedStates(ctx: var Ctx, n: PNode): PNode =
|
||||
result = n
|
||||
if n.kind == nkIntLit:
|
||||
let idx = n.intVal
|
||||
if idx >= 0 and idx < ctx.states.len and ctx.states[idx].label == n and ctx.states[idx].deletable:
|
||||
let gt = ctx.replaceDeletedStates(skipStmtList(ctx.states[idx].body))
|
||||
assert(gt.kind == nkGotoState)
|
||||
result = gt[0]
|
||||
else:
|
||||
for i in 0 ..< n.safeLen:
|
||||
n[i] = ctx.replaceDeletedStates(n[i])
|
||||
for i in 0 ..< n.safeLen:
|
||||
let c = n[i]
|
||||
if c.kind == nkIntLit:
|
||||
let idx = c.intVal
|
||||
if idx >= 0 and idx < ctx.states.len and ctx.states[idx].label == c and ctx.states[idx].deletable:
|
||||
let gt = ctx.replaceDeletedStates(skipStmtList(ctx.states[idx].body))
|
||||
assert(gt.kind == nkGotoState)
|
||||
n[i] = gt[0]
|
||||
else:
|
||||
n[i] = ctx.replaceDeletedStates(c)
|
||||
|
||||
proc replaceInlinedStates(ctx: var Ctx, n: PNode): PNode =
|
||||
## Find all nkGotoState(stateIdx) nodes that do not follow nkYield.
|
||||
@@ -1345,7 +1333,6 @@ proc optimizeStates(ctx: var Ctx) =
|
||||
# Replace deletable state labels to labels of respective non-empty states
|
||||
for i in 0 .. ctx.states.high:
|
||||
ctx.states[i].body = ctx.replaceDeletedStates(ctx.states[i].body)
|
||||
ctx.states[i].excLandingState = ctx.replaceDeletedStates(ctx.states[i].excLandingState)
|
||||
|
||||
# Remove deletable states
|
||||
var i = 0
|
||||
@@ -1394,7 +1381,7 @@ proc detectCapturedVars(c: var Ctx, n: PNode, stateIdx: int) =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
let s = n.sym
|
||||
if s.kind in {skResult, skVar, skLet, skForVar, skTemp} and sfGlobal notin s.flags and s.owner == c.fn and s != c.externExcSym:
|
||||
if s.kind in {skResult, skVar, skLet, skForVar, skTemp} and sfGlobal notin s.flags and s.owner == c.fn:
|
||||
let vs = c.varStates.getOrDefault(s.itemId, localNotSeen)
|
||||
if vs == localNotSeen: # First seing this variable
|
||||
c.varStates[s.itemId] = stateIdx
|
||||
@@ -1467,16 +1454,10 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
|
||||
ctx.curExcLandingState = ctx.newStateLabel()
|
||||
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), idgen, fn, fn.info)
|
||||
|
||||
|
||||
ctx.nullifyCurExc = newTree(nkStmtList)
|
||||
ctx.restoreExternExc = newTree(nkStmtList)
|
||||
|
||||
var n = n.toStmtList
|
||||
# echo "transformed into ", n
|
||||
|
||||
discard ctx.newState(n, false, nil)
|
||||
|
||||
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))
|
||||
|
||||
var ns = false
|
||||
@@ -1489,10 +1470,6 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
# Splitting transformation
|
||||
discard ctx.transformClosureIteratorBody(n, gotoOut)
|
||||
|
||||
if ctx.hasExceptions:
|
||||
ctx.nullifyCurExc.add(ctx.newNullifyCurExc(fn.info))
|
||||
ctx.restoreExternExc.add(ctx.newRestoreExternException())
|
||||
|
||||
# Assign state label indexes
|
||||
for i in 0 .. ctx.states.high:
|
||||
ctx.states[i].label.intVal = i
|
||||
@@ -1510,9 +1487,7 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
let body = ctx.transformStateAssignments(s.body)
|
||||
caseDispatcher.add newTreeI(nkOfBranch, body.info, s.label, body)
|
||||
|
||||
caseDispatcher.add newTreeI(nkElse, n.info,
|
||||
newTree(nkStmtList, ctx.restoreExternExc,
|
||||
newTreeI(nkReturnStmt, n.info, g.emptyNode)))
|
||||
caseDispatcher.add newTreeI(nkElse, n.info, newTreeI(nkReturnStmt, n.info, g.emptyNode))
|
||||
|
||||
result = wrapIntoStateLoop(ctx, caseDispatcher)
|
||||
result = liftLocals(ctx, result)
|
||||
|
||||
@@ -364,7 +364,6 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||
result = false
|
||||
of "panics": result = contains(conf.globalOptions, optPanics)
|
||||
of "jsbigint64": result = contains(conf.globalOptions, optJsBigInt64)
|
||||
of "mangle": result = contains(conf.globalOptions, optItaniumMangle)
|
||||
else:
|
||||
result = false
|
||||
invalidCmdLineOption(conf, passCmd1, switch, info)
|
||||
@@ -498,8 +497,6 @@ proc parseCommand*(command: string): Command =
|
||||
of "secret": cmdInteractive
|
||||
of "nop", "help": cmdNop
|
||||
of "jsonscript": cmdJsonscript
|
||||
of "nifc": cmdNifC # generate C from NIF files
|
||||
of "ic": cmdIc # generate .build.nif for nifmake
|
||||
else: cmdUnknown
|
||||
|
||||
proc setCmd*(conf: ConfigRef, cmd: Command) =
|
||||
@@ -512,11 +509,6 @@ proc setCmd*(conf: ConfigRef, cmd: Command) =
|
||||
of cmdCompileToOC: conf.backend = backendObjc
|
||||
of cmdCompileToJS: conf.backend = backendJs
|
||||
of cmdCompileToNif: conf.backend = backendNif
|
||||
of cmdNifC:
|
||||
conf.backend = backendC # NIF to C compilation
|
||||
of cmdM:
|
||||
# cmdM requires optCompress for proper IC handling (include files, etc.)
|
||||
conf.globalOptions.incl optCompress
|
||||
else: discard
|
||||
|
||||
proc setCommandEarly*(conf: ConfigRef, command: string) =
|
||||
@@ -770,16 +762,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
conf.globalOptions.excl optCDebug
|
||||
else:
|
||||
localError(conf, info, "expected native|gdb|on|off but found " & arg)
|
||||
of "mangle":
|
||||
case arg.normalize
|
||||
of "nim":
|
||||
conf.globalOptions.excl optItaniumMangle
|
||||
of "cpp":
|
||||
conf.globalOptions.incl optItaniumMangle
|
||||
else:
|
||||
localError(conf, info, "expected nim|cpp but found " & arg)
|
||||
of "compress":
|
||||
conf.globalOptions.incl optCompress
|
||||
of "g": # alias for --debugger:native
|
||||
conf.globalOptions.incl optCDebug
|
||||
conf.options.incl optLineDir
|
||||
@@ -902,19 +884,11 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "import":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
let m = findModule(conf, arg, toFullPath(conf, info)).string
|
||||
if m.len == 0:
|
||||
localError(conf, info, "Cannot resolve filename: " & arg)
|
||||
else:
|
||||
conf.implicitImports.add m
|
||||
conf.implicitImports.add findModule(conf, arg, toFullPath(conf, info)).string
|
||||
of "include":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
let m = findModule(conf, arg, toFullPath(conf, info)).string
|
||||
if m.len == 0:
|
||||
localError(conf, info, "Cannot resolve filename: " & arg)
|
||||
else:
|
||||
conf.implicitIncludes.add m
|
||||
conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
|
||||
of "listcmd":
|
||||
processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
|
||||
of "asm":
|
||||
@@ -1000,8 +974,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
# xxx maybe also ic, since not in help?
|
||||
if pass in {passCmd2, passPP}:
|
||||
case arg.normalize
|
||||
of "on": conf.ic = true
|
||||
of "legacy": conf.symbolFiles = v2Sf
|
||||
of "on": conf.symbolFiles = v2Sf
|
||||
of "off": conf.symbolFiles = disabledSf
|
||||
of "writeonly": conf.symbolFiles = writeOnlySf
|
||||
of "readonly": conf.symbolFiles = readOnlySf
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
## for details. Note this is a first implementation and only the "Concept matching"
|
||||
## section has been implemented.
|
||||
|
||||
import ast, semdata, lookups, lineinfos, idents, msgs, renderer, types, layeredtable
|
||||
import ast, astalgo, semdata, lookups, lineinfos, idents, msgs, renderer, types, layeredtable
|
||||
|
||||
import std/sets
|
||||
import std/intsets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -29,7 +29,7 @@ proc declareSelf(c: PContext; info: TLineInfo) =
|
||||
let ow = getCurrOwner(c)
|
||||
let s = newSym(skType, getIdent(c.cache, "Self"), c.idgen, ow, info)
|
||||
s.typ = newType(tyTypeDesc, c.idgen, ow)
|
||||
s.typ.incl {tfUnresolved, tfPacked}
|
||||
s.typ.flags.incl {tfUnresolved, tfPacked}
|
||||
s.typ.add newType(tyEmpty, c.idgen, ow)
|
||||
addDecl(c, s, info)
|
||||
|
||||
@@ -73,20 +73,18 @@ type
|
||||
MatchFlags* = enum
|
||||
mfDontBind # Do not bind generic parameters
|
||||
mfCheckGeneric # formal <- formal comparison as opposed to formal <- operand
|
||||
|
||||
ConceptTypePair = tuple[conceptId, typeId: ItemId]
|
||||
## Pair of (concept type id, implementation type id) used for cycle detection
|
||||
|
||||
|
||||
MatchCon = object ## Context we pass around during concept matching.
|
||||
bindings: LayeredIdTable
|
||||
marker: HashSet[ConceptTypePair] ## Tracks (concept, type) pairs being checked to detect cycles.
|
||||
marker: IntSet ## Some protection against wild runaway recursions.
|
||||
potentialImplementation: PType ## the concrete type that might match the concept we try to match.
|
||||
magic: TMagic ## mArrGet and mArrPut is wrong in system.nim and
|
||||
## cannot be fixed that easily.
|
||||
## Thus we special case it here.
|
||||
concpt: PType ## current concept being evaluated
|
||||
depthCount = 0
|
||||
flags: set[MatchFlags]
|
||||
|
||||
|
||||
MatchKind = enum
|
||||
mkNoMatch, mkSubset, mkSame
|
||||
|
||||
@@ -139,7 +137,7 @@ proc bindParam(c: PContext, m: var MatchCon; key, v: PType): bool {. discardable
|
||||
# check previously bound value
|
||||
if not matchType(c, old, value, m):
|
||||
return false
|
||||
elif key.hasElementType and not key.elementType.isNil and key.elementType.kind != tyNone:
|
||||
elif key.hasElementType and key.elementType.kind != tyNone:
|
||||
# check constaint
|
||||
if matchType(c, unrollGenericParam(key), value, m) == false:
|
||||
return false
|
||||
@@ -190,48 +188,32 @@ iterator traverseTyOr(t: PType): PType {. closure .}=
|
||||
proc matchConceptToImpl(c: PContext, f, potentialImpl: PType; m: var MatchCon): bool =
|
||||
assert not(potentialImpl.reduceToBase.kind == tyConcept)
|
||||
let concpt = f.reduceToBase
|
||||
|
||||
# Handle self-referential concepts: when a concept references itself in its body
|
||||
# (e.g., `A = concept; proc test(x: Self, y: A)`), the inner type A has n=nil.
|
||||
# We detect this by checking if the concept has the same symbol name as the
|
||||
# one we're currently matching and has no body (n=nil).
|
||||
if concpt.n.isNil:
|
||||
if concpt.sym != nil and m.concpt.sym != nil and
|
||||
concpt.sym == m.concpt.sym:
|
||||
# Self-reference: check if potentialImpl matches what we're already checking
|
||||
return potentialImpl.id == m.potentialImplementation.id
|
||||
# Concept without body that's not a self-reference - cannot match
|
||||
return false
|
||||
|
||||
# Cycle detection: track (concept, type) pairs to prevent infinite recursion.
|
||||
# Returns true on cycle (coinductive semantics) to support co-dependent concepts.
|
||||
let pair: ConceptTypePair = (concpt.itemId, potentialImpl.itemId)
|
||||
if pair in m.marker:
|
||||
if m.depthCount > 0:
|
||||
# concepts that are more then 2 levels deep are treated like
|
||||
# tyAnything to stop dependencies from getting out of control
|
||||
return true
|
||||
m.marker.incl pair
|
||||
|
||||
var efPot = potentialImpl
|
||||
if potentialImpl.isSelf:
|
||||
if m.concpt.n == concpt.n:
|
||||
m.marker.excl pair
|
||||
return true
|
||||
efPot = m.potentialImplementation
|
||||
|
||||
|
||||
var oldBindings = m.bindings
|
||||
m.bindings = newTypeMapLayer(m.bindings)
|
||||
let oldPotentialImplementation = m.potentialImplementation
|
||||
m.potentialImplementation = efPot
|
||||
let oldConcept = m.concpt
|
||||
m.concpt = concpt
|
||||
|
||||
|
||||
var invocation: PType = nil
|
||||
if f.kind in {tyGenericInvocation, tyGenericInst}:
|
||||
invocation = f
|
||||
inc m.depthCount
|
||||
result = processConcept(c, concpt, invocation, oldBindings, m)
|
||||
dec m.depthCount
|
||||
m.potentialImplementation = oldPotentialImplementation
|
||||
m.concpt = oldConcept
|
||||
m.bindings = oldBindings
|
||||
m.marker.excl pair
|
||||
|
||||
proc cmpConceptDefs(c: PContext, fn, an: PNode, m: var MatchCon): bool=
|
||||
if fn.kind != an.kind:
|
||||
@@ -281,22 +263,6 @@ proc conceptsMatch(c: PContext, fc, ac: PType; m: var MatchCon): MatchKind =
|
||||
return mkNoMatch
|
||||
return mkSubset
|
||||
|
||||
proc isObjectSubtype(f, a: PType): bool =
|
||||
var t = a
|
||||
result = false
|
||||
while t != nil:
|
||||
t = t.baseClass
|
||||
if t == nil:
|
||||
break
|
||||
t = t.skipTypes({tyPtr,tyRef})
|
||||
if t == nil:
|
||||
break
|
||||
if t.kind != tyObject:
|
||||
break
|
||||
if sameObjectTypes(f, t):
|
||||
result = true
|
||||
break
|
||||
|
||||
proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool =
|
||||
## The heart of the concept matching process. 'f' is the formal parameter of some
|
||||
## routine inside the concept that we're looking for. 'a' is the formal parameter
|
||||
@@ -305,10 +271,7 @@ proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool =
|
||||
var
|
||||
a = ao
|
||||
f = fo
|
||||
if a.isSelf:
|
||||
if m.magic in {mArrPut, mArrGet}:
|
||||
return false
|
||||
a = m.potentialImplementation
|
||||
|
||||
if a.kind in bindableTypes:
|
||||
a = existingBinding(m, ao)
|
||||
if a == ao and a.kind == tyGenericParam and a.hasElementType and a.elementType.kind != tyNone:
|
||||
@@ -361,8 +324,6 @@ proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool =
|
||||
result = a.base.sym == f.sym
|
||||
else:
|
||||
result = sameType(f, a)
|
||||
if not result and f.kind == tyObject and a.kind == tyObject:
|
||||
result = isObjectSubtype(f, a)
|
||||
of tyEmpty, tyString, tyCstring, tyPointer, tyNil, tyUntyped, tyTyped, tyVoid:
|
||||
result = a.skipTypes(ignorableForArgType).kind == f.kind
|
||||
of tyBool, tyChar, tyInt..tyUInt64:
|
||||
@@ -376,11 +337,8 @@ proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool =
|
||||
result = true
|
||||
else:
|
||||
let ak = a.skipTypes(ignorableForArgType - {f.kind})
|
||||
if ak.kind == f.kind:
|
||||
if f.base.kind == tyNone:
|
||||
result = true
|
||||
elif f.kidsLen == ak.kidsLen:
|
||||
result = matchKids(c, f, ak, m)
|
||||
if ak.kind == f.kind and f.kidsLen == ak.kidsLen:
|
||||
result = matchKids(c, f, ak, m)
|
||||
of tyGenericInvocation, tyGenericInst:
|
||||
result = false
|
||||
let ea = a.skipTypes(ignorableForArgType)
|
||||
@@ -394,14 +352,6 @@ proc matchType(c: PContext; fo, ao: PType; m: var MatchCon): bool =
|
||||
if not matchType(c, f[i], ea[i], m):
|
||||
result = false
|
||||
break
|
||||
elif f.kind == tyGenericInvocation:
|
||||
# bind potential generic constraints into body
|
||||
let body = f.base
|
||||
for i in 1 ..< len(f):
|
||||
bindParam(c,m,body[i-1], f[i])
|
||||
result = matchType(c, body, a, m)
|
||||
else: # tyGenericInst
|
||||
result = matchType(c, f.last, a, m)
|
||||
of tyOrdinal:
|
||||
result = isOrdinalType(a, allowEnumWithHoles = false) or a.kind == tyGenericParam
|
||||
of tyStatic:
|
||||
@@ -628,7 +578,7 @@ proc conceptMatch*(c: PContext; concpt, arg: PType; bindings: var LayeredIdTable
|
||||
## `C[S, T]` parent type that we look for. We need this because we need to store bindings
|
||||
## for 'S' and 'T' inside 'bindings' on a successful match. It is very important that
|
||||
## we do not add any bindings at all on an unsuccessful match!
|
||||
var m = MatchCon(bindings: bindings, potentialImplementation: arg, concpt: concpt, flags: flags, marker: initHashSet[ConceptTypePair]())
|
||||
var m = MatchCon(bindings: bindings, potentialImplementation: arg, concpt: concpt, flags: flags)
|
||||
if arg.isConcept:
|
||||
result = conceptsMatch(c, concpt.reduceToBase, arg.reduceToBase, m) >= mkSubset
|
||||
elif arg.acceptsAllTypes:
|
||||
|
||||
@@ -173,5 +173,4 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasXorSet")
|
||||
|
||||
defineSymbol("nimHasSetLengthSeqUninitMagic")
|
||||
defineSymbol("nimHasPreviewDuplicateModuleError")
|
||||
|
||||
|
||||
@@ -1,389 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2025 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Generate a .build.nif file for nifmake from a Nim project.
|
||||
## This enables incremental and parallel compilation using the `m` switch.
|
||||
|
||||
import std / [os, tables, sets, times, osproc, strutils]
|
||||
import options, msgs, lineinfos, pathutils
|
||||
|
||||
import "../dist/nimony/src/lib" / [nifstreams, nifcursors, bitabs, nifreader, nifbuilder]
|
||||
import "../dist/nimony/src/gear2" / modnames
|
||||
|
||||
type
|
||||
FilePair = object
|
||||
nimFile: string
|
||||
modname: string
|
||||
|
||||
Node = ref object
|
||||
files: seq[FilePair] # main file + includes
|
||||
deps: seq[int] # indices into DepContext.nodes
|
||||
id: int
|
||||
|
||||
DepContext = object
|
||||
config: ConfigRef
|
||||
nifler: string
|
||||
nodes: seq[Node]
|
||||
processedModules: Table[string, int] # modname -> node index
|
||||
includeStack: seq[string]
|
||||
|
||||
proc toPair(c: DepContext; f: string): FilePair =
|
||||
FilePair(nimFile: f, modname: moduleSuffix(f, cast[seq[string]](c.config.searchPaths)))
|
||||
|
||||
proc depsFile(c: DepContext; f: FilePair): string =
|
||||
getNimcacheDir(c.config).string / f.modname & ".deps.nif"
|
||||
|
||||
proc parsedFile(c: DepContext; f: FilePair): string =
|
||||
getNimcacheDir(c.config).string / f.modname & ".p.nif"
|
||||
|
||||
proc semmedFile(c: DepContext; f: FilePair): string =
|
||||
getNimcacheDir(c.config).string / f.modname & ".nif"
|
||||
|
||||
proc findNifler(): string =
|
||||
# Look for nifler in common locations
|
||||
let nimDir = getAppDir()
|
||||
result = nimDir / "nifler"
|
||||
if not fileExists(result):
|
||||
result = findExe("nifler")
|
||||
|
||||
proc findNifmake(): string =
|
||||
# Look for nifmake in common locations
|
||||
# Try relative to nim executable
|
||||
let nimDir = getAppDir()
|
||||
result = nimDir / "nifmake"
|
||||
if not fileExists(result):
|
||||
result = findExe("nifmake")
|
||||
|
||||
proc runNifler(c: DepContext; nimFile: string): bool =
|
||||
## Run nifler deps on a file if needed. Returns true on success.
|
||||
let pair = c.toPair(nimFile)
|
||||
let depsPath = c.depsFile(pair)
|
||||
|
||||
# Check if deps file is up-to-date
|
||||
if fileExists(depsPath) and fileExists(nimFile):
|
||||
if getLastModificationTime(depsPath) > getLastModificationTime(nimFile):
|
||||
return true # Already up-to-date
|
||||
|
||||
# Create output directory if needed
|
||||
createDir(parentDir(depsPath))
|
||||
|
||||
# Run nifler deps
|
||||
let cmd = quoteShell(c.nifler) & " deps " & quoteShell(nimFile) & " " & quoteShell(depsPath)
|
||||
let exitCode = execShellCmd(cmd)
|
||||
result = exitCode == 0
|
||||
|
||||
proc resolveFile(c: DepContext; origin, toResolve: string): string =
|
||||
## Resolve an import path relative to origin file
|
||||
# Handle std/ prefix
|
||||
var path = toResolve
|
||||
if path.startsWith("std/"):
|
||||
path = path.substr(4)
|
||||
|
||||
# Try relative to origin first
|
||||
let originDir = parentDir(origin)
|
||||
result = originDir / path.addFileExt("nim")
|
||||
if fileExists(result):
|
||||
return result
|
||||
|
||||
# Try search paths
|
||||
for searchPath in c.config.searchPaths:
|
||||
result = searchPath.string / path.addFileExt("nim")
|
||||
if fileExists(result):
|
||||
return result
|
||||
|
||||
result = ""
|
||||
|
||||
proc traverseDeps(c: var DepContext; pair: FilePair; current: Node)
|
||||
|
||||
proc processInclude(c: var DepContext; includePath: string; current: Node) =
|
||||
let resolved = resolveFile(c, current.files[current.files.len - 1].nimFile, includePath)
|
||||
if resolved.len == 0 or not fileExists(resolved):
|
||||
return
|
||||
|
||||
# Check for recursive includes
|
||||
for s in c.includeStack:
|
||||
if s == resolved:
|
||||
return # Skip recursive include
|
||||
|
||||
c.includeStack.add resolved
|
||||
current.files.add c.toPair(resolved)
|
||||
traverseDeps(c, c.toPair(resolved), current)
|
||||
discard c.includeStack.pop()
|
||||
|
||||
proc processImport(c: var DepContext; importPath: string; current: Node) =
|
||||
let resolved = resolveFile(c, current.files[0].nimFile, importPath)
|
||||
if resolved.len == 0 or not fileExists(resolved):
|
||||
return
|
||||
|
||||
let pair = c.toPair(resolved)
|
||||
let existingIdx = c.processedModules.getOrDefault(pair.modname, -1)
|
||||
|
||||
if existingIdx == -1:
|
||||
# New module - create node and process it
|
||||
let newNode = Node(files: @[pair], id: c.nodes.len)
|
||||
current.deps.add newNode.id
|
||||
c.processedModules[pair.modname] = newNode.id
|
||||
c.nodes.add newNode
|
||||
traverseDeps(c, pair, newNode)
|
||||
else:
|
||||
# Already processed - just add dependency
|
||||
if existingIdx notin current.deps:
|
||||
current.deps.add existingIdx
|
||||
|
||||
proc readDepsFile(c: var DepContext; pair: FilePair; current: Node) =
|
||||
## Read a .deps.nif file and process imports/includes
|
||||
let depsPath = c.depsFile(pair)
|
||||
if not fileExists(depsPath):
|
||||
return
|
||||
|
||||
var s = nifstreams.open(depsPath)
|
||||
defer: nifstreams.close(s)
|
||||
discard processDirectives(s.r)
|
||||
|
||||
var t = next(s)
|
||||
if t.kind != ParLe:
|
||||
return
|
||||
|
||||
# Skip to content (past stmts tag)
|
||||
t = next(s)
|
||||
|
||||
while t.kind != EofToken:
|
||||
if t.kind == ParLe:
|
||||
let tag = pool.tags[t.tagId]
|
||||
case tag
|
||||
of "import", "fromimport":
|
||||
# Read import path
|
||||
t = next(s)
|
||||
# Check for "when" marker (conditional import)
|
||||
if t.kind == Ident and pool.strings[t.litId] == "when":
|
||||
t = next(s) # skip it, still process the import
|
||||
# Handle path expression (could be ident, string, or infix like std/foo)
|
||||
var importPath = ""
|
||||
if t.kind == Ident:
|
||||
importPath = pool.strings[t.litId]
|
||||
elif t.kind == StringLit:
|
||||
importPath = pool.strings[t.litId]
|
||||
elif t.kind == ParLe and pool.tags[t.tagId] == "infix":
|
||||
# Handle std / foo style imports
|
||||
t = next(s) # skip infix tag
|
||||
if t.kind == Ident: # operator (/)
|
||||
t = next(s)
|
||||
if t.kind == Ident: # first part (std)
|
||||
importPath = pool.strings[t.litId]
|
||||
t = next(s)
|
||||
if t.kind == Ident: # second part (foo)
|
||||
importPath = importPath & "/" & pool.strings[t.litId]
|
||||
if importPath.len > 0:
|
||||
processImport(c, importPath, current)
|
||||
# Skip to end of import node
|
||||
var depth = 1
|
||||
while depth > 0:
|
||||
t = next(s)
|
||||
if t.kind == ParLe: inc depth
|
||||
elif t.kind == ParRi: dec depth
|
||||
of "include":
|
||||
# Read include path
|
||||
t = next(s)
|
||||
if t.kind == Ident and pool.strings[t.litId] == "when":
|
||||
t = next(s) # skip conditional marker
|
||||
var includePath = ""
|
||||
if t.kind == Ident:
|
||||
includePath = pool.strings[t.litId]
|
||||
elif t.kind == StringLit:
|
||||
includePath = pool.strings[t.litId]
|
||||
if includePath.len > 0:
|
||||
processInclude(c, includePath, current)
|
||||
# Skip to end
|
||||
var depth = 1
|
||||
while depth > 0:
|
||||
t = next(s)
|
||||
if t.kind == ParLe: inc depth
|
||||
elif t.kind == ParRi: dec depth
|
||||
else:
|
||||
# Skip unknown node
|
||||
var depth = 1
|
||||
while depth > 0:
|
||||
t = next(s)
|
||||
if t.kind == ParLe: inc depth
|
||||
elif t.kind == ParRi: dec depth
|
||||
t = next(s)
|
||||
|
||||
proc traverseDeps(c: var DepContext; pair: FilePair; current: Node) =
|
||||
## Process a module: run nifler and read deps
|
||||
if not runNifler(c, pair.nimFile):
|
||||
rawMessage(c.config, errGenerated, "nifler failed for: " & pair.nimFile)
|
||||
return
|
||||
readDepsFile(c, pair, current)
|
||||
|
||||
proc generateBuildFile(c: DepContext): string =
|
||||
## Generate the .build.nif file for nifmake
|
||||
createDir("nifcache")
|
||||
result = "nifcache" / c.nodes[0].files[0].modname & ".build.nif"
|
||||
#getNimcacheDir(c.config).string / c.nodes[0].files[0].modname & ".build.nif"
|
||||
|
||||
var b = nifbuilder.open(result)
|
||||
defer: b.close()
|
||||
|
||||
b.addHeader("nim ic", "nifmake")
|
||||
b.addTree "stmts"
|
||||
|
||||
# Define nifler command
|
||||
b.addTree "cmd"
|
||||
b.addSymbolDef "nifler"
|
||||
b.addStrLit c.nifler
|
||||
b.addStrLit "parse"
|
||||
b.addStrLit "--deps"
|
||||
b.addTree "input"
|
||||
b.endTree()
|
||||
b.addTree "output"
|
||||
b.endTree()
|
||||
b.endTree()
|
||||
|
||||
# Define nim m command
|
||||
b.addTree "cmd"
|
||||
b.addSymbolDef "nim_m"
|
||||
b.addStrLit getAppFilename()
|
||||
b.addStrLit "m"
|
||||
b.addStrLit "--nimcache:nifcache"
|
||||
# Add search paths
|
||||
for p in c.config.searchPaths:
|
||||
b.addStrLit "--path:" & p.string
|
||||
b.addTree "args"
|
||||
b.endTree()
|
||||
b.withTree "input":
|
||||
b.addIntLit 0 # main parsed file
|
||||
b.endTree()
|
||||
|
||||
# Define nim nifc command
|
||||
b.addTree "cmd"
|
||||
b.addSymbolDef "nim_nifc"
|
||||
b.addStrLit getAppFilename()
|
||||
b.addStrLit "nifc"
|
||||
b.addStrLit "--nimcache:nifcache"
|
||||
# Add search paths
|
||||
for p in c.config.searchPaths:
|
||||
b.addStrLit "--path:" & p.string
|
||||
b.addTree "input"
|
||||
b.addIntLit 0
|
||||
b.endTree()
|
||||
b.endTree()
|
||||
|
||||
# Build rules for parsing (nifler)
|
||||
var seenFiles = initHashSet[string]()
|
||||
for node in c.nodes:
|
||||
for pair in node.files:
|
||||
let parsed = c.parsedFile(pair)
|
||||
if not seenFiles.containsOrIncl(parsed):
|
||||
b.addTree "do"
|
||||
b.addIdent "nifler"
|
||||
b.addTree "input"
|
||||
b.addStrLit pair.nimFile
|
||||
b.endTree()
|
||||
b.addTree "output"
|
||||
b.addStrLit parsed
|
||||
b.endTree()
|
||||
b.addTree "output"
|
||||
b.addStrLit c.depsFile(pair)
|
||||
b.endTree()
|
||||
b.endTree()
|
||||
|
||||
# Build rules for semantic checking (nim m)
|
||||
for i in countdown(c.nodes.len - 1, 0):
|
||||
let node = c.nodes[i]
|
||||
let pair = node.files[0]
|
||||
b.addTree "do"
|
||||
b.addIdent "nim_m"
|
||||
# Input: all parsed files for this module
|
||||
b.withTree "input":
|
||||
b.addStrLit node.files[0].nimFile
|
||||
for f in node.files:
|
||||
b.addTree "input"
|
||||
b.addStrLit c.parsedFile(f)
|
||||
b.endTree()
|
||||
# Also depend on semmed files of dependencies
|
||||
for depIdx in node.deps:
|
||||
b.addTree "input"
|
||||
b.addStrLit c.semmedFile(c.nodes[depIdx].files[0])
|
||||
b.endTree()
|
||||
# Output: semmed file
|
||||
b.addTree "output"
|
||||
b.addStrLit c.semmedFile(pair)
|
||||
b.endTree()
|
||||
b.endTree()
|
||||
|
||||
# Final compilation step: generate executable from main module
|
||||
let mainNif = c.nodes[0].files[0].nimFile
|
||||
let exeFile = changeFileExt(c.nodes[0].files[0].nimFile, ExeExt)
|
||||
b.addTree "do"
|
||||
b.addIdent "nim_nifc"
|
||||
# Input: .nim file (expanded as argument) and .nif file (dependency)
|
||||
b.addTree "input"
|
||||
b.addStrLit mainNif
|
||||
b.endTree()
|
||||
b.addTree "output"
|
||||
b.addStrLit exeFile
|
||||
b.endTree()
|
||||
b.endTree()
|
||||
|
||||
b.endTree() # stmts
|
||||
|
||||
proc commandIc*(conf: ConfigRef) =
|
||||
## Main entry point for `nim ic`
|
||||
when not defined(nimKochBootstrap):
|
||||
let nifler = findNifler()
|
||||
if nifler.len == 0:
|
||||
rawMessage(conf, errGenerated, "nifler tool not found. Install nimony or add nifler to PATH.")
|
||||
return
|
||||
|
||||
let projectFile = conf.projectFull.string
|
||||
if not fileExists(projectFile):
|
||||
rawMessage(conf, errGenerated, "project file not found: " & projectFile)
|
||||
return
|
||||
|
||||
# Create nimcache directory
|
||||
createDir(getNimcacheDir(conf).string)
|
||||
|
||||
var c = DepContext(
|
||||
config: conf,
|
||||
nifler: nifler,
|
||||
nodes: @[],
|
||||
processedModules: initTable[string, int](),
|
||||
includeStack: @[]
|
||||
)
|
||||
|
||||
# Create root node for main project file
|
||||
let rootPair = c.toPair(projectFile)
|
||||
let rootNode = Node(files: @[rootPair], id: 0)
|
||||
c.nodes.add rootNode
|
||||
c.processedModules[rootPair.modname] = 0
|
||||
|
||||
# model the system.nim dependency:
|
||||
let sysNode = Node(files: @[toPair(c, (conf.libpath / RelativeFile"system.nim").string)], id: 1)
|
||||
c.nodes.add sysNode
|
||||
rootNode.deps.add sysNode.id
|
||||
|
||||
# Process dependencies
|
||||
traverseDeps(c, rootPair, rootNode)
|
||||
|
||||
# Generate build file
|
||||
let buildFile = generateBuildFile(c)
|
||||
rawMessage(conf, hintSuccess, "generated: " & buildFile)
|
||||
|
||||
# Automatically run nifmake
|
||||
let nifmake = findNifmake()
|
||||
if nifmake.len == 0:
|
||||
rawMessage(conf, hintSuccess, "run: nifmake run " & buildFile)
|
||||
else:
|
||||
let cmd = quoteShell(nifmake) & " run " & quoteShell(buildFile)
|
||||
rawMessage(conf, hintExecuting, cmd)
|
||||
let exitCode = execShellCmd(cmd)
|
||||
if exitCode != 0:
|
||||
rawMessage(conf, errGenerated, "nifmake failed with exit code: " & $exitCode)
|
||||
else:
|
||||
rawMessage(conf, errGenerated, "nim ic not available in bootstrap build")
|
||||
@@ -19,7 +19,7 @@ import
|
||||
wordrecg, syntaxes, renderer, lexer,
|
||||
packages/docutils/[rst, rstidx, rstgen, dochelpers],
|
||||
trees, types,
|
||||
typesrenderer, lineinfos,
|
||||
typesrenderer, astalgo, lineinfos,
|
||||
pathutils, nimpaths, renderverbatim, packages
|
||||
import packages/docutils/rstast except FileIndex, TLineInfo
|
||||
|
||||
@@ -1320,7 +1320,7 @@ proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, id
|
||||
if t.startsWith("ref "): t = substr(t, 4)
|
||||
effects[i] = newIdentNode(getIdent(cache, t), n.info)
|
||||
# set the type so that the following analysis doesn't screw up:
|
||||
effects[i].typ = real[i].typ
|
||||
effects[i].typ() = real[i].typ
|
||||
|
||||
result = newTreeI(nkExprColonExpr, n.info,
|
||||
newIdentNode(getIdent(cache, $effectType), n.info), effects)
|
||||
|
||||
@@ -47,7 +47,8 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGener
|
||||
n[bodyPos] = body
|
||||
n[resultPos] = newSymNode(res)
|
||||
result.ast = n
|
||||
incl result.flagsImpl, {sfFromGeneric, sfNeverRaises}
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfNeverRaises
|
||||
|
||||
proc searchObjCaseImpl(obj: PNode; field: PSym): PNode =
|
||||
case obj.kind
|
||||
@@ -109,4 +110,5 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
|
||||
n[bodyPos] = body
|
||||
n[resultPos] = newSymNode(res)
|
||||
result.ast = n
|
||||
incl result.flagsImpl, {sfFromGeneric, sfNeverRaises}
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfNeverRaises
|
||||
|
||||
@@ -275,7 +275,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
# the nkPar node:
|
||||
if n.isNil:
|
||||
result = newNode(nkTupleConstr)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if typ.n.isNil:
|
||||
internalError(conf, "cannot unpack unnamed tuple")
|
||||
unpackObjectAdd(conf, x, typ.n, result)
|
||||
@@ -298,7 +298,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
if n.isNil:
|
||||
result = newNode(nkBracket)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
newSeq(result.sons, lengthOrd(conf, typ).toInt)
|
||||
else:
|
||||
result = n
|
||||
@@ -319,7 +319,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
template aw(k, v, field: untyped): untyped =
|
||||
if n.isNil:
|
||||
result = newNode(k)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
else:
|
||||
# check we have the right field:
|
||||
result = n
|
||||
@@ -333,12 +333,12 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
template setNil() =
|
||||
if n.isNil:
|
||||
result = newNode(nkNilLit)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
else:
|
||||
reset n[]
|
||||
result = n
|
||||
result[] = TNode(kind: nkNilLit)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
|
||||
template awf(kind, v: untyped): untyped = aw(kind, v, floatVal)
|
||||
@@ -427,7 +427,7 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
|
||||
# cast through a pointer needs a new inner object:
|
||||
let y = if x.kind == nkRefTy: newNodeI(nkRefTy, x.info, 1)
|
||||
else: x.copyTree
|
||||
y.typ = x.typ
|
||||
y.typ() = x.typ
|
||||
result = unpack(conf, a, destTyp, y)
|
||||
dealloc a
|
||||
|
||||
@@ -481,7 +481,7 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
|
||||
if aTyp.isNil:
|
||||
internalAssert conf, i+1 < fntyp.len
|
||||
aTyp = fntyp[i+1]
|
||||
args[i+start].typ = aTyp
|
||||
args[i+start].typ() = aTyp
|
||||
sig[i] = mapType(conf, aTyp)
|
||||
if sig[i].isNil: globalError(conf, info, "cannot map FFI type")
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
|
||||
d.add newSymNode(sym, info)
|
||||
result.add d
|
||||
result.add res
|
||||
result.typ = res.typ
|
||||
result.typ() = res.typ
|
||||
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||
conf: ConfigRef;
|
||||
|
||||
@@ -1104,7 +1104,7 @@ proc settype(n: PNode): PType =
|
||||
|
||||
proc buildOf(it, loc: PNode; o: Operators): PNode =
|
||||
var s = newNodeI(nkCurly, it.info, it.len-1)
|
||||
s.typ = settype(loc)
|
||||
s.typ() = settype(loc)
|
||||
for i in 0..<it.len-1: s[i] = it[i]
|
||||
result = newNodeI(nkCall, it.info, 3)
|
||||
result[0] = newSymNode(o.opContains)
|
||||
@@ -1170,7 +1170,7 @@ proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
|
||||
# set field name to discriminator field name
|
||||
a[1] = check[2]
|
||||
# set discriminator field type: important for `neg`
|
||||
a.typ = check[2].typ
|
||||
a.typ() = check[2].typ
|
||||
result[2] = a
|
||||
# 'access.kind != nkDotExpr' can happen for object constructors
|
||||
# which we don't check yet
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# This include implements the high level optimization pass.
|
||||
# included from sem.nim
|
||||
|
||||
proc hlo(c: PContext, n: PNode, loopDetector: int): PNode
|
||||
proc hlo(c: PContext, n: PNode): PNode
|
||||
|
||||
proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||
internalAssert c.config, n.kind == nkCall and n[0].kind == nkSym
|
||||
@@ -61,11 +61,10 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||
# activate this pattern again:
|
||||
c.patterns[i] = pattern
|
||||
|
||||
proc hlo(c: PContext, n: PNode, loopDetector: int): PNode =
|
||||
proc hlo(c: PContext, n: PNode): PNode =
|
||||
inc(c.hloLoopDetector)
|
||||
# simply stop and do not perform any further transformations:
|
||||
if loopDetector > 300:
|
||||
message(c.config, n.info, warnUser, "term rewrite macro instantiation too nested")
|
||||
return n
|
||||
if c.hloLoopDetector > 300: return n
|
||||
case n.kind
|
||||
of nkMacroDef, nkTemplateDef, procDefs:
|
||||
# already processed (special cases in semstmts.nim)
|
||||
@@ -81,7 +80,7 @@ proc hlo(c: PContext, n: PNode, loopDetector: int): PNode =
|
||||
# no optimization applied, try subtrees:
|
||||
for i in 0..<result.safeLen:
|
||||
let a = result[i]
|
||||
let h = hlo(c, a, loopDetector)
|
||||
let h = hlo(c, a)
|
||||
if h != a: result[i] = h
|
||||
else:
|
||||
# perform type checking, so that the replacement still fits:
|
||||
@@ -91,15 +90,17 @@ proc hlo(c: PContext, n: PNode, loopDetector: int): PNode =
|
||||
result = fitNode(c, n.typ, result, n.info)
|
||||
# optimization has been applied so check again:
|
||||
result = commonOptimizations(c.graph, c.idgen, c.module, result)
|
||||
result = hlo(c, result, loopDetector + 1)
|
||||
result = hlo(c, result)
|
||||
result = commonOptimizations(c.graph, c.idgen, c.module, result)
|
||||
|
||||
proc hloBody(c: PContext, n: PNode): PNode =
|
||||
# fast exit:
|
||||
if c.patterns.len == 0 or optTrMacros notin c.config.options: return n
|
||||
result = hlo(c, n, 0)
|
||||
c.hloLoopDetector = 0
|
||||
result = hlo(c, n)
|
||||
|
||||
proc hloStmt(c: PContext, n: PNode): PNode =
|
||||
# fast exit:
|
||||
if c.patterns.len == 0 or optTrMacros notin c.config.options: return n
|
||||
result = hlo(c, n, 0)
|
||||
c.hloLoopDetector = 0
|
||||
result = hlo(c, n)
|
||||
|
||||
@@ -37,10 +37,11 @@ proc setupBackendModule(g: ModuleGraph; m: var LoadedModule) =
|
||||
if g.backend == nil:
|
||||
g.backend = cgendata.newModuleList(g)
|
||||
assert g.backend != nil
|
||||
var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config, idgenFromLoadedModule(m))
|
||||
var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config)
|
||||
bmod.idgen = idgenFromLoadedModule(m)
|
||||
|
||||
proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) =
|
||||
var bmod = BModuleList(g.backend).mods[m.module.position]
|
||||
var bmod = BModuleList(g.backend).modules[m.module.position]
|
||||
assert bmod != nil
|
||||
bmod.flags.incl useAliveDataFromDce
|
||||
bmod.alive = move alive[m.module.position]
|
||||
@@ -51,7 +52,7 @@ proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var Alive
|
||||
|
||||
finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
|
||||
for disp in getDispatchers(g):
|
||||
genProcLvl3(bmod, disp)
|
||||
genProcAux(bmod, disp)
|
||||
m.fromDisk.backendFlags = cgen.whichInitProcs(bmod)
|
||||
|
||||
proc replayTypeInfo(g: ModuleGraph; m: var LoadedModule; origin: FileIndex) =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -370,14 +370,8 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
|
||||
paddingAtEnd: t.paddingAtEnd)
|
||||
storeNode(p, t, n)
|
||||
p.typeInst = t.typeInst.storeType(c, m)
|
||||
if t.kind == tyProc and t.len > 0:
|
||||
# if kind == tyProc, parameter types are stored in t.n
|
||||
# and you can access them with `kits` iterator.
|
||||
# return type is stored in t.sons[0].
|
||||
p.types.add t[0].storeType(c, m)
|
||||
else:
|
||||
for kid in kids t:
|
||||
p.types.add kid.storeType(c, m)
|
||||
for kid in kids t:
|
||||
p.types.add kid.storeType(c, m)
|
||||
c.addMissing t.sym
|
||||
p.sym = t.sym.safeItemId(c, m)
|
||||
c.addMissing t.owner
|
||||
@@ -844,7 +838,7 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
|
||||
of nkSym:
|
||||
result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree[n].soperand))
|
||||
if result.typ == nil:
|
||||
result.typ = result.sym.typ
|
||||
result.typ() = result.sym.typ
|
||||
of externIntLit:
|
||||
result.intVal = g[thisModule].fromDisk.numbers[n.litId]
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -858,7 +852,7 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
|
||||
transitionNoneToSym(result)
|
||||
result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree[n2].soperand))
|
||||
if result.typ == nil:
|
||||
result.typ = result.sym.typ
|
||||
result.typ() = result.sym.typ
|
||||
else:
|
||||
for n0 in sonsReadonly(tree, n):
|
||||
result.addAllowNil loadNodes(c, g, thisModule, tree, n0)
|
||||
@@ -905,11 +899,11 @@ proc moduleIndex*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: in
|
||||
proc symHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
s: PackedSym; si, item: int32): PSym =
|
||||
result = PSym(itemId: ItemId(module: si, item: item),
|
||||
kindImpl: s.kind, magicImpl: s.magic, flagsImpl: s.flags,
|
||||
infoImpl: translateLineInfo(c, g, si, s.info),
|
||||
optionsImpl: s.options,
|
||||
positionImpl: if s.kind in {skForVar, skVar, skLet, skTemp}: 0 else: s.position,
|
||||
offsetImpl: if s.kind in routineKinds: defaultOffset else: s.offset,
|
||||
kind: s.kind, magic: s.magic, flags: s.flags,
|
||||
info: translateLineInfo(c, g, si, s.info),
|
||||
options: s.options,
|
||||
position: if s.kind in {skForVar, skVar, skLet, skTemp}: 0 else: s.position,
|
||||
offset: if s.kind in routineKinds: defaultOffset else: s.offset,
|
||||
disamb: s.disamb,
|
||||
name: getIdent(c.cache, g[si].fromDisk.strings[s.name])
|
||||
)
|
||||
@@ -951,8 +945,8 @@ proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
setOwner(result, loadSym(c, g, si, s.owner))
|
||||
let externalName = g[si].fromDisk.strings[s.externalName]
|
||||
if externalName != "":
|
||||
result.locImpl.snippet = externalName
|
||||
result.locImpl.flags = s.locFlags
|
||||
result.loc.snippet = externalName
|
||||
result.loc.flags = s.locFlags
|
||||
result.instantiatedFrom = loadSym(c, g, si, s.instantiatedFrom)
|
||||
|
||||
proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
|
||||
@@ -996,10 +990,10 @@ proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s:
|
||||
proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32): PType =
|
||||
result = PType(itemId: ItemId(module: si, item: t.nonUniqueId), kind: t.kind,
|
||||
flagsImpl: t.flags, sizeImpl: t.size, alignImpl: t.align,
|
||||
paddingAtEndImpl: t.paddingAtEnd,
|
||||
flags: t.flags, size: t.size, align: t.align,
|
||||
paddingAtEnd: t.paddingAtEnd,
|
||||
uniqueId: ItemId(module: si, item: item),
|
||||
callConvImpl: t.callConv)
|
||||
callConv: t.callConv)
|
||||
|
||||
proc typeBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32; result: PType) =
|
||||
@@ -1064,12 +1058,12 @@ proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa
|
||||
let filename = AbsoluteFile toFullPath(conf, fileIdx)
|
||||
# We cannot call ``newSym`` here, because we have to circumvent the ID
|
||||
# mechanism, which we do in order to assign each module a persistent ID.
|
||||
m.module = PSym(kindImpl: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
m.module = PSym(kind: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
name: getIdent(cache, splitFile(filename).name),
|
||||
infoImpl: newLineInfo(fileIdx, 1, 1),
|
||||
positionImpl: int(fileIdx))
|
||||
info: newLineInfo(fileIdx, 1, 1),
|
||||
position: int(fileIdx))
|
||||
setOwner(m.module, getPackage(conf, cache, fileIdx))
|
||||
m.module.flagsImpl = m.fromDisk.moduleFlags
|
||||
m.module.flags = m.fromDisk.moduleFlags
|
||||
|
||||
proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
|
||||
fileIdx: FileIndex; m: var LoadedModule) =
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Supports the "nim check --ic:legacy --defusages:FILE,LINE,COL"
|
||||
## Supports the "nim check --ic:on --defusages:FILE,LINE,COL"
|
||||
## IDE-like features. It uses the set of .rod files to accomplish
|
||||
## its task. The set must cover a complete Nim project.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module implements the symbol importing mechanism.
|
||||
|
||||
import
|
||||
ast, msgs, options, idents, lookups,
|
||||
ast, astalgo, msgs, options, idents, lookups,
|
||||
semdata, modulepaths, sigmatch, lineinfos,
|
||||
modulegraphs, wordrecg
|
||||
from std/strutils import `%`, startsWith
|
||||
@@ -245,8 +245,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden, track
|
||||
# avoids modifying `realModule`, see D20201209T194412 for `import {.all.}`
|
||||
result = createModuleAliasImpl(realModule.name)
|
||||
if importHidden:
|
||||
ensureMutable result
|
||||
result.optionsImpl.incl optImportHidden
|
||||
result.options.incl optImportHidden
|
||||
let moduleIdent = if n.kind in {nkInfix, nkImportAs}: n[^1] else: n
|
||||
result.info = moduleIdent.info
|
||||
if trackUnusedImport:
|
||||
|
||||
@@ -163,13 +163,9 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool =
|
||||
else:
|
||||
result = false
|
||||
|
||||
template hasDestructorOrAsgn(c: var Con, typ: PType): bool =
|
||||
# bug #23354; an object type could have a non-trivial assignements when it is passed to a sink parameter
|
||||
hasDestructor(c, typ) or (c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
|
||||
typ.kind == tyObject and not isTrivial(getAttachedOp(c.graph, typ, attachedAsgn)))
|
||||
|
||||
proc isLastRead(n: PNode; c: var Con; s: var Scope): bool =
|
||||
if not hasDestructorOrAsgn(c, n.typ): return true
|
||||
# bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter
|
||||
if not hasDestructor(c, n.typ) and (n.typ.kind != tyObject or isTrival(getAttachedOp(c.graph, n.typ, attachedAsgn))): return true
|
||||
|
||||
let m = skipConvDfa(n)
|
||||
result = isLastReadImpl(n, c, s)
|
||||
@@ -343,7 +339,7 @@ proc genMarkCyclic(c: var Con; result, dest: PNode) =
|
||||
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, dest)
|
||||
else:
|
||||
let xenv = genBuiltin(c.graph, c.idgen, mAccessEnv, "accessEnv", dest)
|
||||
xenv.typ = getSysType(c.graph, dest.info, tyPointer)
|
||||
xenv.typ() = getSysType(c.graph, dest.info, tyPointer)
|
||||
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, xenv)
|
||||
|
||||
proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode =
|
||||
@@ -419,7 +415,7 @@ proc genWasMoved(c: var Con, n: PNode): PNode =
|
||||
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
||||
result = newNodeI(nkCall, info)
|
||||
result.add(newSymNode(createMagic(c.graph, c.idgen, "default", mDefault)))
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
# generate: (let tmp = v; reset(v); tmp)
|
||||
@@ -460,7 +456,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let nTyp = n.typ.skipTypes(tyUserTypeClasses)
|
||||
let tmp = c.getTemp(s, nTyp, n.info)
|
||||
if hasDestructorOrAsgn(c, nTyp):
|
||||
if hasDestructor(c, nTyp):
|
||||
let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
let op = getAttachedOp(c.graph, typ, attachedDup)
|
||||
if op != nil and tfHasOwned notin typ.flags:
|
||||
@@ -825,9 +821,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
n[1].typ.skipTypes(abstractInst-{tyOwned}).kind == tyOwned:
|
||||
# allow conversions from owned to unowned via this little hack:
|
||||
let nTyp = n[1].typ
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
result[1] = p(n[1], c, s, sinkArg)
|
||||
result[1].typ = nTyp
|
||||
result[1].typ() = nTyp
|
||||
else:
|
||||
result[1] = p(n[1], c, s, sinkArg)
|
||||
elif n.kind in {nkObjDownConv, nkObjUpConv}:
|
||||
@@ -964,14 +960,14 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
s.locals.add v.sym
|
||||
pVarTopLevel(v, c, s, result)
|
||||
if ri.kind != nkEmpty:
|
||||
let isGlobalPragma = v.kind == nkSym and
|
||||
let isGlobalPragma = v.kind == nkSym and
|
||||
{sfPure, sfGlobal} <= v.sym.flags and
|
||||
isInProc
|
||||
|
||||
let value = moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
if isGlobalPragma:
|
||||
c.graph.procGlobals.add newTree(nkFastAsgn, v, ri)
|
||||
c.graph.procGlobals.add value
|
||||
else:
|
||||
let value = moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
result.add value
|
||||
elif ri.kind == nkEmpty and c.inLoop > 0:
|
||||
let skipInit = v.kind == nkDotExpr and # Closure var
|
||||
@@ -1036,9 +1032,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
n[1].typ.skipTypes(abstractInst-{tyOwned}).kind == tyOwned:
|
||||
# allow conversions from owned to unowned via this little hack:
|
||||
let nTyp = n[1].typ
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
result[1] = p(n[1], c, s, mode)
|
||||
result[1].typ = nTyp
|
||||
result[1].typ() = nTyp
|
||||
else:
|
||||
result[1] = p(n[1], c, s, mode)
|
||||
|
||||
@@ -1155,7 +1151,7 @@ proc ownsData(c: var Con; s: var Scope; orig: PNode; flags: set[MoveOrCopyFlag])
|
||||
if n.kind in nkCallKinds and n.typ != nil and hasDestructor(c, n.typ):
|
||||
result = newNodeIT(nkStmtListExpr, orig.info, orig.typ)
|
||||
let tmp = c.getTemp(s, n.typ, n.info)
|
||||
tmp.sym.flagsImpl.incl sfSingleUsedTemp
|
||||
tmp.sym.flags.incl sfSingleUsedTemp
|
||||
result.add newTree(nkFastAsgn, tmp, copyTree(n))
|
||||
s.final.add c.genDestroy(tmp)
|
||||
n[] = tmp[]
|
||||
@@ -1330,7 +1326,7 @@ proc addSinkCopy(c: var Con; s: var Scope; sinkParams: seq[PSym]; n: PNode): PNo
|
||||
for param in sinkParams:
|
||||
if param.id in mutatedSet:
|
||||
let newSym = newSym(skTemp, getIdent(c.graph.cache, "sinkCopy"), c.idgen, param.owner, n.info)
|
||||
newSym.flagsImpl.incl sfFromGeneric
|
||||
newSym.flags.incl sfFromGeneric
|
||||
newSym.typ = param.typ.elementType
|
||||
mapping[param.id] = newSym
|
||||
let v = newNodeI(nkVarSection, n.info)
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
|
||||
proc copySymdef(n: PNode; locals: var Table[int, PSym]; idgen: IdGenerator; owner: PSym): PNode =
|
||||
case n.kind
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
result = n
|
||||
of nkSym:
|
||||
let oldSym = n.sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result = newSymNode(newSym, oldSym.info)
|
||||
else:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = copySymdef(n[i], locals, idgen, owner)
|
||||
|
||||
proc copyInlineProcBody(n: PNode; locals: var Table[int, PSym]; idgen: IdGenerator; owner: PSym): PNode =
|
||||
case n.kind
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
result = n
|
||||
of nkSym:
|
||||
let sym = locals.getOrDefault(n.sym.id)
|
||||
if sym != nil:
|
||||
result = newSymNode(sym, n.info)
|
||||
else:
|
||||
result = n
|
||||
of nkLetSection, nkVarSection:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind == nkCommentStmt:
|
||||
result[i] = it
|
||||
elif it.kind in {nkIdentDefs, nkConstDef}:
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
result[i][j] = copySymdef(it[j], locals, idgen, owner)
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
else:
|
||||
assert it.kind == nkVarTuple
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
assert it[j].kind == nkSym
|
||||
let oldSym = it[j].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i][j] = newSymNode(newSym, oldSym.info)
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
|
||||
of nkForStmt, nkParForStmt:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len-2:
|
||||
assert n[i].kind == nkSym
|
||||
let oldSym = n[i].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i] = newSymNode(newSym, oldSym.info)
|
||||
result[n.len-2] = copyInlineProcBody(n[n.len-2], locals, idgen, owner)
|
||||
result[n.len-1] = copyInlineProcBody(n[n.len-1], locals, idgen, owner)
|
||||
of routineDefs, nkTypeSection, nkTypeOfExpr, nkMixinStmt, nkBindStmt, nkConstSection:
|
||||
result = n
|
||||
else:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = copyInlineProcBody(n[i], locals, idgen, owner)
|
||||
|
||||
proc copyParams(n: PNode; locals: var Table[int, PSym]; idgen: IdGenerator; owner: PSym): PNode =
|
||||
result = shallowCopy(n)
|
||||
result[0] = n[0] # return type
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
assert it.kind == nkIdentDefs
|
||||
result[i] = shallowCopy(it)
|
||||
for j in 0..<it.len-2:
|
||||
assert it[j].kind == nkSym
|
||||
let oldSym = it[j].sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, owner)
|
||||
locals[oldSym.id] = newSym
|
||||
result[i][j] = newSymNode(newSym, oldSym.info)
|
||||
owner.typ.addParam newSym
|
||||
for j in it.len-2..<it.len:
|
||||
result[i][j] = copyInlineProcBody(it[j], locals, idgen, owner)
|
||||
|
||||
proc copyInlineProc(prc: PSym; idgen: IdGenerator): PSym =
|
||||
result = copySym(prc, idgen)
|
||||
var locals = initTable[int, PSym]()
|
||||
|
||||
var a = shallowCopy(prc.ast)
|
||||
if resultPos < prc.ast.len and prc.ast[resultPos].kind == nkSym:
|
||||
let oldRes = prc.ast[resultPos].sym
|
||||
let newRes = copySym(oldRes, idgen)
|
||||
setOwner(newRes, result)
|
||||
locals[oldRes.id] = newRes
|
||||
a[resultPos] = newSymNode(newRes, oldRes.info)
|
||||
|
||||
result.typ = copyType(prc.typ, idgen, result)
|
||||
result.typ.n = newNodeI(prc.typ.n.kind, prc.typ.n.info)
|
||||
if prc.typ.n.len > 0:
|
||||
result.typ.n.add copyNode(prc.typ.n[0])
|
||||
for i in 1..<prc.typ.n.len:
|
||||
let it = prc.typ.n[i]
|
||||
assert it.kind == nkSym
|
||||
let oldSym = it.sym
|
||||
let newSym = copySym(oldSym, idgen)
|
||||
setOwner(newSym, result)
|
||||
locals[oldSym.id] = newSym
|
||||
result.typ.addParam newSym
|
||||
|
||||
for i in 0..<prc.ast.len:
|
||||
if i == paramsPos:
|
||||
a[i] = copyTree(prc.ast[i])
|
||||
elif i == resultPos and prc.ast[i].kind == nkSym:
|
||||
discard "handled above"
|
||||
else:
|
||||
a[i] = copyInlineProcBody(prc.ast[i], locals, idgen, result)
|
||||
result.ast = a
|
||||
|
||||
#echo "Produced: ", renderTree(result.ast, {renderIds})
|
||||
@@ -6,7 +6,7 @@ Name: "Nim"
|
||||
Version: "$version"
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;s390x;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv32;riscv64;loongarch64
|
||||
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv32;riscv64;loongarch64
|
||||
macosx: i386;amd64;powerpc64;arm64
|
||||
solaris: i386;amd64;sparc;sparc64
|
||||
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el
|
||||
|
||||
@@ -277,8 +277,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
|
||||
else:
|
||||
result.add("_")
|
||||
result.add(rope(s.id))
|
||||
ensureMutable s
|
||||
s.locImpl.snippet = result
|
||||
s.loc.snippet = result
|
||||
|
||||
proc escapeJSString(s: string): string =
|
||||
result = newStringOfCap(s.len + s.len shr 2)
|
||||
@@ -729,47 +728,44 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
of mShrI:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asIntN(64, BigInt.asUintN(64, $1) >> (BigInt($2) & 63n))")
|
||||
applyFormat("BigInt.asIntN(64, BigInt.asUintN(64, $1) >> BigInt($2))")
|
||||
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("($1 >> (BigInt($2) & 63n))")
|
||||
applyFormat("($1 >> BigInt($2))")
|
||||
else:
|
||||
let bitmask = typ.size * 8 - 1
|
||||
if typ.kind in {tyInt..tyInt32}:
|
||||
let trimmerU = unsignedTrimmer(typ.size)
|
||||
let trimmerS = signedTrimmer(typ.size)
|
||||
r.res = "((($1 $2) >>> ($3 & $5)) $4)" % [xLoc, trimmerU, yLoc, trimmerS, $bitmask]
|
||||
r.res = "((($1 $2) >>> $3) $4)" % [xLoc, trimmerU, yLoc, trimmerS]
|
||||
else:
|
||||
r.res = "($1 >>> ($2 & $3))" % [xLoc, yLoc, $bitmask]
|
||||
applyFormat("($1 >>> $2)")
|
||||
of mShlI:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.size == 8:
|
||||
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asIntN(64, $1 << (BigInt($2) & 63n))")
|
||||
applyFormat("BigInt.asIntN(64, $1 << BigInt($2))")
|
||||
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asUintN(64, $1 << (BigInt($2) & 63n))")
|
||||
applyFormat("BigInt.asUintN(64, $1 << BigInt($2))")
|
||||
else:
|
||||
applyFormat("($1 * Math.pow(2, ($2 & 63)))")
|
||||
applyFormat("($1 * Math.pow(2, $2))")
|
||||
else:
|
||||
let bitmask = typ.size * 8 - 1
|
||||
if typ.kind in {tyUInt..tyUInt32}:
|
||||
let trimmer = unsignedTrimmer(typ.size)
|
||||
r.res = "(($1 << ($2 & $4)) $3)" % [xLoc, yLoc, trimmer, $bitmask]
|
||||
r.res = "(($1 << $2) $3)" % [xLoc, yLoc, trimmer]
|
||||
else:
|
||||
let trimmer = signedTrimmer(typ.size)
|
||||
r.res = "(($1 << ($2 & $4)) $3)" % [xLoc, yLoc, trimmer, $bitmask]
|
||||
r.res = "(($1 << $2) $3)" % [xLoc, yLoc, trimmer]
|
||||
of mAshrI:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.size == 8:
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("($1 >> (BigInt($2) & 63n))")
|
||||
applyFormat("($1 >> BigInt($2))")
|
||||
else:
|
||||
applyFormat("Math.floor($1 / Math.pow(2, ($2 & 63)))")
|
||||
applyFormat("Math.floor($1 / Math.pow(2, $2))")
|
||||
else:
|
||||
let bitmask = typ.size * 8 - 1
|
||||
if typ.kind in {tyUInt..tyUInt32}:
|
||||
r.res = "($1 >>> ($2 & $3)))" % [xLoc, yLoc, $bitmask]
|
||||
applyFormat("($1 >>> $2)")
|
||||
else:
|
||||
r.res = "($1 >> ($2 & $3))" % [xLoc, yLoc, $bitmask]
|
||||
applyFormat("($1 >> $2)")
|
||||
of mBitandI: bitwiseExpr("&")
|
||||
of mBitorI: bitwiseExpr("|")
|
||||
of mBitxorI: bitwiseExpr("^")
|
||||
@@ -1006,8 +1002,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
# If some branch requires a local alias introduce it here. This is needed
|
||||
# since JS cannot do ``catch x as y``.
|
||||
if excAlias != nil:
|
||||
ensureMutable excAlias.sym
|
||||
excAlias.sym.locImpl.snippet = mangleName(p.module, excAlias.sym)
|
||||
excAlias.sym.loc.snippet = mangleName(p.module, excAlias.sym)
|
||||
lineF(p, "var $1 = lastJSError;$n", excAlias.sym.loc.snippet)
|
||||
gen(p, n[i][^1], a)
|
||||
moveInto(p, a, r)
|
||||
@@ -1140,8 +1135,7 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
|
||||
# named block?
|
||||
if (n[0].kind != nkSym): internalError(p.config, n.info, "genBlock")
|
||||
var sym = n[0].sym
|
||||
ensureMutable sym
|
||||
sym.locImpl.k = locOther
|
||||
sym.loc.k = locOther
|
||||
sym.position = idx+1
|
||||
let labl = p.unique
|
||||
lineF(p, "Label$1: {$n", [labl.rope])
|
||||
@@ -1240,8 +1234,7 @@ proc generateHeader(p: PProc, prc: PSym): Rope =
|
||||
# to keep it simple
|
||||
let env = prc.ast[paramsPos].lastSon
|
||||
assert env.kind == nkSym, "env is missing"
|
||||
ensureMutable env.sym
|
||||
env.sym.locImpl.snippet = "this"
|
||||
env.sym.loc.snippet = "this"
|
||||
|
||||
for i in 1..<typ.n.len:
|
||||
assert(typ.n[i].kind == nkSym)
|
||||
@@ -1378,15 +1371,12 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.typ = etyBaseIndex
|
||||
let b = if n.kind == nkHiddenAddr: n[0] else: n
|
||||
gen(p, b[0], a)
|
||||
if skipTypes(b[0].typ, abstractVarRange + tyTypeClasses).kind == tyTuple:
|
||||
# ref #25227 about `+ tyTypeClasses`
|
||||
if skipTypes(b[0].typ, abstractVarRange).kind == tyTuple:
|
||||
r.res = makeJSString("Field" & $getFieldPosition(p, b[1]))
|
||||
else:
|
||||
if b[1].kind != nkSym: internalError(p.config, b[1].info, "genFieldAddr")
|
||||
var f = b[1].sym
|
||||
if f.loc.snippet == "":
|
||||
ensureMutable f
|
||||
f.locImpl.snippet = mangleName(p.module, f)
|
||||
if f.loc.snippet == "": f.loc.snippet = mangleName(p.module, f)
|
||||
r.res = makeJSString($f.loc.snippet)
|
||||
internalAssert p.config, a.typ != etyBaseIndex
|
||||
r.address = a.res
|
||||
@@ -1414,9 +1404,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else:
|
||||
if n[1].kind != nkSym: internalError(p.config, n[1].info, "genFieldAccess")
|
||||
var f = n[1].sym
|
||||
if f.loc.snippet == "":
|
||||
ensureMutable f
|
||||
f.locImpl.snippet = mangleName(p.module, f)
|
||||
if f.loc.snippet == "": f.loc.snippet = mangleName(p.module, f)
|
||||
r.res = "$1.$2" % [r.res, f.loc.snippet]
|
||||
mkTemp(1)
|
||||
r.kind = resExpr
|
||||
@@ -1437,15 +1425,11 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||
# Field symbol
|
||||
var field = accessExpr[1].sym
|
||||
internalAssert p.config, field.kind == skField
|
||||
if field.loc.snippet == "":
|
||||
ensureMutable field
|
||||
field.locImpl.snippet = mangleName(p.module, field)
|
||||
if field.loc.snippet == "": field.loc.snippet = mangleName(p.module, field)
|
||||
# Discriminant symbol
|
||||
let disc = checkExpr[2].sym
|
||||
internalAssert p.config, disc.kind == skField
|
||||
if disc.loc.snippet == "":
|
||||
ensureMutable disc
|
||||
disc.locImpl.snippet = mangleName(p.module, disc)
|
||||
if disc.loc.snippet == "": disc.loc.snippet = mangleName(p.module, disc)
|
||||
|
||||
var setx: TCompRes = default(TCompRes)
|
||||
gen(p, checkExpr[1], setx)
|
||||
@@ -1602,11 +1586,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkObjDownConv:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenDeref, nkDerefExpr:
|
||||
if n.kind in {nkAddr, nkHiddenAddr}:
|
||||
# addr ( deref ( x )) --> x
|
||||
gen(p, n[0][0], r)
|
||||
else:
|
||||
gen(p, n[0], r)
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenAddr:
|
||||
gen(p, n[0], r)
|
||||
of nkConv:
|
||||
@@ -1857,9 +1837,7 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
|
||||
proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) =
|
||||
# don't call '$' here for efficiency:
|
||||
let f = n[0].sym
|
||||
if f.loc.snippet == "":
|
||||
ensureMutable f
|
||||
f.locImpl.snippet = mangleName(p.module, f)
|
||||
if f.loc.snippet == "": f.loc.snippet = mangleName(p.module, f)
|
||||
if sfInfixCall in f.flags:
|
||||
let pat = $n[0].sym.loc.snippet
|
||||
internalAssert p.config, pat.len > 0
|
||||
@@ -2351,8 +2329,8 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.res = "if (null != $1) { if (null == $2) $2 = $3; else $2 += $3; }" %
|
||||
[b, lhs.rdLoc, tmp]
|
||||
else:
|
||||
useMagic(p, "nimAddStrStr")
|
||||
r.res = "nimAddStrStr($1, $2);" % [lhs.rdLoc, rhs.rdLoc]
|
||||
let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
|
||||
r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp]
|
||||
r.kind = resExpr
|
||||
of mAppendSeqElem:
|
||||
var x, y: TCompRes = default(TCompRes)
|
||||
@@ -2595,9 +2573,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let val = it[1]
|
||||
gen(p, val, a)
|
||||
var f = it[0].sym
|
||||
if f.loc.snippet == "":
|
||||
ensureMutable f
|
||||
f.locImpl.snippet = mangleName(p.module, f)
|
||||
if f.loc.snippet == "": f.loc.snippet = mangleName(p.module, f)
|
||||
fieldIDs.incl(lookupFieldAgain(n.typ.skipTypes({tyDistinct}), f).id)
|
||||
|
||||
let typ = val.typ.skipTypes(abstractInst)
|
||||
@@ -2899,8 +2875,6 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||
elif dest.kind in tyFloat..tyFloat64:
|
||||
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number($1)" % [r.res]
|
||||
elif dest.kind == tyChar and (fromInt or fromUint):
|
||||
r.res = "($1 & 255)" % [r.res]
|
||||
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
|
||||
r.address = r.res
|
||||
r.res = "null"
|
||||
|
||||
@@ -150,7 +150,6 @@ template isIterator*(owner: PSym): bool =
|
||||
|
||||
proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
|
||||
result = createObj(g, idgen, owner, info, final=false)
|
||||
result.incl tfFinal
|
||||
if owner.isIterator:
|
||||
rawAddField(result, createStateField(g, owner, idgen))
|
||||
|
||||
@@ -161,7 +160,7 @@ proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym
|
||||
# XXX a bit hacky:
|
||||
result = newSym(skResult, getIdent(g.cache, ":result"), idgen, iter, iter.info, {})
|
||||
result.typ = iter.typ.returnType
|
||||
incl(result.flagsImpl, sfUsed)
|
||||
incl(result.flags, sfUsed)
|
||||
iter.ast.add newSymNode(result)
|
||||
|
||||
proc addHiddenParam(routine: PSym, param: PSym) =
|
||||
@@ -228,7 +227,7 @@ proc makeClosure*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; env: PNode; inf
|
||||
#if isClosureIterator(result.typ):
|
||||
createTypeBoundOps(g, nil, result.typ, info, idgen)
|
||||
if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions:
|
||||
prc.incl sfInjectDestructors
|
||||
prc.flags.incl sfInjectDestructors
|
||||
|
||||
template liftingHarmful(conf: ConfigRef; owner: PSym): bool =
|
||||
## lambda lifting can be harmful for JS-like code generators.
|
||||
@@ -240,7 +239,7 @@ proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; idgen
|
||||
createTypeBoundOps(g, nil, refType.elementType, info, idgen)
|
||||
createTypeBoundOps(g, nil, refType, info, idgen)
|
||||
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
|
||||
owner.incl sfInjectDestructors
|
||||
owner.flags.incl sfInjectDestructors
|
||||
|
||||
proc genCreateEnv(env: PNode): PNode =
|
||||
var c = newNodeIT(nkObjConstr, env.info, env.typ)
|
||||
@@ -290,7 +289,7 @@ proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
|
||||
elif not (owner.typ.isClosure or owner.isNimcall and not owner.isExplicitCallConv or isEnv):
|
||||
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
|
||||
[s.name.s, owner.name.s, $owner.typ.callConv])
|
||||
incl(owner.typ, tfCapturesEnv)
|
||||
incl(owner.typ.flags, tfCapturesEnv)
|
||||
if not isEnv:
|
||||
owner.typ.callConv = ccClosure
|
||||
|
||||
@@ -336,7 +335,7 @@ proc asOwnedRef(c: var DetectionPass; t: PType): PType =
|
||||
if optOwnedRefs in c.graph.config.globalOptions:
|
||||
assert t.kind == tyRef
|
||||
result = newType(tyOwned, c.idgen, t.owner)
|
||||
result.incl tfHasOwned
|
||||
result.flags.incl tfHasOwned
|
||||
result.rawAddSon t
|
||||
else:
|
||||
result = t
|
||||
@@ -414,7 +413,7 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
|
||||
let t = c.getEnvTypeForOwner(owner, info)
|
||||
if cp == nil:
|
||||
cp = newSym(skParam, getIdent(c.graph.cache, paramName), c.idgen, fn, fn.info)
|
||||
incl(cp.flagsImpl, sfFromGeneric)
|
||||
incl(cp.flags, sfFromGeneric)
|
||||
cp.typ = t
|
||||
addHiddenParam(fn, cp)
|
||||
elif cp.typ != t and fn.kind != skIterator:
|
||||
@@ -610,7 +609,7 @@ proc rawClosureCreation(owner: PSym;
|
||||
let unowned = c.unownedEnvVars[owner.id]
|
||||
assert unowned != nil
|
||||
let env2 = copyTree(env)
|
||||
env2.typ = unowned.typ
|
||||
env2.typ() = unowned.typ
|
||||
result.add newAsgnStmt(unowned, env2, env.info)
|
||||
createTypeBoundOpsLL(d.graph, unowned.typ, env.info, d.idgen, owner)
|
||||
|
||||
@@ -624,7 +623,7 @@ proc rawClosureCreation(owner: PSym;
|
||||
if owner.kind != skMacro:
|
||||
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info, d.idgen)
|
||||
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
|
||||
owner.incl sfInjectDestructors
|
||||
owner.flags.incl sfInjectDestructors
|
||||
|
||||
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
|
||||
if upField != nil:
|
||||
@@ -666,7 +665,7 @@ proc closureCreationForIter(owner: PSym, iter: PNode;
|
||||
result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ)
|
||||
let iterOwner = iter.sym.skipGenericOwner
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName), d.idgen, iterOwner, iter.info)
|
||||
incl(v.flagsImpl, sfShadowed)
|
||||
incl(v.flags, sfShadowed)
|
||||
v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ)
|
||||
var vnode: PNode
|
||||
if iterOwner.isIterator:
|
||||
@@ -787,7 +786,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
let oldInContainer = c.inContainer
|
||||
c.inContainer = 0
|
||||
let m = newSymNode(n[namePos].sym)
|
||||
m.typ = n.typ
|
||||
m.typ() = n.typ
|
||||
result = liftCapturedVars(m, owner, d, c)
|
||||
c.inContainer = oldInContainer
|
||||
of nkHiddenStdConv:
|
||||
@@ -975,20 +974,6 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym):
|
||||
for i in 0..<op.len-1:
|
||||
result.add op[i]
|
||||
|
||||
elif op.kind != nkSym: # might have side effects
|
||||
# bug #25046
|
||||
# create a temp for the closure
|
||||
# var :closureTemp
|
||||
# :closureTemp = ...
|
||||
let tempSym = newSym(skLet, getIdent(g.cache, ":closureTemp"), idgen, owner, body.info)
|
||||
tempSym.typ = call[0].typ
|
||||
let temp = newSymNode(tempSym)
|
||||
var v = newNodeI(nkVarSection, body.info)
|
||||
addVar(v, temp)
|
||||
result.add(v)
|
||||
result.add newAsgnStmt(temp, call[0], body.info)
|
||||
call[0] = temp
|
||||
|
||||
var loopBody = newNodeI(nkStmtList, body.info, 3)
|
||||
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
|
||||
whileLoop[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import std/[tables]
|
||||
import ast, astalgo
|
||||
|
||||
type
|
||||
|
||||
@@ -49,7 +49,7 @@ proc at(a, i: PNode, elemType: PType): PNode =
|
||||
result = newNodeI(nkBracketExpr, a.info, 2)
|
||||
result[0] = a
|
||||
result[1] = i
|
||||
result.typ = elemType
|
||||
result.typ() = elemType
|
||||
|
||||
proc destructorOverridden(g: ModuleGraph; t: PType): bool =
|
||||
let op = getAttachedOp(g, t, attachedDestructor)
|
||||
@@ -68,7 +68,7 @@ proc dotField(x: PNode, f: PSym): PNode =
|
||||
else:
|
||||
result[0] = x
|
||||
result[1] = newSymNode(f, x.info)
|
||||
result.typ = f.typ
|
||||
result.typ() = f.typ
|
||||
|
||||
proc newAsgnStmt(le, ri: PNode): PNode =
|
||||
result = newNodeI(nkAsgn, le.info, 2)
|
||||
@@ -88,7 +88,7 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
elif c.kind == attachedDestructor and c.addMemReset:
|
||||
let call = genBuiltin(c, mDefault, "default", x)
|
||||
call.typ = t
|
||||
call.typ() = t
|
||||
body.add newAsgnStmt(x, call)
|
||||
elif c.kind == attachedWasMoved:
|
||||
body.add genBuiltin(c, mWasMoved, "wasMoved", x)
|
||||
@@ -105,7 +105,7 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
|
||||
result = newNodeI(nkWhileStmt, c.info, 2)
|
||||
let cmp = genBuiltin(c, mLtI, "<", i)
|
||||
cmp.add genLen(c.g, dest)
|
||||
cmp.typ = getSysType(c.g, c.info, tyBool)
|
||||
cmp.typ() = getSysType(c.g, c.info, tyBool)
|
||||
result[0] = cmp
|
||||
result[1] = newNodeI(nkStmtList, c.info)
|
||||
|
||||
@@ -127,10 +127,10 @@ proc genContainerOf(c: var TLiftCtx; objType: PType, field, x: PSym): PNode =
|
||||
dotExpr.add newSymNode(field)
|
||||
|
||||
let offsetOf = genBuiltin(c, mOffsetOf, "offsetof", dotExpr)
|
||||
offsetOf.typ = intType
|
||||
offsetOf.typ() = intType
|
||||
|
||||
let minusExpr = genBuiltin(c, mSubI, "-", castExpr1)
|
||||
minusExpr.typ = intType
|
||||
minusExpr.typ() = intType
|
||||
minusExpr.add offsetOf
|
||||
|
||||
let objPtr = makePtrType(objType.owner, objType, c.idgen)
|
||||
@@ -280,11 +280,11 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
# because the wasMoved(dest) call would zero out src, if dest aliases src.
|
||||
var cond = newTree(nkCall, newSymNode(c.g.getSysMagic(c.info, "==", mEqRef)),
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x), newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y))
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
|
||||
temp.typ = x.typ
|
||||
incl(temp, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
var v = newNodeI(nkVarSection, c.info)
|
||||
let blob = newSymNode(temp)
|
||||
v.addVar(blob, x)
|
||||
@@ -312,7 +312,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
|
||||
proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
|
||||
result = newIntLit(g, info, ord value)
|
||||
result.typ = getSysType(g, info, tyBool)
|
||||
result.typ() = getSysType(g, info, tyBool)
|
||||
|
||||
proc getCycleParam(c: TLiftCtx): PNode =
|
||||
assert c.kind in {attachedAsgn, attachedDup}
|
||||
@@ -380,10 +380,6 @@ proc requiresDestructor(c: TLiftCtx; t: PType): bool {.inline.} =
|
||||
proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
|
||||
if c.c != nil and typeInst != nil:
|
||||
result = c.c.instTypeBoundOp(c.c, op, typeInst, c.info, attachedAsgn, 1)
|
||||
elif typeInst != nil and getAttachedOp(c.g, typeInst, c.kind) != nil:
|
||||
# c.c == nil in lambdalifting
|
||||
# hooks are already insted
|
||||
result = getAttachedOp(c.g, typeInst, c.kind)
|
||||
else:
|
||||
localError(c.g.config, c.info,
|
||||
"cannot generate destructor for generic type: " & typeToString(t))
|
||||
@@ -397,8 +393,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
if op != nil and op != c.fn and
|
||||
(sfOverridden in op.flags or destructorOverridden):
|
||||
if sfError in op.flags:
|
||||
ensureMutable c.fn
|
||||
incl c.fn.flagsImpl, sfError
|
||||
incl c.fn.flags, sfError
|
||||
#else:
|
||||
# markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||
onUse(c.info, op)
|
||||
@@ -424,8 +419,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
if op == nil:
|
||||
op = produceSym(c.g, c.c, t, c.kind, c.info, c.idgen)
|
||||
if sfError in op.flags:
|
||||
ensureMutable c.fn
|
||||
incl c.fn.flagsImpl, sfError
|
||||
incl c.fn.flags, sfError
|
||||
#else:
|
||||
# markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||
onUse(c.info, op)
|
||||
@@ -541,7 +535,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
|
||||
temp.typ = getSysType(c.g, body.info, tyInt)
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
var v = newNodeI(nkVarSection, c.info)
|
||||
result = newSymNode(temp)
|
||||
@@ -551,7 +545,7 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
|
||||
temp.typ = value.typ
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
var v = newNodeI(nkVarSection, c.info)
|
||||
result = newSymNode(temp)
|
||||
@@ -567,18 +561,18 @@ proc newSeqCall(c: var TLiftCtx; x, y: PNode): PNode =
|
||||
# don't call genAddr(c, x) here:
|
||||
result = genBuiltin(c, mNewSeq, "newSeq", x)
|
||||
let lenCall = genBuiltin(c, mLengthSeq, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
result.add lenCall
|
||||
|
||||
proc setLenStrCall(c: var TLiftCtx; x, y: PNode): PNode =
|
||||
let lenCall = genBuiltin(c, mLengthStr, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
result = genBuiltin(c, mSetLengthStr, "setLen", x) # genAddr(g, x))
|
||||
result.add lenCall
|
||||
|
||||
proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||
let lenCall = genBuiltin(c, mLengthSeq, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
var op = getSysMagic(c.g, x.info, "setLen", mSetLengthSeq)
|
||||
op = instantiateGeneric(c, op, t, t)
|
||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||
@@ -601,7 +595,7 @@ proc checkSelfAssignment(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x),
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y)
|
||||
)
|
||||
cond.typ = getSysType(c.g, c.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, c.info, tyBool)
|
||||
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
|
||||
|
||||
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
@@ -742,7 +736,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(tmp, nkDerefExpr))
|
||||
var alignOf = genBuiltin(c, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
alignOf.typ() = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, tmp, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(tmp, nkDerefExpr))
|
||||
@@ -752,7 +746,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
typInfo.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
||||
@@ -760,7 +754,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastDyn", c.info, x)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
@@ -787,7 +781,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
typInfo.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x, c.idgen), typInfo, y)
|
||||
else:
|
||||
# If the ref is polymorphic we have to account for this
|
||||
@@ -808,7 +802,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
## Closures are really like refs except they always use a virtual destructor
|
||||
## and we need to do the refcounting only on the ref field which we call 'xenv':
|
||||
let xenv = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc
|
||||
let tmp =
|
||||
@@ -824,7 +818,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic: "nimDecRefIsLastCyclicDyn"
|
||||
else: "nimDecRefIsLast"
|
||||
let cond = callCodegenProc(c.g, decRefProc, c.info, tmp)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
@@ -836,7 +830,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
if isCyclic:
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
|
||||
body.add newAsgnStmt(x, y)
|
||||
@@ -848,7 +842,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
|
||||
@@ -900,7 +894,7 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||
var alignOf = genBuiltin(c, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
alignOf.typ() = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||
@@ -923,14 +917,14 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
# a big problem is that we don't know the environment's type here, so we
|
||||
# have to go through some indirection; we delegate this to the codegen:
|
||||
let call = newNodeI(nkCall, c.info, 2)
|
||||
call.typ = t
|
||||
call.typ() = t
|
||||
call[0] = newSymNode(createMagic(c.g, c.idgen, "deepCopy", mDeepCopy))
|
||||
call[1] = y
|
||||
body.add newAsgnStmt(x, call)
|
||||
elif (optOwnedRefs in c.g.config.globalOptions and
|
||||
optRefCheck in c.g.config.options) or c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
|
||||
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
# we 'nil' y out afterwards so we *need* to take over its reference
|
||||
@@ -939,13 +933,13 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
of attachedDestructor:
|
||||
@@ -960,7 +954,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
var actions = newNodeI(nkStmtList, c.info)
|
||||
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
|
||||
@@ -1050,8 +1044,6 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add genBuiltin(c, mWasMoved, "wasMoved", x)
|
||||
else:
|
||||
fillBodyObjT(c, t, body, x, y)
|
||||
elif tfUnion in t.flags: # bug #25236
|
||||
defaultOp(c, t, body, x, y)
|
||||
else:
|
||||
if c.kind == attachedDup:
|
||||
var op2 = getAttachedOp(c.g, t, attachedAsgn)
|
||||
@@ -1126,7 +1118,8 @@ proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttache
|
||||
n[bodyPos] = newNodeI(nkStmtList, info)
|
||||
n[resultPos] = newSymNode(res)
|
||||
result.ast = n
|
||||
incl result.flagsImpl, {sfFromGeneric, sfGeneratedOp}
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false): PSym =
|
||||
@@ -1168,17 +1161,17 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
n[paramsPos] = result.typ.n
|
||||
n[bodyPos] = newNodeI(nkStmtList, info)
|
||||
result.ast = n
|
||||
incl result.flagsImpl, sfFromGeneric
|
||||
incl result.flagsImpl, sfGeneratedOp
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
if kind == attachedWasMoved:
|
||||
incl result.flagsImpl, sfNoSideEffect
|
||||
incl result.typ, tfNoSideEffect
|
||||
incl result.flags, sfNoSideEffect
|
||||
incl result.typ.flags, tfNoSideEffect
|
||||
|
||||
proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessTypeField, "accessTypeField", x)
|
||||
let yy = genBuiltin(c, mAccessTypeField, "accessTypeField", y)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ = xx.typ
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = xx.typ
|
||||
body.add newAsgnStmt(xx, yy)
|
||||
|
||||
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
@@ -1205,17 +1198,14 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
|
||||
if kind == attachedSink and destructorOverridden(g, typ):
|
||||
## compiler can use a combination of `=destroy` and memCopy for sink op
|
||||
ensureMutable dest
|
||||
dest.flagsImpl.incl sfCursor
|
||||
dest.flags.incl sfCursor
|
||||
let op = getAttachedOp(g, typ, attachedDestructor)
|
||||
result.ast[bodyPos].add newOpCall(a, op, if op.typ.firstParamType.kind == tyVar: d[0] else: d)
|
||||
result.ast[bodyPos].add newAsgnStmt(d, src)
|
||||
else:
|
||||
var tk: TTypeKind
|
||||
var skipped: PType = nil
|
||||
if g.config.selectedGC in {gcArc, gcOrc, gcHooks, gcAtomicArc}:
|
||||
skipped = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink})
|
||||
tk = skipped.kind
|
||||
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
||||
else:
|
||||
tk = tyNone # no special casing for strings and seqs
|
||||
case tk
|
||||
@@ -1225,20 +1215,18 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
fillStrOp(a, typ, result.ast[bodyPos], d, src)
|
||||
else:
|
||||
fillBody(a, typ, result.ast[bodyPos], d, src)
|
||||
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy, attachedDup} and not isObjLackingTypeField(skipped):
|
||||
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy, attachedDup} and not isObjLackingTypeField(typ):
|
||||
# bug #19205: Do not forget to also copy the hidden type field:
|
||||
genTypeFieldCopy(a, typ, result.ast[bodyPos], d, src)
|
||||
|
||||
if not a.canRaise:
|
||||
ensureMutable result
|
||||
incl result.flagsImpl, sfNeverRaises
|
||||
incl result.flags, sfNeverRaises
|
||||
result.ast[pragmasPos] = newNodeI(nkPragma, info)
|
||||
result.ast[pragmasPos].add newTree(nkExprColonExpr,
|
||||
newIdentNode(g.cache.getIdent("raises"), info), newNodeI(nkBracket, info))
|
||||
|
||||
if kind == attachedDestructor:
|
||||
ensureMutable result
|
||||
incl result.optionsImpl, optQuirky
|
||||
incl result.options, optQuirky
|
||||
completePartialOp(g, idgen.module, typ, kind, result)
|
||||
|
||||
|
||||
@@ -1263,9 +1251,7 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
|
||||
result.ast[bodyPos].add v
|
||||
let placeHolder = newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
|
||||
fillBody(a, typ, result.ast[bodyPos], d, placeHolder)
|
||||
if not a.canRaise:
|
||||
ensureMutable result
|
||||
incl result.flagsImpl, sfNeverRaises
|
||||
if not a.canRaise: incl result.flags, sfNeverRaises
|
||||
|
||||
|
||||
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||
@@ -1300,7 +1286,7 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I
|
||||
else:
|
||||
localError(g.config, info, "unresolved generic parameter")
|
||||
|
||||
proc isTrivial*(s: PSym): bool {.inline.} =
|
||||
proc isTrival*(s: PSym): bool {.inline.} =
|
||||
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
|
||||
|
||||
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
|
||||
@@ -1309,13 +1295,11 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||
## to ensure we lift assignment, destructors and moves properly.
|
||||
## The later 'injectdestructors' pass depends on it.
|
||||
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.flags != {}: return
|
||||
# IC: review this solution again later
|
||||
incl orig.flagsImpl, tfCheckedForDestructor
|
||||
incl orig.flags, tfCheckedForDestructor
|
||||
# for user defined generic destructors:
|
||||
let origRoot = genericRoot(orig)
|
||||
if origRoot != nil:
|
||||
# IC: review this solution again later
|
||||
incl origRoot.flagsImpl, tfGenericHasDestructor
|
||||
incl origRoot.flags, tfGenericHasDestructor
|
||||
|
||||
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return
|
||||
@@ -1341,7 +1325,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||
# bug #15122: We need to produce all prototypes before entering the
|
||||
# mind boggling recursion. Hacks like these imply we should rewrite
|
||||
# this module.
|
||||
var generics = default(array[attachedWasMoved..attachedTrace, bool])
|
||||
var generics: array[attachedWasMoved..attachedTrace, bool] = default(array[attachedWasMoved..attachedTrace, bool])
|
||||
for k in attachedWasMoved..lastAttached:
|
||||
generics[k] = getAttachedOp(g, canon, k) != nil
|
||||
if not generics[k]:
|
||||
@@ -1357,9 +1341,8 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||
if canon != orig:
|
||||
setAttachedOp(g, idgen.module, orig, k, getAttachedOp(g, canon, k))
|
||||
|
||||
if not isTrivial(getAttachedOp(g, orig, attachedDestructor)):
|
||||
#or not isTrivial(orig.assignment) or
|
||||
# not isTrivial(orig.sink):
|
||||
# IC: review this solution again later
|
||||
orig.flagsImpl.incl tfHasAsgn
|
||||
if not isTrival(getAttachedOp(g, orig, attachedDestructor)):
|
||||
#or not isTrival(orig.assignment) or
|
||||
# not isTrival(orig.sink):
|
||||
orig.flags.incl tfHasAsgn
|
||||
# ^ XXX Breaks IC!
|
||||
|
||||
@@ -32,12 +32,12 @@ proc interestingVar(s: PSym): bool {.inline.} =
|
||||
proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode =
|
||||
let field = addUniqueField(c.objType, s, c.cache, c.idgen)
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = c.objType
|
||||
deref.typ() = c.objType
|
||||
deref.add(newSymNode(c.partialParam, info))
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add(deref)
|
||||
result.add(newSymNode(field))
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc liftLocals(n: PNode; i: int; c: var Ctx) =
|
||||
let it = n[i]
|
||||
|
||||
@@ -273,10 +273,6 @@ const
|
||||
errFloatToString* = "cannot convert '$1' to '$2'"
|
||||
|
||||
type
|
||||
FileInfoKind* = enum
|
||||
fikSource, ## A real source file path
|
||||
fikNifModule ## A NIF module suffix (not a real path)
|
||||
|
||||
TFileInfo* = object
|
||||
fullPath*: AbsoluteFile # This is a canonical full filesystem path
|
||||
projPath*: RelativeFile # This is relative to the project's root
|
||||
@@ -295,7 +291,6 @@ type
|
||||
# for 'nimsuggest'
|
||||
hash*: string # the checksum of the file
|
||||
dirty*: bool # for 'nimpretty' like tooling
|
||||
kind*: FileInfoKind # distinguishes real files from NIF suffixes
|
||||
when defined(nimpretty):
|
||||
fullContent*: string
|
||||
FileIndex* = distinct int32
|
||||
|
||||
@@ -311,7 +311,7 @@ proc errorSym*(c: PContext, ident: PIdent, info: TLineInfo): PSym =
|
||||
## creates an error symbol to avoid cascading errors (for IDE support)
|
||||
result = newSym(skError, ident, c.idgen, getCurrOwner(c), info, {})
|
||||
result.typ = errorType(c)
|
||||
incl(result.flagsImpl, sfDiscardable)
|
||||
incl(result.flags, sfDiscardable)
|
||||
# pretend it's from the top level scope to prevent cascading errors:
|
||||
if c.config.cmd != cmdInteractive and c.compilesContextId == 0:
|
||||
c.moduleScope.addSym(result)
|
||||
@@ -388,7 +388,7 @@ proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) =
|
||||
if sym.name.id == ord(wUnderscore): return
|
||||
let conflict = scope.addUniqueSym(sym)
|
||||
if conflict != nil:
|
||||
if sym.kind == skModule and conflict.kind == skModule and not c.config.isDefined("nimPreviewDuplicateModuleError"):
|
||||
if sym.kind == skModule and conflict.kind == skModule:
|
||||
# e.g.: import foo; import foo
|
||||
# xxx we could refine this by issuing a different hint for the case
|
||||
# where a duplicate import happens inside an include.
|
||||
|
||||
@@ -82,7 +82,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: P
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen,
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
tempAsNode = newSymNode(temp)
|
||||
|
||||
var v = newNodeI(nkVarSection, value.info)
|
||||
@@ -103,7 +103,7 @@ proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): P
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen,
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
var v = newNodeI(nkLetSection, value.info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
@@ -127,8 +127,8 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNod
|
||||
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
|
||||
var temp = newSym(skVar, getIdent(g.cache, genPrefix), idgen, owner, n.info, owner.options)
|
||||
temp.typ = n[1].typ
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flagsImpl, sfGenSym)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
incl(temp.flags, sfGenSym)
|
||||
|
||||
var v = newNodeI(nkVarSection, n.info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
@@ -147,13 +147,13 @@ proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo
|
||||
result = newType(tyObject, idgen, owner)
|
||||
if final:
|
||||
rawAddSon(result, nil)
|
||||
incl result, tfFinal
|
||||
incl result.flags, tfFinal
|
||||
else:
|
||||
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
|
||||
result.n = newNodeI(nkRecList, info)
|
||||
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
|
||||
idgen, owner, info, owner.options)
|
||||
incl s.flagsImpl, sfAnon
|
||||
incl s.flags, sfAnon
|
||||
s.typ = result
|
||||
result.sym = s
|
||||
|
||||
@@ -174,12 +174,12 @@ proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode =
|
||||
# returns a[].field as a node
|
||||
assert field.kind == skField
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst)[0]
|
||||
deref.typ() = a.typ.skipTypes(abstractInst)[0]
|
||||
deref.add a
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc rawDirectAccess*(obj, field: PSym): PNode =
|
||||
# returns a.field as a node
|
||||
@@ -187,7 +187,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode =
|
||||
result = newNodeI(nkDotExpr, field.info)
|
||||
result.add newSymNode(obj)
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc lookupInRecord(n: PNode, id: ItemId): PSym =
|
||||
result = nil
|
||||
@@ -250,12 +250,12 @@ proc newDotExpr*(obj, b: PSym): PNode =
|
||||
assert field != nil, b.name.s
|
||||
result.add newSymNode(obj)
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode =
|
||||
# returns a[].b as a node
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst).elementType
|
||||
deref.typ() = a.typ.skipTypes(abstractInst).elementType
|
||||
var t = deref.typ.skipTypes(abstractInst)
|
||||
var field: PSym
|
||||
while true:
|
||||
@@ -273,12 +273,12 @@ proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode =
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode =
|
||||
# returns a[].b as a node
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst).elementType
|
||||
deref.typ() = a.typ.skipTypes(abstractInst).elementType
|
||||
var t = deref.typ.skipTypes(abstractInst)
|
||||
var field: PSym
|
||||
let bb = getIdent(cache, b)
|
||||
@@ -297,7 +297,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): P
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc getFieldFromObj*(t: PType; v: PSym): PSym =
|
||||
assert v.kind != skField
|
||||
@@ -320,7 +320,7 @@ proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
|
||||
proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode =
|
||||
result = newNodeI(nkAddr, n.info, 1)
|
||||
result[0] = n
|
||||
result.typ = newType(typeKind, idgen, n.typ.owner)
|
||||
result.typ() = newType(typeKind, idgen, n.typ.owner)
|
||||
result.typ.rawAddSon(n.typ)
|
||||
|
||||
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
|
||||
@@ -344,18 +344,18 @@ proc callCodegenProc*(g: ModuleGraph; name: string;
|
||||
if optionalArgs != nil:
|
||||
for i in 1..<optionalArgs.len-2:
|
||||
result.add optionalArgs[i]
|
||||
result.typ = sym.typ.returnType
|
||||
result.typ() = sym.typ.returnType
|
||||
|
||||
proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
|
||||
result = nkIntLit.newIntNode(value)
|
||||
result.typ = getSysType(g, info, tyInt)
|
||||
result.typ() = getSysType(g, info, tyInt)
|
||||
|
||||
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
result.typ() = getSysType(g, n.info, tyInt)
|
||||
result[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
|
||||
result[1] = n
|
||||
|
||||
@@ -364,7 +364,7 @@ proc genLen*(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
result.typ() = getSysType(g, n.info, tyInt)
|
||||
result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
|
||||
result[1] = n
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Built-in types and compilerprocs are registered here.
|
||||
|
||||
import
|
||||
ast, msgs, platform, idents,
|
||||
ast, astalgo, msgs, platform, idents,
|
||||
modulegraphs, lineinfos
|
||||
|
||||
export createMagic
|
||||
@@ -166,4 +166,4 @@ proc makeAddr*(n: PNode; idgen: IdGenerator): PNode =
|
||||
result = n
|
||||
else:
|
||||
result = newTree(nkHiddenAddr, n)
|
||||
result.typ = makePtrType(n.typ.skipTypes({tySink}), idgen)
|
||||
result.typ() = makePtrType(n.typ.skipTypes({tySink}), idgen)
|
||||
|
||||
@@ -32,10 +32,6 @@ import ../dist/checksums/src/checksums/sha1
|
||||
|
||||
import pipelines
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
import nifbackend
|
||||
import deps
|
||||
|
||||
when not defined(leanCompiler):
|
||||
import docgen
|
||||
|
||||
@@ -137,22 +133,6 @@ proc commandCompileToNif(graph: ModuleGraph) =
|
||||
setPipeLinePass(graph, NifgenPass)
|
||||
compilePipelineProject(graph)
|
||||
|
||||
proc commandNifC(graph: ModuleGraph) =
|
||||
## Generate C code from precompiled NIF files.
|
||||
## This is the new IC approach: compile modules to NIF first with `nim m`,
|
||||
## then generate C code from the entry.nif file with whole-program DCE.
|
||||
when not defined(nimKochBootstrap):
|
||||
let conf = graph.config
|
||||
extccomp.initVars(conf)
|
||||
|
||||
if not extccomp.ccHasSaneOverflow(conf):
|
||||
conf.symbols.defineSymbol("nimEmulateOverflowChecks")
|
||||
|
||||
# Use the NIF backend to generate C code
|
||||
nifbackend.generateCode(graph, conf.projectMainIdx)
|
||||
else:
|
||||
rawMessage(graph.config, errGenerated, "NIF backend not available during bootstrap build")
|
||||
|
||||
proc commandCompileToC(graph: ModuleGraph) =
|
||||
let conf = graph.config
|
||||
extccomp.initVars(conf)
|
||||
@@ -220,7 +200,7 @@ proc commandInteractive(graph: ModuleGraph) =
|
||||
discard graph.compilePipelineModule(fileInfoIdx(graph.config, graph.config.projectFull), {})
|
||||
else:
|
||||
var m = graph.makeStdinModule()
|
||||
incl(m, sfMainModule)
|
||||
incl(m.flags, sfMainModule)
|
||||
var idgen = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0)
|
||||
let s = llStreamOpenStdIn(onPrompt = proc() = flushDot(graph.config))
|
||||
discard processPipelineModule(graph, m, idgen, s)
|
||||
@@ -440,24 +420,9 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
of cmdCheck:
|
||||
commandCheck(graph)
|
||||
of cmdM:
|
||||
# cmdM uses NIF files, not ROD files
|
||||
graph.config.symbolFiles = disabledSf
|
||||
setUseIc(true)
|
||||
graph.config.symbolFiles = v2Sf
|
||||
setUseIc(graph.config.symbolFiles != disabledSf)
|
||||
commandCheck(graph)
|
||||
of cmdNifC:
|
||||
setUseIc(true)
|
||||
# Generate C code from NIF files
|
||||
wantMainModule(conf)
|
||||
setOutFile(conf)
|
||||
commandNifC(graph)
|
||||
of cmdIc:
|
||||
# Generate .build.nif for nifmake
|
||||
setUseIc(true)
|
||||
wantMainModule(conf)
|
||||
when not defined(nimKochBootstrap):
|
||||
commandIc(conf)
|
||||
else:
|
||||
rawMessage(conf, errGenerated, "nim deps not available in bootstrap build")
|
||||
of cmdParse:
|
||||
wantMainModule(conf)
|
||||
discard parseFile(conf.projectMainIdx, cache, conf)
|
||||
|
||||
@@ -11,16 +11,11 @@
|
||||
## represents a complete Nim project. Single modules can either be kept in RAM
|
||||
## or stored in a rod-file.
|
||||
|
||||
import std/[intsets, tables, hashes, strtabs, os, strutils, parseutils]
|
||||
import std/[intsets, tables, hashes, strtabs, algorithm, os, strutils, parseutils]
|
||||
import ../dist/checksums/src/checksums/md5
|
||||
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages, suggestsymdb
|
||||
import ic / [packed_ast, ic]
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
import ast2nif
|
||||
import "../dist/nimony/src/lib" / [nifstreams, bitabs]
|
||||
|
||||
import typekeys
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -81,8 +76,6 @@ type
|
||||
typeInstCache*: Table[ItemId, seq[LazyType]] # A symbol's ItemId.
|
||||
procInstCache*: Table[ItemId, seq[LazyInstantiation]] # A symbol's ItemId.
|
||||
attachedOps*: array[TTypeAttachedOp, Table[ItemId, LazySym]] # Type ID, destructors, etc.
|
||||
loadedOps: array[TTypeAttachedOp, Table[string, PSym]] # This can later by unified with `attachedOps` once it's stable
|
||||
opsLog*: seq[LogEntry]
|
||||
methodsPerGenericType*: Table[ItemId, seq[(int, LazySym)]] # Type ID, attached methods
|
||||
memberProcsPerType*: Table[ItemId, seq[PSym]] # Type ID, attached member procs (only c++, virtual,member and ctor so far).
|
||||
initializersPerType*: Table[ItemId, PNode] # Type ID, AST call to the default ctor (c++ only)
|
||||
@@ -145,7 +138,6 @@ type
|
||||
cachedFiles*: StringTableRef
|
||||
|
||||
procGlobals*: seq[PNode]
|
||||
nifReplayActions*: Table[int32, seq[PNode]] # module position -> replay actions for NIF
|
||||
|
||||
TPassContext* = object of RootObj # the pass's context
|
||||
idgen*: IdGenerator
|
||||
@@ -170,9 +162,6 @@ proc resetForBackend*(g: ModuleGraph) =
|
||||
g.enumToStringProcs.clear()
|
||||
g.dispatchers.setLen(0)
|
||||
g.methodsPerType.clear()
|
||||
for a in mitems(g.loadedOps):
|
||||
a.clear()
|
||||
g.opsLog.setLen(0)
|
||||
|
||||
const
|
||||
cb64 = [
|
||||
@@ -368,32 +357,13 @@ proc getAttachedOp*(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym =
|
||||
## if no such operation exists.
|
||||
if g.attachedOps[op].contains(t.itemId):
|
||||
result = resolveAttachedOp(g, g.attachedOps[op][t.itemId])
|
||||
elif g.config.cmd in {cmdNifC, cmdM}:
|
||||
# Fall back to key-based lookup for NIF-loaded hooks
|
||||
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
|
||||
result = g.loadedOps[op].getOrDefault(key)
|
||||
#echo "fallback ", key, " ", op, " ", result
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
||||
## we also need to record this to the packed module.
|
||||
if not g.attachedOps[op].contains(t.itemId):
|
||||
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
|
||||
# Use key-based deduplication for opsLog because different type objects
|
||||
# (e.g. canon vs orig) can have different itemIds but same structural key
|
||||
if key notin g.loadedOps[op]:
|
||||
# Hooks should be written to the module where the type is defined,
|
||||
# not the module that triggered the registration
|
||||
let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: module
|
||||
g.opsLog.add LogEntry(kind: HookEntry, op: op, module: ownerModule, key: key, sym: value)
|
||||
g.loadedOps[op][key] = value
|
||||
g.attachedOps[op][t.itemId] = LazySym(sym: value)
|
||||
|
||||
proc setAttachedOp*(g: ModuleGraph; module: int; typeId: ItemId; op: TTypeAttachedOp; value: PSym) =
|
||||
## Overload that takes ItemId directly, useful for registering hooks from NIF index.
|
||||
g.attachedOps[op][typeId] = LazySym(sym: value)
|
||||
|
||||
proc setAttachedOpPartial*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
||||
## we also need to record this to the packed module.
|
||||
g.attachedOps[op][t.itemId] = LazySym(sym: value)
|
||||
@@ -421,10 +391,6 @@ proc setMethodsPerType*(g: ModuleGraph; id: ItemId, methods: seq[LazySym]) =
|
||||
# TODO: add it for packed modules
|
||||
g.methodsPerType[id] = methods
|
||||
|
||||
proc addNifReplayAction*(g: ModuleGraph; module: int32; n: PNode) =
|
||||
## Stores a replay action for NIF-based incremental compilation.
|
||||
g.nifReplayActions.mgetOrPut(module, @[]).add n
|
||||
|
||||
iterator getMethodsPerType*(g: ModuleGraph; t: PType): PSym =
|
||||
if g.methodsPerType.contains(t.itemId):
|
||||
for it in mitems g.methodsPerType[t.itemId]:
|
||||
@@ -436,9 +402,6 @@ proc getToStringProc*(g: ModuleGraph; t: PType): PSym =
|
||||
|
||||
proc setToStringProc*(g: ModuleGraph; t: PType; value: PSym) =
|
||||
g.enumToStringProcs[t.itemId] = LazySym(sym: value)
|
||||
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
|
||||
let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: value.itemId.module.int
|
||||
g.opsLog.add LogEntry(kind: EnumToStrEntry, module: ownerModule, key: key, sym: value)
|
||||
|
||||
iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) =
|
||||
if g.methodsPerGenericType.contains(t.itemId):
|
||||
@@ -447,17 +410,6 @@ iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) =
|
||||
|
||||
proc addMethodToGeneric*(g: ModuleGraph; module: int; t: PType; col: int; m: PSym) =
|
||||
g.methodsPerGenericType.mgetOrPut(t.itemId, @[]).add (col, LazySym(sym: m))
|
||||
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
|
||||
let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: module
|
||||
g.opsLog.add LogEntry(kind: MethodEntry, module: ownerModule, key: key, sym: m)
|
||||
|
||||
proc logGenericInstance*(g: ModuleGraph; inst: PSym) =
|
||||
## Log a generic instance so it gets written to the NIF file.
|
||||
## This is needed when generic instances are created during compile-time
|
||||
## evaluation and may be referenced from other modules compiled in the same run.
|
||||
if g.config.cmd in {cmdNifC, cmdM}:
|
||||
let ownerModule = inst.itemId.module.int
|
||||
g.opsLog.add LogEntry(kind: GenericInstEntry, module: ownerModule, sym: inst)
|
||||
|
||||
proc hasDisabledAsgn*(g: ModuleGraph; t: PType): bool =
|
||||
let op = getAttachedOp(g, t, attachedAsgn)
|
||||
@@ -471,30 +423,7 @@ proc copyTypeProps*(g: ModuleGraph; module: int; dest, src: PType) =
|
||||
|
||||
proc loadCompilerProc*(g: ModuleGraph; name: string): PSym =
|
||||
result = nil
|
||||
if g.config.symbolFiles == disabledSf and optWithinConfigSystem notin g.config.globalOptions:
|
||||
# For NIF-based compilation, search in loaded NIF modules
|
||||
when not defined(nimKochBootstrap):
|
||||
# Only try to resolve from NIF if we're actually using NIF files (cmdNifC)
|
||||
if g.config.cmd == cmdNifC:
|
||||
# First try system module (most compilerprocs are there)
|
||||
let systemFileIdx = g.config.m.systemFileIdx
|
||||
if systemFileIdx != InvalidFileIdx:
|
||||
result = tryResolveCompilerProc(ast.program, name, systemFileIdx)
|
||||
if result != nil:
|
||||
strTableAdd(g.compilerprocs, result)
|
||||
return result
|
||||
|
||||
# Try threadpool module (some compilerprocs like FlowVar are there)
|
||||
# Find threadpool module by searching loaded modules
|
||||
for moduleIdx in 0..<g.ifaces.len:
|
||||
let module = g.ifaces[moduleIdx].module
|
||||
if module != nil and module.name.s == "threadpool":
|
||||
let threadpoolFileIdx = module.position.FileIndex
|
||||
result = tryResolveCompilerProc(ast.program, name, threadpoolFileIdx)
|
||||
if result != nil:
|
||||
strTableAdd(g.compilerprocs, result)
|
||||
return result
|
||||
return nil
|
||||
if g.config.symbolFiles == disabledSf: return nil
|
||||
|
||||
# slow, linear search, but the results are cached:
|
||||
for module in 0..<len(g.packed):
|
||||
@@ -599,10 +528,9 @@ proc registerModule*(g: ModuleGraph; m: PSym) =
|
||||
if m.position >= g.packed.len:
|
||||
setLen(g.packed.pm, m.position + 1)
|
||||
|
||||
if g.ifaces[m.position].module == nil:
|
||||
g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[],
|
||||
uniqueName: rope(uniqueModuleName(g.config, m)))
|
||||
initStrTables(g, m)
|
||||
g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[],
|
||||
uniqueName: rope(uniqueModuleName(g.config, m)))
|
||||
initStrTables(g, m)
|
||||
|
||||
proc registerModuleById*(g: ModuleGraph; m: FileIndex) =
|
||||
registerModule(g, g.packed[int m].module)
|
||||
@@ -658,7 +586,6 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result.config = config
|
||||
result.cache = cache
|
||||
initModuleGraphFields(result)
|
||||
ast.setupProgram(config, cache)
|
||||
|
||||
proc resetAllModules*(g: ModuleGraph) =
|
||||
g.packageSyms = initStrTable()
|
||||
@@ -754,13 +681,13 @@ proc markDirty*(g: ModuleGraph; fileIdx: FileIndex) =
|
||||
if m != nil:
|
||||
g.suggestSymbols.del(fileIdx)
|
||||
g.suggestErrors.del(fileIdx)
|
||||
incl m.flagsImpl, sfDirty
|
||||
incl m.flags, sfDirty
|
||||
|
||||
proc unmarkAllDirty*(g: ModuleGraph) =
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
let m = g.ifaces[i].module
|
||||
if m != nil:
|
||||
m.flagsImpl.excl sfDirty
|
||||
m.flags.excl sfDirty
|
||||
|
||||
proc isDirty*(g: ModuleGraph; m: PSym): bool =
|
||||
result = g.suggestMode and sfDirty in m.flags
|
||||
@@ -813,49 +740,6 @@ proc moduleFromRodFile*(g: ModuleGraph; fileIdx: FileIndex;
|
||||
else:
|
||||
result = nil
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
proc moduleFromNifFile*(g: ModuleGraph; fileIdx: FileIndex;
|
||||
flags: set[LoadFlag] = {}): PrecompiledModule =
|
||||
## Returns 'nil' if the module needs to be recompiled.
|
||||
## Loads module from NIF file when optCompress is enabled.
|
||||
## When loadFullAst is true, loads the complete module AST for code generation.
|
||||
if not fileExists(toNifFilename(g.config, fileIdx)):
|
||||
return PrecompiledModule(module: nil)
|
||||
|
||||
# Create module symbol
|
||||
let filename = AbsoluteFile toFullPath(g.config, fileIdx)
|
||||
|
||||
let m = PSym(
|
||||
kindImpl: skModule,
|
||||
itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
name: getIdent(g.cache, splitFile(filename).name),
|
||||
infoImpl: newLineInfo(fileIdx, 1, 1),
|
||||
positionImpl: int(fileIdx))
|
||||
setOwner(m, getPackage(g.config, g.cache, fileIdx))
|
||||
# Register module in graph
|
||||
registerModule(g, m)
|
||||
|
||||
result = loadNifModule(ast.program, fileIdx,
|
||||
g.ifaces[fileIdx.int].interf,
|
||||
g.ifaces[fileIdx.int].interfHidden, flags)
|
||||
result.module = m
|
||||
|
||||
# Register hooks from NIF index with the module graph
|
||||
for x in result.logOps:
|
||||
case x.kind
|
||||
of HookEntry:
|
||||
g.loadedOps[x.op][x.key] = x.sym
|
||||
of ConverterEntry:
|
||||
g.ifaces[fileIdx.int].converters.add LazySym(sym: x.sym)
|
||||
of MethodEntry:
|
||||
discard "todo"
|
||||
of EnumToStrEntry:
|
||||
discard "todo"
|
||||
of GenericInstEntry:
|
||||
raiseAssert "GenericInstEntry should not be in the NIF index"
|
||||
# Register methods per type from NIF index
|
||||
discard "todo"
|
||||
|
||||
proc configComplete*(g: ModuleGraph) =
|
||||
rememberStartupConfig(g.startupPackedConfig, g.config)
|
||||
|
||||
@@ -880,7 +764,7 @@ proc getPackage*(graph: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
result = pkgSym
|
||||
graph.packageSyms.strTableAdd(pkgSym)
|
||||
|
||||
proc belongsToStdlib*(graph: ModuleGraph, sym: PSym): bool =
|
||||
func belongsToStdlib*(graph: ModuleGraph, sym: PSym): bool =
|
||||
## Check if symbol belongs to the 'stdlib' package.
|
||||
sym.getPackageSymbol.getPackageId == graph.systemModule.getPackageId
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ proc newModule*(graph: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
|
||||
# We cannot call ``newSym`` here, because we have to circumvent the ID
|
||||
# mechanism, which we do in order to assign each module a persistent ID.
|
||||
result = PSym(kindImpl: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
result = PSym(kind: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
name: getModuleIdent(graph, filename),
|
||||
infoImpl: newLineInfo(fileIdx, 1, 1))
|
||||
info: newLineInfo(fileIdx, 1, 1))
|
||||
if not isNimIdentifier(result.name.s):
|
||||
rawMessage(graph.config, errGenerated, "invalid module name: '" & result.name.s &
|
||||
"'; a module name must be a valid Nim identifier.")
|
||||
|
||||
@@ -30,6 +30,7 @@ proc toLowerAscii(a: var string) {.inline.} =
|
||||
|
||||
proc flushDot*(conf: ConfigRef) =
|
||||
## safe to call multiple times
|
||||
# xxx one edge case not yet handled is when `printf` is called at CT with `compiletimeFFI`.
|
||||
let stdOrr = if optStdout in conf.globalOptions: stdout else: stderr
|
||||
let stdOrrKind = toStdOrrKind(stdOrr)
|
||||
if stdOrrKind in conf.lastMsgWasDot:
|
||||
@@ -51,7 +52,7 @@ proc makeCString*(s: string): Rope =
|
||||
result = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
|
||||
result.add("\"")
|
||||
for i in 0..<s.len:
|
||||
# line wrapping of string literals in cgen'd code was a bad idea, e.g. causes: bug #16265
|
||||
# line wrapping of string litterals in cgen'd code was a bad idea, e.g. causes: bug #16265
|
||||
# It also makes reading c sources or grepping harder, for zero benefit.
|
||||
# const MaxLineLength = 64
|
||||
# if (i + 1) mod MaxLineLength == 0:
|
||||
@@ -59,12 +60,12 @@ proc makeCString*(s: string): Rope =
|
||||
toCChar(s[i], result)
|
||||
result.add('\"')
|
||||
|
||||
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile; kind = fikSource): TFileInfo =
|
||||
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
|
||||
result = TFileInfo(fullPath: fullPath, projPath: projPath,
|
||||
shortName: fullPath.extractFilename,
|
||||
quotedFullName: fullPath.string.makeCString,
|
||||
lines: @[],
|
||||
kind: kind)
|
||||
lines: @[]
|
||||
)
|
||||
result.quotedName = result.shortName.makeCString
|
||||
when defined(nimpretty):
|
||||
if not result.fullPath.isEmpty:
|
||||
@@ -132,23 +133,6 @@ proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
|
||||
var dummy: bool = false
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
|
||||
|
||||
proc registerNifSuffix*(conf: ConfigRef; suffix: string; isKnownFile: var bool): FileIndex =
|
||||
result = conf.m.filenameToIndexTbl.getOrDefault(suffix, InvalidFileIdx)
|
||||
if result == InvalidFileIdx:
|
||||
isKnownFile = false
|
||||
result = conf.m.fileInfos.len.FileIndex
|
||||
conf.m.fileInfos.add(newFileInfo(AbsoluteFile suffix, RelativeFile suffix, fikNifModule))
|
||||
conf.m.filenameToIndexTbl[suffix] = result
|
||||
else:
|
||||
isKnownFile = true
|
||||
|
||||
proc fileInfoKind*(conf: ConfigRef; fileIdx: FileIndex): FileInfoKind =
|
||||
## Returns the kind of a FileIndex (source file or NIF module suffix).
|
||||
if fileIdx.int >= 0 and fileIdx.int < conf.m.fileInfos.len:
|
||||
result = conf.m.fileInfos[fileIdx.int].kind
|
||||
else:
|
||||
result = fikSource # Default to source for unknown indices
|
||||
|
||||
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
|
||||
result = TLineInfo(fileIndex: fileInfoIdx)
|
||||
if line < int high(uint16):
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2025 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## NIF-based C/C++ code generator backend.
|
||||
##
|
||||
## This module implements C code generation from precompiled NIF files.
|
||||
## It traverses the module dependency graph starting from the main module
|
||||
## and generates C code for all reachable modules.
|
||||
##
|
||||
## Usage:
|
||||
## 1. Compile modules to NIF: nim m mymodule.nim
|
||||
## 2. Generate C from NIF: nim nifc myproject.nim
|
||||
|
||||
import std/[intsets, tables, sets, os]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ast, options, lineinfos, modulegraphs, cgendata, cgen,
|
||||
pathutils, extccomp, msgs, modulepaths, idents, types, ast2nif
|
||||
|
||||
proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[PrecompiledModule] =
|
||||
## Traverse the module dependency graph using a stack.
|
||||
## Returns all modules that need code generation, in dependency order.
|
||||
let mainModule = moduleFromNifFile(g, mainFileIdx, {LoadFullAst})
|
||||
|
||||
var stack: seq[ModuleSuffix] = @[]
|
||||
result = @[]
|
||||
|
||||
if mainModule.module != nil:
|
||||
incl mainModule.module.flagsImpl, sfMainModule
|
||||
for dep in mainModule.deps:
|
||||
stack.add dep
|
||||
|
||||
var visited = initHashSet[string]()
|
||||
|
||||
while stack.len > 0:
|
||||
let suffix = stack.pop()
|
||||
|
||||
if not visited.containsOrIncl(suffix.string):
|
||||
let nifFile = toGeneratedFile(g.config, AbsoluteFile(suffix.string), ".nif")
|
||||
let fileIdx = msgs.fileInfoIdx(g.config, nifFile)
|
||||
let precomp = moduleFromNifFile(g, fileIdx, {LoadFullAst})
|
||||
if precomp.module != nil:
|
||||
result.add precomp
|
||||
for dep in precomp.deps:
|
||||
if not visited.contains(dep.string):
|
||||
stack.add dep
|
||||
|
||||
if mainModule.module != nil:
|
||||
result.add mainModule
|
||||
|
||||
proc setupNifBackendModule(g: ModuleGraph; module: PSym): BModule =
|
||||
## Set up a BModule for code generation from a NIF module.
|
||||
if g.backend == nil:
|
||||
g.backend = cgendata.newModuleList(g)
|
||||
result = cgen.newModule(BModuleList(g.backend), module, g.config, idGeneratorFromModule(module))
|
||||
|
||||
proc finishModule(g: ModuleGraph; bmod: BModule) =
|
||||
# Finalize the module (this adds it to modulesClosed)
|
||||
# Create an empty stmt list as the init body - genInitCode in writeModule will set it up properly
|
||||
let initStmt = newNode(nkStmtList)
|
||||
finalCodegenActions(g, bmod, initStmt)
|
||||
|
||||
# Generate dispatcher methods
|
||||
for disp in getDispatchers(g):
|
||||
genProcLvl3(bmod, disp)
|
||||
|
||||
proc generateCodeForModule(g: ModuleGraph; precomp: PrecompiledModule) =
|
||||
## Generate C code for a single module.
|
||||
let moduleId = precomp.module.position
|
||||
var bmod = BModuleList(g.backend).mods[moduleId]
|
||||
if bmod == nil:
|
||||
bmod = setupNifBackendModule(g, precomp.module)
|
||||
|
||||
# Generate code for the module's top-level statements
|
||||
if precomp.topLevel != nil:
|
||||
cgen.genTopLevelStmt(bmod, precomp.topLevel)
|
||||
|
||||
proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
|
||||
## Main entry point for NIF-based C code generation.
|
||||
## Traverses the module dependency graph and generates C code.
|
||||
|
||||
# Reset backend state
|
||||
resetForBackend(g)
|
||||
|
||||
var isKnownFile = false
|
||||
let systemFileIdx = registerNifSuffix(g.config, "sysma2dyk", isKnownFile)
|
||||
g.config.m.systemFileIdx = systemFileIdx
|
||||
#msgs.fileInfoIdx(g.config,
|
||||
# g.config.libpath / RelativeFile"system.nim")
|
||||
|
||||
# Load system module first - it's always needed and contains essential hooks
|
||||
var precompSys = PrecompiledModule(module: nil)
|
||||
precompSys = moduleFromNifFile(g, systemFileIdx, {LoadFullAst, AlwaysLoadInterface})
|
||||
g.systemModule = precompSys.module
|
||||
|
||||
# Load all modules in dependency order using stack traversal
|
||||
# This must happen BEFORE any code generation so that hooks are loaded into loadedOps
|
||||
let modules = loadModuleDependencies(g, mainFileIdx)
|
||||
if modules.len == 0:
|
||||
rawMessage(g.config, errGenerated,
|
||||
"Cannot load NIF file for main module: " & toFullPath(g.config, mainFileIdx))
|
||||
return
|
||||
|
||||
# Set up backend modules for all modules that need code generation
|
||||
for m in modules:
|
||||
discard setupNifBackendModule(g, m.module)
|
||||
|
||||
# Also ensure system module is set up and generated first if it exists
|
||||
if precompSys.module != nil:
|
||||
discard setupNifBackendModule(g, precompSys.module)
|
||||
generateCodeForModule(g, precompSys)
|
||||
|
||||
# Track which modules have been processed to avoid duplicates
|
||||
var processed = initIntSet()
|
||||
if precompSys.module != nil:
|
||||
processed.incl precompSys.module.position
|
||||
|
||||
# Generate code for all modules (skip system since it's already processed)
|
||||
for m in modules:
|
||||
if not processed.containsOrIncl(m.module.position):
|
||||
generateCodeForModule(g, m)
|
||||
|
||||
# during code generation of `main.nim` we can trigger the code generation
|
||||
# of symbols in different modules so we need to finish these modules
|
||||
# here later, after the above loop!
|
||||
# Important: The main module must be finished LAST so that all other modules
|
||||
# have registered their init procs before genMainProc uses them.
|
||||
var mainModule: BModule = nil
|
||||
for m in BModuleList(g.backend).mods:
|
||||
if m != nil:
|
||||
assert m.module != nil
|
||||
if sfMainModule in m.module.flags:
|
||||
mainModule = m
|
||||
else:
|
||||
finishModule g, m
|
||||
if mainModule != nil:
|
||||
finishModule g, mainModule
|
||||
|
||||
# Write C files
|
||||
cgenWriteModules(g.backend, g.config)
|
||||
|
||||
# Run C compiler
|
||||
if g.config.cmd != cmdTcc:
|
||||
extccomp.callCCompiler(g.config)
|
||||
if not g.config.hcrOn:
|
||||
extccomp.writeJsonBuildInstructions(g.config, g.cachedFiles)
|
||||
@@ -919,7 +919,7 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode =
|
||||
newSymNode(op, r.info),
|
||||
l,
|
||||
r)
|
||||
result.typ = newType(tyBool, ctx.idgen, nil)
|
||||
result.typ() = newType(tyBool, ctx.idgen, nil)
|
||||
|
||||
proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
|
||||
var cache = newIdentCache()
|
||||
@@ -929,7 +929,7 @@ proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
|
||||
result = nkPrefix.newTree(
|
||||
newSymNode(op, node.info),
|
||||
node)
|
||||
result.typ = newType(tyBool, ctx.idgen, nil)
|
||||
result.typ() = newType(tyBool, ctx.idgen, nil)
|
||||
|
||||
proc infixEq(ctx: NilCheckerContext, l: PNode, r: PNode): PNode =
|
||||
infix(ctx, l, r, mEqRef)
|
||||
|
||||
@@ -12,8 +12,6 @@ define:nimPreviewNonVarDestructor
|
||||
define:nimPreviewCheckedClose
|
||||
define:nimPreviewAsmSemSymbol
|
||||
define:nimPreviewCStringComparisons
|
||||
define:nimPreviewDuplicateModuleError
|
||||
|
||||
threads:off
|
||||
|
||||
#import:"$projectpath/testability"
|
||||
|
||||
@@ -118,7 +118,7 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
|
||||
if conf.selectedGC == gcUnselected:
|
||||
if conf.backend in {backendC, backendCpp, backendObjc} or
|
||||
(conf.cmd in cmdDocLike and conf.backend != backendJs) or
|
||||
conf.cmd in {cmdGendepend, cmdNifC, cmdIc, cmdM}:
|
||||
conf.cmd == cmdGendepend:
|
||||
initOrcDefines(conf)
|
||||
|
||||
mainCommand(graph)
|
||||
|
||||
@@ -207,6 +207,7 @@ proc parseAssignment(L: var Lexer, tok: var Token;
|
||||
checkSymbol(L, tok)
|
||||
val.add($tok)
|
||||
confTok(L, tok, config, condStack)
|
||||
config.currentConfigDir = parentDir(filename.string)
|
||||
if percent:
|
||||
processSwitch(s, strtabs.`%`(val, config.configVars,
|
||||
{useEnvironment, useEmpty}), passPP, info, config)
|
||||
@@ -248,8 +249,6 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen:
|
||||
setDefaultLibpath(conf)
|
||||
template readConfigFile(path) =
|
||||
let configPath = path
|
||||
conf.currentConfigDir = configPath.splitFile.dir.string
|
||||
setConfigVar(conf, "selfDir", conf.currentConfigDir)
|
||||
if readConfigFile(configPath, cache, conf):
|
||||
conf.configFiles.add(configPath)
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ proc createInterpreter*(scriptName: string;
|
||||
if conf.libpath.isEmpty: conf.libpath = AbsoluteDir p
|
||||
|
||||
var m = graph.makeModule(scriptName)
|
||||
incl(m, sfMainModule)
|
||||
incl(m.flags, sfMainModule)
|
||||
var idgen = idGeneratorFromModule(m)
|
||||
var vm = newCtx(m, cache, graph, idgen)
|
||||
vm.mode = emRepl
|
||||
@@ -168,7 +168,7 @@ proc runRepl*(r: TLLRepl;
|
||||
if supportNimscript: defineSymbol(conf.symbols, "nimconfig")
|
||||
when hasFFI: defineSymbol(graph.config.symbols, "nimffi")
|
||||
var m = graph.makeStdinModule()
|
||||
incl(m, sfMainModule)
|
||||
incl(m.flags, sfMainModule)
|
||||
var idgen = idGeneratorFromModule(m)
|
||||
|
||||
if supportNimscript: graph.vm = setupVM(m, cache, "stdin", graph, idgen)
|
||||
|
||||
@@ -84,7 +84,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
elemType = settype[0]
|
||||
first = firstOrd(conf, elemType).toInt64
|
||||
result = newNodeI(nkCurly, info)
|
||||
result.typ = settype
|
||||
result.typ() = settype
|
||||
result.info = info
|
||||
e = 0
|
||||
while e < s.len * ElemSize:
|
||||
@@ -101,7 +101,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
result.add aa
|
||||
else:
|
||||
n = newNodeI(nkRange, info)
|
||||
n.typ = elemType
|
||||
n.typ() = elemType
|
||||
n.add aa
|
||||
let bb = newIntTypeNode(b + first, elemType)
|
||||
bb.info = info
|
||||
|
||||
@@ -25,7 +25,7 @@ const
|
||||
useEffectSystem* = true
|
||||
useWriteTracking* = false
|
||||
hasFFI* = defined(nimHasLibFFI)
|
||||
copyrightYear* = "2026"
|
||||
copyrightYear* = "2025"
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
@@ -110,9 +110,6 @@ type # please make sure we have under 32 options
|
||||
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
|
||||
optShowNonExportedFields # for documentation: show fields that are not exported
|
||||
optJsBigInt64 # use bigints for 64-bit integers in JS
|
||||
optItaniumMangle # mangling follows the Itanium spec
|
||||
optCompress # turn on AST compression by converting it to NIF
|
||||
optWithinConfigSystem # we still compile within the configuration system
|
||||
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
|
||||
@@ -176,8 +173,6 @@ type
|
||||
cmdJsonscript # compile a .json build file
|
||||
# old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs)
|
||||
cmdCompileToNif
|
||||
cmdNifC # generate C code from NIF files
|
||||
cmdIc # generate .build.nif for nifmake
|
||||
|
||||
const
|
||||
cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||
@@ -369,7 +364,6 @@ type
|
||||
numberOfProcessors*: int # number of processors
|
||||
lastCmdTime*: float # when caas is enabled, we measure each command
|
||||
symbolFiles*: SymbolFilesOption
|
||||
ic*: bool # whether ic is enabled
|
||||
spellSuggestMax*: int # max number of spelling suggestions for typos
|
||||
|
||||
cppDefines*: HashSet[string] # (*)
|
||||
@@ -514,7 +508,7 @@ const
|
||||
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
|
||||
optTrMacros, optStyleCheck, optCursorInference}
|
||||
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
|
||||
optJsBigInt64, optItaniumMangle}
|
||||
optJsBigInt64}
|
||||
|
||||
proc getSrcTimestamp(): DateTime =
|
||||
try:
|
||||
|
||||
@@ -33,7 +33,7 @@ proc getPackage*(conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): PSym =
|
||||
pkgIdent = getIdent(cache, pkgName)
|
||||
newSym(skPackage, pkgIdent, idGeneratorForPackage(int32(fileIdx)), nil, info)
|
||||
|
||||
proc getPackageSymbol*(sym: PSym): PSym =
|
||||
func getPackageSymbol*(sym: PSym): PSym =
|
||||
## Return the owning package symbol.
|
||||
assert sym != nil
|
||||
result = sym
|
||||
@@ -41,18 +41,18 @@ proc getPackageSymbol*(sym: PSym): PSym =
|
||||
result = result.owner
|
||||
assert result != nil, repr(sym.info)
|
||||
|
||||
proc getPackageId*(sym: PSym): int =
|
||||
func getPackageId*(sym: PSym): int =
|
||||
## Return the owning package ID.
|
||||
sym.getPackageSymbol.id
|
||||
|
||||
proc belongsToProjectPackage*(conf: ConfigRef, sym: PSym): bool =
|
||||
func belongsToProjectPackage*(conf: ConfigRef, sym: PSym): bool =
|
||||
## Return whether the symbol belongs to the project's package.
|
||||
##
|
||||
## See Also:
|
||||
## * `modulegraphs.belongsToStdlib`
|
||||
conf.mainPackageId == sym.getPackageId
|
||||
|
||||
proc belongsToProjectPackageMaybeNil*(conf: ConfigRef, sym: PSym): bool =
|
||||
func belongsToProjectPackageMaybeNil*(conf: ConfigRef, sym: PSym): bool =
|
||||
## Return whether the symbol belongs to the project's package.
|
||||
## Returns `false` if `sym` is nil.
|
||||
##
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import ast, types, msgs, idents, renderer, wordrecg, trees,
|
||||
options
|
||||
|
||||
import std/[strutils, assertions]
|
||||
import std/strutils
|
||||
|
||||
# we precompile the pattern here for efficiency into some internal
|
||||
# stack based VM :-) Why? Because it's fun; I did no benchmarks to see if that
|
||||
@@ -216,11 +216,6 @@ proc exprRoot*(n: PNode; allowCalls = true): PSym =
|
||||
else:
|
||||
break
|
||||
|
||||
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult
|
||||
|
||||
proc isLentableBranch(owner: PSym, n: PNode): bool =
|
||||
result = isAssignable(owner, n) in {arLentValue, arAddressableConst, arLentValue}
|
||||
|
||||
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
## 'owner' can be nil!
|
||||
result = arNone
|
||||
@@ -313,35 +308,6 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
# nkVarTy denotes an lvalue, but the example above is the only
|
||||
# possible code which will get us here
|
||||
result = arLValue
|
||||
of nkIfExpr, nkIfStmt:
|
||||
# allow 'if' expressions to be lent if all branches are lentable
|
||||
for branch in n:
|
||||
if branch.len == 2:
|
||||
if not isLentableBranch(owner, branch[1]):
|
||||
return
|
||||
elif branch.len == 1:
|
||||
if not isLentableBranch(owner, branch[0]):
|
||||
return
|
||||
else:
|
||||
raiseAssert "Malformed `if` statement in isAssignable"
|
||||
result = arLentValue
|
||||
of nkCaseStmt:
|
||||
# allow 'case' expressions to be lent if all branches are lentable
|
||||
for i in 1 ..< n.len:
|
||||
let branch = n[i]
|
||||
case branch.kind
|
||||
of nkOfBranch:
|
||||
if not isLentableBranch(owner, branch[^1]):
|
||||
return
|
||||
of nkElifBranch:
|
||||
if not isLentableBranch(owner, branch[1]):
|
||||
return
|
||||
of nkElse:
|
||||
if not isLentableBranch(owner, branch[0]):
|
||||
return
|
||||
else:
|
||||
raiseAssert "Malformed `case` statement in isAssignable"
|
||||
result = arLentValue
|
||||
else:
|
||||
discard
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fr
|
||||
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
|
||||
if result == nil:
|
||||
result = newModule(graph, fileIdx)
|
||||
result.incl flags
|
||||
result.flags.incl flags
|
||||
registerModule(graph, result)
|
||||
processModuleAux("import")
|
||||
else:
|
||||
@@ -185,7 +185,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fr
|
||||
replayStateChanges(graph.packed.pm[m.int].module, graph)
|
||||
replayGenericCacheInformation(graph, m.int)
|
||||
elif graph.isDirty(result):
|
||||
result.excl sfDirty
|
||||
result.flags.excl sfDirty
|
||||
# reset module fields:
|
||||
initStrTables(graph, result)
|
||||
result.ast = nil
|
||||
|
||||
@@ -3,11 +3,6 @@ import sem, cgen, modulegraphs, ast, llstream, parser, msgs,
|
||||
packages, syntaxes, depends, vm, pragmas, idents, lookups, wordrecg,
|
||||
liftdestructors, nifgen
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
import vmdef
|
||||
import ast2nif
|
||||
import "../dist/nimony/src/lib" / [nifstreams, bitabs]
|
||||
|
||||
import pipelineutils
|
||||
|
||||
import ../dist/checksums/src/checksums/sha1
|
||||
@@ -40,12 +35,7 @@ proc processPipeline(graph: ModuleGraph; semNode: PNode; bModule: PPassContext):
|
||||
of GenDependPass:
|
||||
result = addDotDependency(bModule, semNode)
|
||||
of SemPass:
|
||||
# Return the semantic node for cmdM (NIF generation needs it)
|
||||
# For regular check, we don't need the result
|
||||
if graph.config.cmd == cmdM:
|
||||
result = semNode
|
||||
else:
|
||||
result = graph.emptyNode
|
||||
result = graph.emptyNode
|
||||
of Docgen2Pass, Docgen2TexPass:
|
||||
when not defined(leanCompiler):
|
||||
result = processNode(bModule, semNode)
|
||||
@@ -62,8 +52,7 @@ proc processPipeline(graph: ModuleGraph; semNode: PNode; bModule: PPassContext):
|
||||
raiseAssert "use setPipeLinePass to set a proper PipelinePass"
|
||||
|
||||
proc processImplicitImports*(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
|
||||
m: PSym, ctx: PContext, bModule: PPassContext, idgen: IdGenerator;
|
||||
topLevelStmts: PNode) =
|
||||
m: PSym, ctx: PContext, bModule: PPassContext, idgen: IdGenerator) =
|
||||
# XXX fixme this should actually be relative to the config file!
|
||||
let relativeTo = toFullPath(graph.config, m.info)
|
||||
for module in items(implicits):
|
||||
@@ -75,13 +64,8 @@ proc processImplicitImports*(graph: ModuleGraph; implicits: seq[string], nodeKin
|
||||
importStmt.add str
|
||||
message(graph.config, importStmt.info, hintProcessingStmt, $idgen[])
|
||||
let semNode = semWithPContext(ctx, importStmt)
|
||||
if semNode == nil:
|
||||
if semNode == nil or processPipeline(graph, semNode, bModule) == nil:
|
||||
break
|
||||
let top = processPipeline(graph, semNode, bModule)
|
||||
if top == nil:
|
||||
break
|
||||
if topLevelStmts != nil:
|
||||
topLevelStmts.add top
|
||||
|
||||
proc prePass*(c: PContext; n: PNode) =
|
||||
for son in n:
|
||||
@@ -103,7 +87,7 @@ proc prePass*(c: PContext; n: PNode) =
|
||||
let feature = parseEnum[Feature](name.strVal)
|
||||
if feature == codeReordering:
|
||||
c.features.incl feature
|
||||
c.module.incl sfReorder
|
||||
c.module.flags.incl sfReorder
|
||||
except ValueError:
|
||||
discard
|
||||
else:
|
||||
@@ -166,11 +150,6 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
else:
|
||||
s = stream
|
||||
graph.interactive = stream.kind == llsStdIn
|
||||
var topLevelStmts =
|
||||
if optCompress in graph.config.globalOptions or graph.config.cmd == cmdM:
|
||||
newNodeI(nkStmtList, module.info)
|
||||
else:
|
||||
nil
|
||||
while true:
|
||||
syntaxes.openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
@@ -180,8 +159,8 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
# in ROD files. I think we should enable this feature only
|
||||
# for the interactive mode.
|
||||
if module.name.s != "nimscriptapi":
|
||||
processImplicitImports graph, graph.config.implicitImports, nkImportStmt, module, ctx, bModule, idgen, topLevelStmts
|
||||
processImplicitImports graph, graph.config.implicitIncludes, nkIncludeStmt, module, ctx, bModule, idgen, topLevelStmts
|
||||
processImplicitImports graph, graph.config.implicitImports, nkImportStmt, module, ctx, bModule, idgen
|
||||
processImplicitImports graph, graph.config.implicitIncludes, nkIncludeStmt, module, ctx, bModule, idgen
|
||||
|
||||
checkFirstLineIndentation(p)
|
||||
block processCode:
|
||||
@@ -202,9 +181,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
if graph.pipelinePass != EvalPass:
|
||||
message(graph.config, sl.info, hintProcessingStmt, $idgen[])
|
||||
var semNode = semWithPContext(ctx, sl)
|
||||
let top = processPipeline(graph, semNode, bModule)
|
||||
if top != nil and topLevelStmts != nil:
|
||||
topLevelStmts.add top
|
||||
discard processPipeline(graph, semNode, bModule)
|
||||
|
||||
closeParser(p)
|
||||
if s.kind != llsStdIn: break
|
||||
@@ -221,7 +198,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
if retTyp != nil:
|
||||
# TODO: properly semcheck the code of dispatcher?
|
||||
createTypeBoundOps(graph, ctx, retTyp, disp.ast.info, idgen)
|
||||
genProcLvl3(m, disp)
|
||||
genProcAux(m, disp)
|
||||
discard closePContext(graph, ctx, nil)
|
||||
of JSgenPass:
|
||||
when not defined(leanCompiler):
|
||||
@@ -241,28 +218,10 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
of NonePass:
|
||||
raiseAssert "use setPipeLinePass to set a proper PipelinePass"
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
if (optCompress in graph.config.globalOptions or graph.config.cmd == cmdM) and
|
||||
not graph.config.isDefined("nimscript"):
|
||||
topLevelStmts.add finalNode
|
||||
# Collect replay actions from both pragma computations and VM state diff
|
||||
var replayActions: seq[PNode] = @[]
|
||||
# Get pragma-recorded replay actions (compile, link, passC, passL, etc.)
|
||||
if graph.nifReplayActions.hasKey(module.position.int32):
|
||||
replayActions.add graph.nifReplayActions[module.position.int32]
|
||||
# Also get VM state diff (macro cache operations)
|
||||
if graph.vm != nil:
|
||||
for (m, n) in PCtx(graph.vm).vmstateDiff:
|
||||
if m == module:
|
||||
replayActions.add n
|
||||
|
||||
writeNifModule(graph.config, module.position.int32, topLevelStmts, graph.opsLog, replayActions)
|
||||
|
||||
if graph.config.backend notin {backendC, backendCpp, backendObjc} and graph.config.cmd != cmdM:
|
||||
if graph.config.backend notin {backendC, backendCpp, backendObjc}:
|
||||
# We only write rod files here if no C-like backend is active.
|
||||
# The C-like backends have been patched to support the IC mechanism.
|
||||
# They are responsible for closing the rod files. See `cbackend.nim`.
|
||||
# cmdM uses NIF files only, not ROD files.
|
||||
closeRodFile(graph, module)
|
||||
result = true
|
||||
|
||||
@@ -280,23 +239,7 @@ proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymF
|
||||
discard processPipelineModule(graph, result, idGeneratorFromModule(result), s)
|
||||
if result == nil:
|
||||
var cachedModules: seq[FileIndex] = @[]
|
||||
when not defined(nimKochBootstrap):
|
||||
# For cmdM: load imports from NIF files (but compile the main module from source)
|
||||
# Skip when withinSystem is true (compiling system.nim itself)
|
||||
if graph.config.cmd == cmdM and
|
||||
sfMainModule notin flags and
|
||||
not graph.withinSystem and
|
||||
not graph.config.isDefined("nimscript"):
|
||||
let precomp = moduleFromNifFile(graph, fileIdx)
|
||||
if precomp.module == nil:
|
||||
let nifPath = toNifFilename(graph.config, fileIdx)
|
||||
localError(graph.config, unknownLineInfo,
|
||||
"nim m requires precompiled NIF for import: " & toFullPath(graph.config, fileIdx) &
|
||||
" (expected: " & nifPath & ")")
|
||||
return nil # Don't fall through to compile from source
|
||||
if result == nil and graph.config.cmd != cmdM:
|
||||
# Fall back to ROD file loading (not used for cmdM which uses NIF only)
|
||||
result = moduleFromRodFile(graph, fileIdx, cachedModules)
|
||||
result = moduleFromRodFile(graph, fileIdx, cachedModules)
|
||||
let path = toFullPath(graph.config, fileIdx)
|
||||
let filename = AbsoluteFile path
|
||||
# it could be a stdinfile/cmdfile
|
||||
@@ -304,29 +247,26 @@ proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymF
|
||||
graph.cachedFiles[path] = $secureHashFile(path)
|
||||
if result == nil:
|
||||
result = newModule(graph, fileIdx)
|
||||
result.incl flags
|
||||
result.flags.incl flags
|
||||
registerModule(graph, result)
|
||||
processModuleAux("import")
|
||||
else:
|
||||
if sfSystemModule in flags:
|
||||
graph.systemModule = result
|
||||
if sfMainModule in flags and graph.config.cmd == cmdM:
|
||||
result.incl flags
|
||||
result.flags.incl flags
|
||||
registerModule(graph, result)
|
||||
processModuleAux("import")
|
||||
partialInitModule(result, graph, fileIdx, filename)
|
||||
for m in cachedModules:
|
||||
registerModuleById(graph, m)
|
||||
if graph.config.cmd == cmdM:
|
||||
# cmdM uses NIF files - replay from module AST loaded by loadNifModule
|
||||
let module = graph.getModule(m)
|
||||
if module != nil and module.ast != nil:
|
||||
replayStateChanges(module, graph)
|
||||
if sfMainModule in flags and graph.config.cmd == cmdM:
|
||||
discard
|
||||
else:
|
||||
replayStateChanges(graph.packed.pm[m.int].module, graph)
|
||||
replayGenericCacheInformation(graph, m.int)
|
||||
elif graph.isDirty(result):
|
||||
result.excl sfDirty
|
||||
result.flags.excl sfDirty
|
||||
# reset module fields:
|
||||
initStrTables(graph, result)
|
||||
result.ast = nil
|
||||
@@ -354,12 +294,10 @@ proc connectPipelineCallbacks*(graph: ModuleGraph) =
|
||||
|
||||
proc compilePipelineSystemModule*(graph: ModuleGraph) =
|
||||
if graph.systemModule == nil:
|
||||
graph.withinSystem = true
|
||||
connectPipelineCallbacks(graph)
|
||||
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
|
||||
graph.config.libpath / RelativeFile"system.nim")
|
||||
discard graph.compilePipelineModule(graph.config.m.systemFileIdx, {sfSystemModule})
|
||||
graph.withinSystem = false
|
||||
|
||||
proc compilePipelineProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
|
||||
connectPipelineCallbacks(graph)
|
||||
@@ -376,24 +314,7 @@ proc compilePipelineProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx
|
||||
graph.importStack.add projectFile
|
||||
|
||||
if projectFile == systemFileIdx:
|
||||
graph.withinSystem = true
|
||||
discard graph.compilePipelineModule(projectFile, {sfMainModule, sfSystemModule})
|
||||
graph.withinSystem = false
|
||||
elif graph.config.cmd == cmdM:
|
||||
# For cmdM: load system.nim from NIF first, then compile the main module
|
||||
connectPipelineCallbacks(graph)
|
||||
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
|
||||
graph.config.libpath / RelativeFile"system.nim")
|
||||
var cachedModules: seq[FileIndex] = @[]
|
||||
when not defined(nimKochBootstrap):
|
||||
let precomp = moduleFromNifFile(graph, graph.config.m.systemFileIdx)
|
||||
graph.systemModule = precomp.module
|
||||
if graph.systemModule == nil:
|
||||
let nifPath = toNifFilename(graph.config, graph.config.m.systemFileIdx)
|
||||
localError(graph.config, unknownLineInfo,
|
||||
"nim m requires precompiled NIF for system module (expected: " & nifPath & ")")
|
||||
return
|
||||
discard graph.compilePipelineModule(projectFile, {sfMainModule})
|
||||
else:
|
||||
graph.compilePipelineSystemModule()
|
||||
discard graph.compilePipelineModule(projectFile, {sfMainModule})
|
||||
|
||||
@@ -210,8 +210,8 @@ type
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuHppa, cpuIa64, cpuAmd64, cpuMips,
|
||||
cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430,
|
||||
cpuSparc64, cpuS390x, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64,
|
||||
cpuEsp, cpuWasm32, cpuE2k, cpuLoongArch64
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32,
|
||||
cpuE2k, cpuLoongArch64
|
||||
|
||||
type
|
||||
TInfoCPU* = tuple[name: string, intSize: int, endian: Endianness,
|
||||
@@ -241,7 +241,6 @@ const
|
||||
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
|
||||
(name: "msp430", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
|
||||
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "s390x", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "riscv32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
|
||||
@@ -33,7 +33,7 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode =
|
||||
|
||||
let prc = newSym(skProc, n[3].ident, c.idgen, iter.sym.owner, iter.sym.info)
|
||||
prc.typ = copyType(iter.sym.typ, c.idgen, prc)
|
||||
excl prc.typ, tfCapturesEnv
|
||||
excl prc.typ.flags, tfCapturesEnv
|
||||
prc.typ.n.add newSymNode(getEnvParam(iter.sym))
|
||||
prc.typ.rawAddSon t
|
||||
let orig = iter.sym.ast
|
||||
|
||||
@@ -148,7 +148,7 @@ proc pragmaEnsures(c: PContext, n: PNode) =
|
||||
if o.kind in routineKinds and o.typ != nil and o.typ.returnType != nil:
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), c.idgen, o, n.info)
|
||||
s.typ = o.typ.returnType
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
addDecl(c, s)
|
||||
n[1] = c.semExpr(c, n[1])
|
||||
closeScope(c)
|
||||
@@ -156,12 +156,12 @@ proc pragmaEnsures(c: PContext, n: PNode) =
|
||||
proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
# special cases to improve performance:
|
||||
if extname == "$1":
|
||||
s.setSnippet(rope(s.name.s))
|
||||
s.loc.snippet = rope(s.name.s)
|
||||
elif '$' notin extname:
|
||||
s.setSnippet(rope(extname))
|
||||
s.loc.snippet = rope(extname)
|
||||
else:
|
||||
try:
|
||||
s.setSnippet(rope(extname % s.name.s))
|
||||
s.loc.snippet = rope(extname % s.name.s)
|
||||
except ValueError:
|
||||
localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)")
|
||||
when hasFFI:
|
||||
@@ -170,36 +170,36 @@ proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
|
||||
proc makeExternImport(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
setExternName(c, s, extname, info)
|
||||
s.incl(sfImportc)
|
||||
s.excl(sfForward)
|
||||
incl(s.flags, sfImportc)
|
||||
excl(s.flags, sfForward)
|
||||
|
||||
proc makeExternExport(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
setExternName(c, s, extname, info)
|
||||
s.incl(sfExportc)
|
||||
incl(s.flags, sfExportc)
|
||||
|
||||
proc processImportCompilerProc(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
setExternName(c, s, extname, info)
|
||||
s.incl(sfImportc)
|
||||
s.excl(sfForward)
|
||||
incl(s.locImpl.flags, lfImportCompilerProc)
|
||||
incl(s.flags, sfImportc)
|
||||
excl(s.flags, sfForward)
|
||||
incl(s.loc.flags, lfImportCompilerProc)
|
||||
|
||||
proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
setExternName(c, s, extname, info)
|
||||
s.incl(sfImportc)
|
||||
incl(s.flagsImpl, sfInfixCall)
|
||||
excl(s.flagsImpl, sfForward)
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfInfixCall)
|
||||
excl(s.flags, sfForward)
|
||||
if c.config.backend == backendC:
|
||||
let m = s.getModule()
|
||||
incl(m.flagsImpl, sfCompileToCpp)
|
||||
incl(m.flags, sfCompileToCpp)
|
||||
incl c.config.globalOptions, optMixedMode
|
||||
|
||||
proc processImportObjC(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
setExternName(c, s, extname, info)
|
||||
s.incl(sfImportc)
|
||||
incl(s.flagsImpl, sfNamedParamCall)
|
||||
excl(s.flagsImpl, sfForward)
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfNamedParamCall)
|
||||
excl(s.flags, sfForward)
|
||||
let m = s.getModule()
|
||||
m.incl(sfCompileToObjc)
|
||||
incl(m.flags, sfCompileToObjc)
|
||||
|
||||
proc newEmptyStrNode(c: PContext; n: PNode, strVal: string = ""): PNode {.noinline.} =
|
||||
result = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString))
|
||||
@@ -239,14 +239,14 @@ proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||
proc processVirtual(c: PContext, n: PNode, s: PSym, flag: TSymFlag) =
|
||||
s.constraint = newEmptyStrNode(c, n, getOptionalStr(c, n, "$1"))
|
||||
s.constraint.strVal = s.constraint.strVal % s.name.s
|
||||
s.flagsImpl.incl {flag, sfInfixCall, sfExportc, sfMangleCpp}
|
||||
s.flags.incl {flag, sfInfixCall, sfExportc, sfMangleCpp}
|
||||
|
||||
s.typ.callConv = ccMember
|
||||
incl c.config.globalOptions, optMixedMode
|
||||
|
||||
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
|
||||
sym.constraint = getStrLitNode(c, n)
|
||||
sym.flagsImpl.incl sfCodegenDecl
|
||||
sym.flags.incl sfCodegenDecl
|
||||
|
||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
#if sfSystemModule notin c.module.flags:
|
||||
@@ -282,10 +282,10 @@ proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
|
||||
|
||||
proc pragmaNoForward*(c: PContext, n: PNode; flag=sfNoForward) =
|
||||
if isTurnedOn(c, n):
|
||||
incl(c.module.flagsImpl, flag)
|
||||
incl(c.module.flags, flag)
|
||||
c.features.incl codeReordering
|
||||
else:
|
||||
excl(c.module.flagsImpl, flag)
|
||||
excl(c.module.flags, flag)
|
||||
# c.features.excl codeReordering
|
||||
|
||||
# deprecated as of 0.18.1
|
||||
@@ -357,9 +357,9 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||
if not lib.isOverridden:
|
||||
addToLib(lib, sym)
|
||||
sym.incl(lfDynamicLib)
|
||||
incl(sym.loc.flags, lfDynamicLib)
|
||||
else:
|
||||
sym.incl(lfExportLib)
|
||||
incl(sym.loc.flags, lfExportLib)
|
||||
# since we'll be loading the dynlib symbols dynamically, we must use
|
||||
# a calling convention that doesn't introduce custom name mangling
|
||||
# cdecl is the default - the user can override this explicitly
|
||||
@@ -435,7 +435,7 @@ proc processExperimental(c: PContext; n: PNode) =
|
||||
if not isTopLevel(c):
|
||||
localError(c.config, n.info,
|
||||
"Code reordering experimental pragma only valid at toplevel")
|
||||
c.module.flagsImpl.incl sfReorder
|
||||
c.module.flags.incl sfReorder
|
||||
except ValueError:
|
||||
localError(c.config, n[1].info, "unknown experimental feature")
|
||||
else:
|
||||
@@ -636,7 +636,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||
var e = searchInScopes(con, getIdent(con.cache, sub), amb)
|
||||
# XXX what to do here if 'amb' is true?
|
||||
if e != nil:
|
||||
incl(e.flagsImpl, sfUsed)
|
||||
incl(e.flags, sfUsed)
|
||||
if isDefined(con.config, "nimPreviewAsmSemSymbol"):
|
||||
result.add con.semExprWithType(con, newSymNode(e), {efTypeAllowed})
|
||||
else:
|
||||
@@ -725,12 +725,12 @@ proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
proc pragmaRaisesOrTags(c: PContext, n: PNode) =
|
||||
proc processExc(c: PContext, x: PNode) =
|
||||
if c.hasUnresolvedArgs(c, x):
|
||||
x.typ = makeTypeFromExpr(c, x)
|
||||
x.typ() = makeTypeFromExpr(c, x)
|
||||
else:
|
||||
var t = skipTypes(c.semTypeNode(c, x, nil), skipPtrs)
|
||||
if t.kind notin {tyObject, tyOr}:
|
||||
localError(c.config, x.info, errGenerated, "invalid type for raises/tags list")
|
||||
x.typ = t
|
||||
x.typ() = t
|
||||
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||
let it = n[1]
|
||||
@@ -757,15 +757,15 @@ proc typeBorrow(c: PContext; sym: PSym, n: PNode) =
|
||||
let it = n[1]
|
||||
if it.kind != nkAccQuoted:
|
||||
localError(c.config, n.info, "a type can only borrow `.` for now")
|
||||
incl(sym.typ, tfBorrowDot)
|
||||
incl(sym.typ.flags, tfBorrowDot)
|
||||
|
||||
proc markCompilerProc(c: PContext; s: PSym) =
|
||||
# minor hack ahead: FlowVar is the only generic .compilerproc type which
|
||||
# should not have an external name set:
|
||||
if s.kind != skType or s.name.s != "FlowVar":
|
||||
makeExternExport(c, s, "$1", s.info)
|
||||
incl(s, sfCompilerProc)
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfCompilerProc)
|
||||
incl(s.flags, sfUsed)
|
||||
registerCompilerProc(c.graph, s)
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
addCompilerProc(c.encoder, c.packedRepr, s)
|
||||
@@ -773,7 +773,7 @@ proc markCompilerProc(c: PContext; s: PSym) =
|
||||
proc deprecatedStmt(c: PContext; outerPragma: PNode) =
|
||||
let pragma = outerPragma[1]
|
||||
if pragma.kind in {nkStrLit..nkTripleStrLit}:
|
||||
incl(c.module, sfDeprecated)
|
||||
incl(c.module.flags, sfDeprecated)
|
||||
c.module.constraint = getStrLitNode(c, outerPragma)
|
||||
return
|
||||
if pragma.kind != nkBracket:
|
||||
@@ -842,7 +842,7 @@ proc processEffectsOf(c: PContext, n: PNode; owner: PSym) =
|
||||
let r = c.semExpr(c, n)
|
||||
if r.kind == nkSym and r.sym.kind == skParam:
|
||||
if r.sym.owner == owner:
|
||||
incl r.sym, sfEffectsDelayed
|
||||
incl r.sym.flags, sfEffectsDelayed
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated, "parameter cannot be declared as .effectsOf")
|
||||
else:
|
||||
@@ -907,8 +907,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if c.config.backend != backendCpp:
|
||||
localError(c.config, it.info, "exportcpp requires `cpp` backend, got: " & $c.config.backend)
|
||||
else:
|
||||
incl(sym, sfMangleCpp)
|
||||
incl(sym.flagsImpl, sfUsed) # avoid wrong hints
|
||||
incl(sym.flags, sfMangleCpp)
|
||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||
of wImportc:
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
cppDefine(c.config, name)
|
||||
@@ -921,24 +921,24 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
processImportCompilerProc(c, sym, name, it.info)
|
||||
of wExtern: setExternName(c, sym, expectStrLit(c, it), it.info)
|
||||
of wDirty:
|
||||
if sym.kind == skTemplate: incl(sym, sfDirty)
|
||||
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
||||
else: invalidPragma(c, it)
|
||||
of wRedefine:
|
||||
if sym.kind == skTemplate: incl(sym, sfTemplateRedefinition)
|
||||
if sym.kind == skTemplate: incl(sym.flags, sfTemplateRedefinition)
|
||||
else: invalidPragma(c, it)
|
||||
of wCallsite:
|
||||
if sym.kind == skTemplate: incl(sym, sfCallsite)
|
||||
if sym.kind == skTemplate: incl(sym.flags, sfCallsite)
|
||||
else: invalidPragma(c, it)
|
||||
of wImportCpp:
|
||||
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
of wCppNonPod:
|
||||
incl(sym, sfCppNonPod)
|
||||
incl(sym.flags, sfCppNonPod)
|
||||
of wImportJs:
|
||||
if c.config.backend != backendJs:
|
||||
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
incl(sym, sfImportc)
|
||||
incl(sym.flagsImpl, sfInfixCall)
|
||||
incl(sym.flags, sfImportc)
|
||||
incl(sym.flags, sfInfixCall)
|
||||
if sym.kind in skProcKinds and {'(', '#', '@'} notin name:
|
||||
localError(c.config, n.info, "`importjs` for routines requires a pattern")
|
||||
setExternName(c, sym, name, it.info)
|
||||
@@ -968,29 +968,29 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
localError(c.config, it.info, "power of two expected")
|
||||
of wNodecl:
|
||||
noVal(c, it)
|
||||
sym.incl(lfNoDecl)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
of wPure, wAsmNoStackFrame:
|
||||
noVal(c, it)
|
||||
if sym != nil:
|
||||
if k == wPure and sym.kind in routineKinds: invalidPragma(c, it)
|
||||
else: incl(sym, sfPure)
|
||||
else: incl(sym.flags, sfPure)
|
||||
of wVolatile:
|
||||
noVal(c, it)
|
||||
incl(sym, sfVolatile)
|
||||
incl(sym.flags, sfVolatile)
|
||||
of wCursor:
|
||||
noVal(c, it)
|
||||
incl(sym, sfCursor)
|
||||
incl(sym.flags, sfCursor)
|
||||
of wRegister:
|
||||
noVal(c, it)
|
||||
incl(sym, sfRegister)
|
||||
incl(sym.flags, sfRegister)
|
||||
of wNoalias:
|
||||
noVal(c, it)
|
||||
incl(sym, sfNoalias)
|
||||
incl(sym.flags, sfNoalias)
|
||||
of wEffectsOf:
|
||||
processEffectsOf(c, it, sym)
|
||||
of wThreadVar:
|
||||
noVal(c, it)
|
||||
incl(sym, {sfThread, sfGlobal})
|
||||
incl(sym.flags, {sfThread, sfGlobal})
|
||||
of wDeadCodeElimUnused:
|
||||
warningDeprecated(c.config, n.info, "'{.deadcodeelim: on.}' is deprecated, now a noop") # deprecated, dead code elim always on
|
||||
of wNoForward: pragmaNoForward(c, it)
|
||||
@@ -1000,50 +1000,51 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
noVal(c, it)
|
||||
if comesFromPush:
|
||||
if sym.kind in {skProc, skFunc}:
|
||||
incl(sym, sfCompileTime)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
else:
|
||||
incl(sym, sfCompileTime)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
#incl(sym.loc.flags, lfNoDecl)
|
||||
of wGlobal:
|
||||
noVal(c, it)
|
||||
incl(sym, {sfGlobal, sfPure})
|
||||
incl(sym.flags, sfGlobal)
|
||||
incl(sym.flags, sfPure)
|
||||
of wConstructor:
|
||||
incl(sym, sfConstructor)
|
||||
incl(sym.flags, sfConstructor)
|
||||
if sfImportc notin sym.flags:
|
||||
sym.constraint = newEmptyStrNode(c, it, getOptionalStr(c, it, ""))
|
||||
sym.constraint.strVal = sym.constraint.strVal
|
||||
sym.flagsImpl.incl {sfExportc, sfMangleCpp}
|
||||
sym.flags.incl {sfExportc, sfMangleCpp}
|
||||
sym.typ.callConv = ccNoConvention
|
||||
of wHeader:
|
||||
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
||||
addToLib(lib, sym)
|
||||
incl(sym, sfImportc)
|
||||
incl(sym.locImpl.flags, lfHeader)
|
||||
incl(sym.locImpl.flags, lfNoDecl)
|
||||
incl(sym.flags, sfImportc)
|
||||
incl(sym.loc.flags, lfHeader)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
# implies nodecl, because otherwise header would not make sense
|
||||
if sym.locImpl.snippet == "": sym.locImpl.snippet = rope(sym.name.s)
|
||||
if sym.loc.snippet == "": sym.loc.snippet = rope(sym.name.s)
|
||||
of wNoSideEffect:
|
||||
noVal(c, it)
|
||||
if sym != nil:
|
||||
incl(sym, sfNoSideEffect)
|
||||
if sym.typ != nil: incl(sym.typ, tfNoSideEffect)
|
||||
incl(sym.flags, sfNoSideEffect)
|
||||
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
|
||||
of wSideEffect:
|
||||
noVal(c, it)
|
||||
incl(sym, sfSideEffect)
|
||||
incl(sym.flags, sfSideEffect)
|
||||
of wNoreturn:
|
||||
noVal(c, it)
|
||||
# Disable the 'noreturn' annotation when in the "Quirky Exceptions" mode!
|
||||
if c.config.exc != excQuirky:
|
||||
incl(sym, sfNoReturn)
|
||||
incl(sym.flags, sfNoReturn)
|
||||
if sym.typ.returnType != nil:
|
||||
localError(c.config, sym.ast[paramsPos][0].info,
|
||||
".noreturn with return type not allowed")
|
||||
of wNoDestroy:
|
||||
noVal(c, it)
|
||||
incl(sym, sfGeneratedOp)
|
||||
incl(sym.flags, sfGeneratedOp)
|
||||
of wNosinks:
|
||||
noVal(c, it)
|
||||
incl(sym, sfWasForwarded)
|
||||
incl(sym.flags, sfWasForwarded)
|
||||
of wDynlib:
|
||||
processDynLib(c, it, sym)
|
||||
of wCompilerProc, wCore:
|
||||
@@ -1052,79 +1053,79 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
recordPragma(c, it, "cppdefine", sym.name.s)
|
||||
if sfFromGeneric notin sym.flags: markCompilerProc(c, sym)
|
||||
of wNonReloadable:
|
||||
sym.incl sfNonReloadable
|
||||
sym.flags.incl sfNonReloadable
|
||||
of wProcVar:
|
||||
# old procvar annotation, no longer needed
|
||||
noVal(c, it)
|
||||
of wExplain:
|
||||
sym.incl sfExplain
|
||||
sym.flags.incl sfExplain
|
||||
of wDeprecated:
|
||||
if sym != nil and sym.kind in routineKinds + {skType, skVar, skLet, skConst}:
|
||||
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
|
||||
incl(sym, sfDeprecated)
|
||||
incl(sym.flags, sfDeprecated)
|
||||
elif sym != nil and sym.kind != skModule:
|
||||
# We don't support the extra annotation field
|
||||
if it.kind in nkPragmaCallKinds:
|
||||
localError(c.config, it.info, "annotation to deprecated not supported here")
|
||||
incl(sym, sfDeprecated)
|
||||
incl(sym.flags, sfDeprecated)
|
||||
# At this point we're quite sure this is a statement and applies to the
|
||||
# whole module
|
||||
elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it)
|
||||
else: incl(c.module, sfDeprecated)
|
||||
else: incl(c.module.flags, sfDeprecated)
|
||||
of wVarargs:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfVarargs)
|
||||
else: incl(sym.typ.flags, tfVarargs)
|
||||
of wBorrow:
|
||||
if sym.kind == skType:
|
||||
typeBorrow(c, sym, it)
|
||||
else:
|
||||
noVal(c, it)
|
||||
incl(sym, sfBorrow)
|
||||
incl(sym.flags, sfBorrow)
|
||||
of wFinal:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfFinal)
|
||||
else: incl(sym.typ.flags, tfFinal)
|
||||
of wInheritable:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfInheritable)
|
||||
else: incl(sym.typ.flags, tfInheritable)
|
||||
of wPackage:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym, sfForward)
|
||||
else: incl(sym.flags, sfForward)
|
||||
of wAcyclic:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfAcyclic)
|
||||
else: incl(sym.typ.flags, tfAcyclic)
|
||||
of wShallow:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfShallow)
|
||||
else: incl(sym.typ.flags, tfShallow)
|
||||
of wThread:
|
||||
noVal(c, it)
|
||||
incl(sym, sfThread)
|
||||
incl(sym.flags, sfThread)
|
||||
if sym.typ != nil:
|
||||
incl(sym.typ, tfThread)
|
||||
incl(sym.typ.flags, tfThread)
|
||||
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccNimCall
|
||||
of wSendable:
|
||||
noVal(c, it)
|
||||
if sym != nil and sym.typ != nil:
|
||||
incl(sym.typ, tfSendable)
|
||||
incl(sym.typ.flags, tfSendable)
|
||||
else:
|
||||
invalidPragma(c, it)
|
||||
of wGcSafe:
|
||||
noVal(c, it)
|
||||
if sym != nil:
|
||||
if sym.kind != skType: incl(sym, sfThread)
|
||||
if sym.typ != nil: incl(sym.typ, tfGcSafe)
|
||||
if sym.kind != skType: incl(sym.flags, sfThread)
|
||||
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
|
||||
else: invalidPragma(c, it)
|
||||
else:
|
||||
discard "no checking if used as a code block"
|
||||
of wPacked:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfPacked)
|
||||
else: incl(sym.typ.flags, tfPacked)
|
||||
of wHint:
|
||||
let s = expectStrLit(c, it)
|
||||
recordPragma(c, it, "hint", s)
|
||||
@@ -1140,8 +1141,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
# distinguish properly between
|
||||
# ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
|
||||
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
|
||||
incl(sym, sfError)
|
||||
excl(sym, sfForward)
|
||||
incl(sym.flags, sfError)
|
||||
excl(sym.flags, sfForward)
|
||||
else:
|
||||
let s = expectStrLit(c, it)
|
||||
recordPragma(c, it, "error", s)
|
||||
@@ -1151,18 +1152,18 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wUndef: processUndef(c, it)
|
||||
of wCompile:
|
||||
let m = sym.getModule()
|
||||
incl(m.flagsImpl, sfUsed)
|
||||
incl(m.flags, sfUsed)
|
||||
processCompile(c, it)
|
||||
of wLink: processLink(c, it)
|
||||
of wPassl:
|
||||
let m = sym.getModule()
|
||||
incl(m.flagsImpl, sfUsed)
|
||||
incl(m.flags, sfUsed)
|
||||
let s = expectStrLit(c, it)
|
||||
extccomp.addLinkOption(c.config, s)
|
||||
recordPragma(c, it, "passl", s)
|
||||
of wPassc:
|
||||
let m = sym.getModule()
|
||||
incl(m.flagsImpl, sfUsed)
|
||||
incl(m.flags, sfUsed)
|
||||
let s = expectStrLit(c, it)
|
||||
extccomp.addCompileOption(c.config, s)
|
||||
recordPragma(c, it, "passc", s)
|
||||
@@ -1180,16 +1181,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
result = true
|
||||
of wPragma:
|
||||
if not sym.isNil and sym.kind == skTemplate:
|
||||
sym.incl sfCustomPragma
|
||||
sym.flags.incl sfCustomPragma
|
||||
else:
|
||||
processPragma(c, n, i)
|
||||
result = true
|
||||
of wDiscardable:
|
||||
noVal(c, it)
|
||||
if sym != nil: incl(sym, sfDiscardable)
|
||||
if sym != nil: incl(sym.flags, sfDiscardable)
|
||||
of wNoInit:
|
||||
noVal(c, it)
|
||||
if sym != nil: incl(sym, sfNoInit)
|
||||
if sym != nil: incl(sym.flags, sfNoInit)
|
||||
of wCodegenDecl: processCodegenDecl(c, it, sym)
|
||||
of wChecks, wObjChecks, wFieldChecks, wRangeChecks, wBoundChecks,
|
||||
wOverflowChecks, wNilChecks, wAssertions, wWarnings, wHints,
|
||||
@@ -1199,8 +1200,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
processOption(c, it, c.config.options)
|
||||
of wStackTrace, wLineTrace:
|
||||
if sym.kind in {skProc, skMethod, skConverter}:
|
||||
ensureMutable sym
|
||||
processOption(c, it, sym.optionsImpl)
|
||||
processOption(c, it, sym.options)
|
||||
else:
|
||||
processOption(c, it, c.config.options)
|
||||
of FirstCallConv..LastCallConv:
|
||||
@@ -1208,7 +1208,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else:
|
||||
sym.typ.callConv = wordToCallConv(k)
|
||||
sym.typ.incl tfExplicitCallConv
|
||||
sym.typ.flags.incl tfExplicitCallConv
|
||||
of wEmit: pragmaEmit(c, it)
|
||||
of wUnroll: pragmaUnroll(c, it)
|
||||
of wLinearScanEnd, wComputedGoto: noVal(c, it)
|
||||
@@ -1218,11 +1218,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wIncompleteStruct:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfIncompleteStruct)
|
||||
else: incl(sym.typ.flags, tfIncompleteStruct)
|
||||
of wCompleteStruct:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfCompleteStruct)
|
||||
else: incl(sym.typ.flags, tfCompleteStruct)
|
||||
of wUnchecked:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil or sym.typ.kind notin {tyArray, tyUncheckedArray}:
|
||||
@@ -1235,35 +1235,34 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
else:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfUnion)
|
||||
else: incl(sym.typ.flags, tfUnion)
|
||||
of wRequiresInit:
|
||||
noVal(c, it)
|
||||
if sym.kind == skField:
|
||||
sym.incl sfRequiresInit
|
||||
sym.flags.incl sfRequiresInit
|
||||
elif sym.typ != nil:
|
||||
incl(sym.typ, tfNeedsFullInit)
|
||||
incl(sym.typ.flags, tfNeedsFullInit)
|
||||
else:
|
||||
invalidPragma(c, it)
|
||||
of wByRef:
|
||||
noVal(c, it)
|
||||
if sym != nil and sym.kind == skParam:
|
||||
ensureMutable sym
|
||||
sym.optionsImpl.incl optByRef
|
||||
sym.options.incl optByRef
|
||||
elif sym == nil or sym.typ == nil:
|
||||
processOption(c, it, c.config.options)
|
||||
else:
|
||||
incl(sym.typ, tfByRef)
|
||||
incl(sym.typ.flags, tfByRef)
|
||||
of wByCopy:
|
||||
noVal(c, it)
|
||||
if sym.kind == skParam:
|
||||
incl(sym, sfByCopy)
|
||||
incl(sym.flags, sfByCopy)
|
||||
elif sym.kind != skType or sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ, tfByCopy)
|
||||
else: incl(sym.typ.flags, tfByCopy)
|
||||
of wPartial:
|
||||
noVal(c, it)
|
||||
if sym.kind != skType or sym.typ == nil: invalidPragma(c, it)
|
||||
else:
|
||||
incl(sym.typ, tfPartial)
|
||||
incl(sym.typ.flags, tfPartial)
|
||||
of wInject, wGensym:
|
||||
# We check for errors, but do nothing with these pragmas otherwise
|
||||
# as they are handled directly in 'evalTemplate'.
|
||||
@@ -1291,7 +1290,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if sym == nil or sym.kind notin {skVar, skLet}:
|
||||
invalidPragma(c, it)
|
||||
else:
|
||||
sym.incl sfGoto
|
||||
sym.flags.incl sfGoto
|
||||
of wExportNims:
|
||||
if sym == nil: invalidPragma(c, it)
|
||||
else: magicsys.registerNimScriptSymbol(c.graph, sym)
|
||||
@@ -1306,7 +1305,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
noVal(c, it)
|
||||
of wBase:
|
||||
noVal(c, it)
|
||||
sym.incl sfBase
|
||||
sym.flags.incl sfBase
|
||||
of wIntDefine:
|
||||
processDefineConst(c, n, sym, mIntDefine)
|
||||
of wStrDefine:
|
||||
@@ -1316,22 +1315,21 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wUsed:
|
||||
noVal(c, it)
|
||||
if sym == nil: invalidPragma(c, it)
|
||||
else: sym.incl sfUsed
|
||||
else: sym.flags.incl sfUsed
|
||||
of wLiftLocals:
|
||||
sym.incl(sfForceLift)
|
||||
sym.flags.incl(sfForceLift)
|
||||
of wRequires, wInvariant, wAssume, wAssert:
|
||||
pragmaProposition(c, it)
|
||||
of wEnsures:
|
||||
pragmaEnsures(c, it)
|
||||
of wEnforceNoRaises:
|
||||
sym.incl sfNeverRaises
|
||||
sym.flags.incl sfNeverRaises
|
||||
of wQuirky:
|
||||
sym.incl sfNeverRaises
|
||||
sym.flags.incl sfNeverRaises
|
||||
if sym.kind in {skProc, skMethod, skConverter, skFunc, skIterator}:
|
||||
ensureMutable sym
|
||||
sym.optionsImpl.incl optQuirky
|
||||
sym.options.incl optQuirky
|
||||
of wSystemRaisesDefect:
|
||||
sym.incl sfSystemRaisesDefect
|
||||
sym.flags.incl sfSystemRaisesDefect
|
||||
of wVirtual:
|
||||
processVirtual(c, it, sym, sfVirtual)
|
||||
of wMember:
|
||||
@@ -1388,9 +1386,9 @@ proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo,
|
||||
var lib = c.optionStack[^1].dynlib
|
||||
if {lfDynamicLib, lfHeader} * sym.loc.flags == {} and
|
||||
sfImportc in sym.flags and lib != nil:
|
||||
incl(sym, lfDynamicLib)
|
||||
incl(sym.loc.flags, lfDynamicLib)
|
||||
addToLib(lib, sym)
|
||||
if sym.locImpl.snippet == "": sym.locImpl.snippet = rope(sym.name.s)
|
||||
if sym.loc.snippet == "": sym.loc.snippet = rope(sym.name.s)
|
||||
|
||||
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
||||
if n == nil: return false
|
||||
|
||||
@@ -30,7 +30,7 @@ type
|
||||
TRenderFlags* = set[TRenderFlag]
|
||||
TRenderTok* = object
|
||||
kind*: TokType
|
||||
length*: int32
|
||||
length*: int16
|
||||
sym*: PSym
|
||||
|
||||
Section = enum
|
||||
@@ -154,7 +154,7 @@ proc initSrcGen(renderFlags: TRenderFlags; config: ConfigRef): TSrcGen =
|
||||
)
|
||||
|
||||
proc addTok(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
|
||||
g.tokens.add TRenderTok(kind: kind, length: int32(s.len), sym: sym)
|
||||
g.tokens.add TRenderTok(kind: kind, length: int16(s.len), sym: sym)
|
||||
g.buf.add(s)
|
||||
if kind != tkSpaces:
|
||||
inc g.col, s.len
|
||||
@@ -327,10 +327,6 @@ proc pushCom(g: var TSrcGen, n: PNode) =
|
||||
setLen(g.comStack, g.comStack.len + 1)
|
||||
g.comStack[^1] = n
|
||||
|
||||
proc popCom(g: var TSrcGen): PNode =
|
||||
result = g.comStack[^1]
|
||||
setLen(g.comStack, g.comStack.len - 1)
|
||||
|
||||
proc popAllComs(g: var TSrcGen) =
|
||||
setLen(g.comStack, 0)
|
||||
|
||||
@@ -1357,10 +1353,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
if not n[0].isExported() and renderNonExportedFields notin g.flags:
|
||||
# Skip if this is a property in a type and its not exported
|
||||
# (While also not allowing rendering of non exported fields)
|
||||
if shouldRenderComment(g, n):
|
||||
# `shouldRenderComment` indicts that we have comments to render
|
||||
# but it's a non-exported field, so we just pop without rendering any comment
|
||||
discard popCom(g)
|
||||
return
|
||||
# render postfix for object fields:
|
||||
exclFlags = g.flags * {renderNoPostfix}
|
||||
@@ -1836,9 +1828,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
putWithSpace(g, tkSymbol, "error")
|
||||
#gcomma(g, n, c)
|
||||
gsub(g, n[0], c)
|
||||
of nkReplayAction:
|
||||
put(g, tkSymbol, "replayaction")
|
||||
#gsons(g, n, c, 0)
|
||||
else:
|
||||
#nkNone, nkExplicitTypeListCall:
|
||||
internalError(g.config, n.info, "renderer.gsub(" & $n.kind & ')')
|
||||
|
||||
@@ -213,10 +213,9 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
unregisterArcOrc(conf)
|
||||
conf.globalOptions.excl optOwnedRefs
|
||||
conf.selectedGC = gcUnselected
|
||||
conf.globalOptions.incl optWithinConfigSystem
|
||||
|
||||
var m = graph.makeModule(scriptName)
|
||||
incl(m, sfMainModule)
|
||||
incl(m.flags, sfMainModule)
|
||||
var vm = setupVM(m, cache, scriptName.string, graph, idgen)
|
||||
graph.vm = vm
|
||||
|
||||
@@ -252,5 +251,4 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
#initDefines()
|
||||
undefSymbol(conf.symbols, "nimscript")
|
||||
undefSymbol(conf.symbols, "nimconfig")
|
||||
conf.globalOptions.excl optWithinConfigSystem
|
||||
conf.symbolFiles = oldSymbolFiles
|
||||
|
||||
@@ -102,7 +102,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
renderTree(arg, {renderNoComments}))
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
elif arg.kind in nkSymChoices and formal.skipTypes(abstractInst).kind == tyEnum:
|
||||
# Pick the right 'sym' from the sym choice by looking at 'formal' type:
|
||||
result = nil
|
||||
@@ -116,7 +116,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
typeMismatch(c.config, info, formal, arg.typ, arg)
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
else:
|
||||
result = fitNodePostMatch(c, formal, result)
|
||||
|
||||
@@ -126,7 +126,7 @@ proc fitNodeConsiderViewType(c: PContext, formal: PType, arg: PNode; info: TLine
|
||||
#classifyViewType(formal) != noView:
|
||||
result = newNodeIT(nkHiddenAddr, a.info, formal)
|
||||
result.add a
|
||||
formal.incl tfVarIsPtr
|
||||
formal.flags.incl tfVarIsPtr
|
||||
else:
|
||||
result = a
|
||||
|
||||
@@ -260,7 +260,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
else:
|
||||
result = newSym(kind, considerQuotedIdent(c, n), c.idgen, getCurrOwner(c), n.info)
|
||||
if find(result.name.s, '`') >= 0:
|
||||
result.flagsImpl.incl sfWasGenSym
|
||||
result.flags.incl sfWasGenSym
|
||||
#if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
|
||||
# incl(result.flags, sfGlobal)
|
||||
when defined(nimsuggest):
|
||||
@@ -321,7 +321,7 @@ proc hasCycle(n: PNode): bool =
|
||||
break
|
||||
excl n.flags, nfNone
|
||||
|
||||
proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode; producedClosure: var bool): PNode =
|
||||
proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
|
||||
# recompute the types as 'eval' isn't guaranteed to construct types nor
|
||||
# that the types are sound:
|
||||
when true:
|
||||
@@ -333,7 +333,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode; producedClosure: v
|
||||
if hasCycle(result):
|
||||
result = localErrorNode(c, eOrig, "the resulting AST is cyclic and cannot be processed further")
|
||||
else:
|
||||
semmacrosanity.annotateType(result, expectedType, c.config, producedClosure)
|
||||
semmacrosanity.annotateType(result, expectedType, c.config)
|
||||
else:
|
||||
result = semExprWithType(c, evaluated)
|
||||
#result = fitNode(c, e.typ, result) inlined with special case:
|
||||
@@ -346,19 +346,6 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode; producedClosure: v
|
||||
isArrayConstr(arg):
|
||||
arg.typ = eOrig.typ
|
||||
|
||||
proc resetEvalPosition(n: PNode) =
|
||||
# resets the eval position of variables because `tryConstExpr` may be
|
||||
# called multiple times on the same node
|
||||
case n.kind
|
||||
of {nkNone..nkNilLit}-{nkSym}:
|
||||
discard
|
||||
of nkSym:
|
||||
if n.sym.kind in {skVar, skLet} and sfGlobal notin n.sym.flags:
|
||||
n.sym.position = 0
|
||||
else:
|
||||
for i in 0..<n.safeLen:
|
||||
resetEvalPosition(n[i])
|
||||
|
||||
proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
var e = semExprWithType(c, n, expectedType = expectedType)
|
||||
if e == nil: return
|
||||
@@ -383,10 +370,7 @@ proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
if result == nil or result.kind == nkEmpty:
|
||||
result = nil
|
||||
else:
|
||||
var producedClosure = false
|
||||
result = fixupTypeAfterEval(c, result, e, producedClosure)
|
||||
if producedClosure:
|
||||
result = nil
|
||||
result = fixupTypeAfterEval(c, result, e)
|
||||
|
||||
except ERecoverableError:
|
||||
result = nil
|
||||
@@ -395,8 +379,6 @@ proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
# Restore the error hook
|
||||
c.graph.config.structuredErrorHook = tempHook
|
||||
|
||||
resetEvalPosition(n)
|
||||
|
||||
c.config.errorCounter = oldErrorCount
|
||||
c.config.errorMax = oldErrorMax
|
||||
c.config.m.errorOutputs = oldErrorOutputs
|
||||
@@ -425,10 +407,7 @@ proc semConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
# error correction:
|
||||
result = e
|
||||
else:
|
||||
var producedClosure = false
|
||||
result = fixupTypeAfterEval(c, result, e, producedClosure)
|
||||
if producedClosure:
|
||||
result = nil
|
||||
result = fixupTypeAfterEval(c, result, e)
|
||||
|
||||
proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
if efNeedStatic in flags:
|
||||
@@ -491,7 +470,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result = newSymNode(errorSym(c, result))
|
||||
else:
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
else:
|
||||
if s.ast[genericParamsPos] != nil and retType.isMetaType:
|
||||
@@ -650,7 +629,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool, ch
|
||||
newNodeIT(nkType, recNode.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recNode.typ
|
||||
asgnExpr.typ() = recNode.typ
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
raiseAssert "unreachable"
|
||||
@@ -672,7 +651,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, checkDefault:
|
||||
if checkDefault: # don't add defaults when checking whether a case branch has default fields
|
||||
return
|
||||
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
|
||||
defaultValue.typ = discriminator.typ
|
||||
defaultValue.typ() = discriminator.typ
|
||||
selectedBranch = recNode.pickCaseBranchIndex defaultValue
|
||||
defaultValue.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
|
||||
@@ -685,7 +664,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, checkDefault:
|
||||
elif recType.kind in {tyObject, tyArray, tyTuple}:
|
||||
let asgnExpr = defaultNodeField(c, recNode, recNode.typ, checkDefault)
|
||||
if asgnExpr != nil:
|
||||
asgnExpr.typ = recNode.typ
|
||||
asgnExpr.typ() = recNode.typ
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
@@ -698,7 +677,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
let child = defaultFieldsForTheUninitialized(c, aTypSkip.n, checkDefault)
|
||||
if child.len > 0:
|
||||
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp))
|
||||
asgnExpr.typ = aTyp
|
||||
asgnExpr.typ() = aTyp
|
||||
asgnExpr.sons.add child
|
||||
result = semExpr(c, asgnExpr)
|
||||
else:
|
||||
@@ -710,11 +689,11 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
let node = newNode(nkIntLit)
|
||||
node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip))
|
||||
let typeNode = newNode(nkType)
|
||||
typeNode.typ = makeTypeDesc(c, aTypSkip[1])
|
||||
typeNode.typ() = makeTypeDesc(c, aTypSkip[1])
|
||||
result = semExpr(c, newTree(nkCall, newTree(nkBracketExpr, newSymNode(getSysSym(c.graph, a.info, "arrayWithDefault"), a.info), typeNode),
|
||||
node
|
||||
))
|
||||
result.typ = aTyp
|
||||
result.typ() = aTyp
|
||||
else:
|
||||
result = nil
|
||||
of tyTuple:
|
||||
@@ -723,7 +702,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
let children = defaultFieldsForTuple(c, aTypSkip.n, hasDefault, checkDefault)
|
||||
if hasDefault and children.len > 0:
|
||||
result = newNodeI(nkTupleConstr, a.info)
|
||||
result.typ = aTyp
|
||||
result.typ() = aTyp
|
||||
result.sons.add children
|
||||
result = semExpr(c, result)
|
||||
else:
|
||||
@@ -731,10 +710,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
else:
|
||||
result = nil
|
||||
of tyRange:
|
||||
if c.graph.config.isDefined("nimPreviewRangeDefault"):
|
||||
result = firstRange(c.config, aTypSkip)
|
||||
else:
|
||||
result = nil
|
||||
result = firstRange(c.config, aTypSkip)
|
||||
else:
|
||||
result = nil
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@ proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) =
|
||||
internalError(c.config, a.info, "generic converter failed rematch")
|
||||
let finalCallee = generateInstance(c, s, convMatch.bindings, a.info)
|
||||
a[0].sym = finalCallee
|
||||
a[0].typ = finalCallee.typ
|
||||
a[0].typ() = finalCallee.typ
|
||||
#a.typ = finalCallee.typ.returnType
|
||||
|
||||
proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||
@@ -730,13 +730,13 @@ proc inferWithMetatype(c: PContext, formal: PType,
|
||||
# This almost exactly replicates the steps taken by the compiler during
|
||||
# param matching. It performs an embarrassing amount of back-and-forth
|
||||
# type jugling, but it's the price to pay for consistency and correctness
|
||||
result.typ = generateTypeInstance(c, m.bindings, arg.info,
|
||||
result.typ() = generateTypeInstance(c, m.bindings, arg.info,
|
||||
formal.skipTypes({tyCompositeTypeClass}))
|
||||
else:
|
||||
typeMismatch(c.config, arg.info, formal, arg.typ, arg)
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
|
||||
proc updateDefaultParams(c: PContext, call: PNode) =
|
||||
# In generic procs, the default parameter may be unique for each
|
||||
@@ -759,7 +759,7 @@ proc updateDefaultParams(c: PContext, call: PNode) =
|
||||
pushInfoContext(c.config, call.info, call[0].sym.detailedInfo)
|
||||
typeMismatch(c.config, def.info, formal.typ, def.typ, formal.ast)
|
||||
popInfoContext(c.config)
|
||||
def.typ = errorType(c)
|
||||
def.typ() = errorType(c)
|
||||
call[i] = def
|
||||
|
||||
proc getCallLineInfo(n: PNode): TLineInfo =
|
||||
@@ -846,8 +846,8 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
result = x.call
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
if containsGenericType(result.typ):
|
||||
result.typ = newTypeS(tyError, c)
|
||||
incl result.typ, tfCheckedForDestructor
|
||||
result.typ() = newTypeS(tyError, c)
|
||||
incl result.typ.flags, tfCheckedForDestructor
|
||||
return
|
||||
let gp = finalCallee.ast[genericParamsPos]
|
||||
if gp.isGenericParams:
|
||||
@@ -873,7 +873,7 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
# this node will be used in template substitution,
|
||||
# pretend this is an untyped node and let regular sem handle the type
|
||||
# to prevent problems where a generic parameter is treated as a value
|
||||
tn.typ = nil
|
||||
tn.typ() = nil
|
||||
x.call.add tn
|
||||
else:
|
||||
internalAssert c.config, false
|
||||
@@ -885,7 +885,7 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
markConvertersUsed(c, result)
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
if finalCallee.magic notin {mArrGet, mArrPut}:
|
||||
result.typ = finalCallee.typ.returnType
|
||||
result.typ() = finalCallee.typ.returnType
|
||||
updateDefaultParams(c, result)
|
||||
|
||||
proc canDeref(n: PNode): bool {.inline.} =
|
||||
@@ -894,7 +894,7 @@ proc canDeref(n: PNode): bool {.inline.} =
|
||||
|
||||
proc tryDeref(n: PNode): PNode =
|
||||
result = newNodeI(nkHiddenDeref, n.info)
|
||||
result.typ = n.typ.skipTypes(abstractInst)[0]
|
||||
result.typ() = n.typ.skipTypes(abstractInst)[0]
|
||||
result.add n
|
||||
|
||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
@@ -913,7 +913,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
else:
|
||||
if c.inGenericContext > 0 and c.matchedConcept == nil:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
elif efNoUndeclared in flags:
|
||||
result = nil
|
||||
elif efExplain notin flags:
|
||||
@@ -945,7 +945,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym, errors: var CandidateErr
|
||||
diagnostics: m.diagnostics))
|
||||
return nil
|
||||
var newInst = generateInstance(c, s, m.bindings, n.info)
|
||||
newInst.typ.excl tfUnresolved
|
||||
newInst.typ.flags.excl tfUnresolved
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c, info, s, isGenericInstance = false)
|
||||
onUse(info, s, isGenericInstance = false)
|
||||
@@ -964,9 +964,9 @@ proc setGenericParams(c: PContext, n, expectedParams: PNode) =
|
||||
nil
|
||||
e = semExprWithType(c, n[i], expectedType = constraint)
|
||||
if e.typ == nil:
|
||||
n[i].typ = errorType(c)
|
||||
n[i].typ() = errorType(c)
|
||||
else:
|
||||
n[i].typ = e.typ.skipTypes({tyTypeDesc})
|
||||
n[i].typ() = e.typ.skipTypes({tyTypeDesc})
|
||||
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
|
||||
assert n.kind == nkBracketExpr
|
||||
@@ -983,7 +983,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool)
|
||||
# same as in semOverloadedCall, make expression untyped,
|
||||
# may have failed match due to unresolved types
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
elif doError:
|
||||
notFoundError(c, n, errors)
|
||||
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
||||
@@ -1001,7 +1001,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool)
|
||||
# any failing match stops building the symchoice for correctness,
|
||||
# can also make it untyped from the start
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
# get rid of nkClosedSymChoice if not ambiguous:
|
||||
if result.len == 0:
|
||||
|
||||
@@ -153,6 +153,7 @@ type
|
||||
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
|
||||
topStmts*: int # counts the number of encountered top level statements
|
||||
lastGenericIdx*: int # used for the generics stack
|
||||
hloLoopDetector*: int # used to prevent endless loops in the HLO
|
||||
inParallelStmt*: int
|
||||
instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
|
||||
op: TTypeAttachedOp; col: int): PSym {.nimcall.}
|
||||
@@ -201,29 +202,29 @@ proc getIntLitType*(c: PContext; literal: PNode): PType =
|
||||
proc setIntLitType*(c: PContext; result: PNode) =
|
||||
let i = result.intVal
|
||||
case c.config.target.intSize
|
||||
of 8: result.typ = getIntLitType(c, result)
|
||||
of 8: result.typ() = getIntLitType(c, result)
|
||||
of 4:
|
||||
if i >= low(int32) and i <= high(int32):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
of 2:
|
||||
if i >= low(int16) and i <= high(int16):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
elif i >= low(int32) and i <= high(int32):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt32)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt32)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
of 1:
|
||||
# 8 bit CPUs are insane ...
|
||||
if i >= low(int8) and i <= high(int8):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
elif i >= low(int16) and i <= high(int16):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt16)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt16)
|
||||
elif i >= low(int32) and i <= high(int32):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt32)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt32)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
else:
|
||||
internalError(c.config, result.info, "invalid int size")
|
||||
|
||||
@@ -358,9 +359,6 @@ proc addImportFileDep*(c: PContext; f: FileIndex) =
|
||||
proc addPragmaComputation*(c: PContext; n: PNode) =
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
addPragmaComputation(c.encoder, c.packedRepr, n)
|
||||
# Also store for NIF-based IC (cmdM mode or optCompress)
|
||||
if optCompress in c.config.globalOptions or c.config.cmd == cmdM:
|
||||
addNifReplayAction(c.graph, c.module.position.int32, n)
|
||||
|
||||
proc inclSym(sq: var seq[PSym], s: PSym): bool =
|
||||
for i in 0..<sq.len:
|
||||
@@ -436,7 +434,7 @@ proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType =
|
||||
|
||||
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||
let typedesc = newTypeS(tyTypeDesc, c)
|
||||
incl typedesc.flagsImpl, tfCheckedForDestructor
|
||||
incl typedesc.flags, tfCheckedForDestructor
|
||||
internalAssert(c.config, typ != nil)
|
||||
typedesc.addSonSkipIntLit(typ, c.idgen)
|
||||
let sym = newSym(skType, c.cache.idAnon, c.idgen, getCurrOwner(c), info,
|
||||
@@ -460,7 +458,7 @@ when false:
|
||||
proc makeStaticExpr*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStaticExpr, n.info)
|
||||
result.sons = @[n]
|
||||
result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
|
||||
result.typ() = if n.typ != nil and n.typ.kind == tyStatic: n.typ
|
||||
else: newTypeS(tyStatic, c, n.typ)
|
||||
|
||||
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||
@@ -469,8 +467,8 @@ proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||
result.rawAddSon t2
|
||||
propagateToOwner(result, t1)
|
||||
propagateToOwner(result, t2)
|
||||
result.flagsImpl.incl((t1.flags + t2.flags) * {tfHasStatic})
|
||||
result.flagsImpl.incl tfHasMeta
|
||||
result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
|
||||
result.flags.incl tfHasMeta
|
||||
|
||||
proc makeOrType*(c: PContext, t1, t2: PType): PType =
|
||||
if t1.kind != tyOr and t2.kind != tyOr:
|
||||
@@ -488,14 +486,14 @@ proc makeOrType*(c: PContext, t1, t2: PType): PType =
|
||||
addOr(t2)
|
||||
propagateToOwner(result, t1)
|
||||
propagateToOwner(result, t2)
|
||||
result.incl((t1.flags + t2.flags) * {tfHasStatic})
|
||||
result.incl tfHasMeta
|
||||
result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
|
||||
result.flags.incl tfHasMeta
|
||||
|
||||
proc makeNotType*(c: PContext, t1: PType): PType =
|
||||
result = newTypeS(tyNot, c, son = t1)
|
||||
propagateToOwner(result, t1)
|
||||
result.flagsImpl.incl(t1.flags * {tfHasStatic})
|
||||
result.flagsImpl.incl tfHasMeta
|
||||
result.flags.incl(t1.flags * {tfHasStatic})
|
||||
result.flags.incl tfHasMeta
|
||||
|
||||
proc nMinusOne(c: PContext; n: PNode): PNode =
|
||||
result = newTreeI(nkCall, n.info, newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n)
|
||||
@@ -505,7 +503,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
|
||||
let intType = getSysType(c.graph, n.info, tyInt)
|
||||
result = newTypeS(tyRange, c, son = intType)
|
||||
if n.typ != nil and n.typ.n == nil:
|
||||
result.incl tfUnresolved
|
||||
result.flags.incl tfUnresolved
|
||||
result.n = newTreeI(nkRange, n.info, newIntTypeNode(0, intType),
|
||||
makeStaticExpr(c, nMinusOne(c, n)))
|
||||
|
||||
@@ -515,11 +513,11 @@ template rangeHasUnresolvedStatic*(t: PType): bool =
|
||||
proc errorType*(c: PContext): PType =
|
||||
## creates a type representing an error state
|
||||
result = newTypeS(tyError, c)
|
||||
result.flagsImpl.incl tfCheckedForDestructor
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc errorNode*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
# These mimic localError
|
||||
template localErrorNode*(c: PContext, n: PNode, info: TLineInfo, msg: TMsgKind, arg: string): PNode =
|
||||
@@ -565,21 +563,21 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
|
||||
result = typ
|
||||
else:
|
||||
result = newTypeS(tyTypeDesc, c, skipIntLit(typ, c.idgen))
|
||||
incl result, tfCheckedForDestructor
|
||||
incl result.flags, tfCheckedForDestructor
|
||||
|
||||
proc symFromType*(c: PContext; t: PType, info: TLineInfo): PSym =
|
||||
if t.sym != nil: return t.sym
|
||||
result = newSym(skType, getIdent(c.cache, "AnonType"), c.idgen, t.owner, info)
|
||||
result.flagsImpl.incl sfAnon
|
||||
result.flags.incl sfAnon
|
||||
result.typ = t
|
||||
|
||||
proc symNodeFromType*(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||
result = newSymNode(symFromType(c, t, info), info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ() = makeTypeDesc(c, t)
|
||||
|
||||
proc markIndirect*(c: PContext, s: PSym) {.inline.} =
|
||||
if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
|
||||
incl(s.flagsImpl, sfAddrTaken)
|
||||
incl(s.flags, sfAddrTaken)
|
||||
# XXX add to 'c' for global analysis
|
||||
|
||||
proc illFormedAst*(n: PNode; conf: ConfigRef) =
|
||||
@@ -687,7 +685,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
|
||||
# n.sym.typ can be nil in 'check' mode ...
|
||||
if n.sym.typ != nil and
|
||||
skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
|
||||
incl(n.sym.flagsImpl, sfAddrTaken)
|
||||
incl(n.sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
of nkDotExpr:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
@@ -695,12 +693,12 @@ proc analyseIfAddressTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
|
||||
internalError(c.config, n.info, "analyseIfAddressTaken")
|
||||
return
|
||||
if skipTypes(n[1].sym.typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
|
||||
incl(n[1].sym.flagsImpl, sfAddrTaken)
|
||||
incl(n[1].sym.flags, sfAddrTaken)
|
||||
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.flagsImpl, sfAddrTaken)
|
||||
if n[0].kind == nkSym: incl(n[0].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
else:
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
@@ -789,7 +787,7 @@ proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode =
|
||||
result[0] = newSymNode(op)
|
||||
if op.typ.len == 3:
|
||||
let boolLit = newIntLit(c.graph, n.info, 1)
|
||||
boolLit.typ = getSysType(c.graph, n.info, tyBool)
|
||||
boolLit.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
result.add boolLit
|
||||
of attachedWasMoved:
|
||||
result = n
|
||||
|
||||
@@ -55,11 +55,11 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if result.typ != nil:
|
||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||
elif {efWantStmt, efAllowStmt} * flags != {}:
|
||||
result.typ = newTypeS(tyVoid, c)
|
||||
result.typ() = newTypeS(tyVoid, c)
|
||||
else:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType = nil): PNode =
|
||||
rejectEmptyNode(n)
|
||||
@@ -81,14 +81,14 @@ proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
result = semExprCheck(c, n, flags-{efTypeAllowed}, expectedType)
|
||||
if result.typ == nil and efInTypeof in flags:
|
||||
result.typ = c.voidType
|
||||
result.typ() = c.voidType
|
||||
elif result.typ == nil or result.typ == c.enforceVoidContext:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
elif result.typ.kind == tyError:
|
||||
# associates the type error to the current owner
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
elif efTypeAllowed in flags and result.typ.kind == tyProc and
|
||||
hasUnresolvedParams(result, {}):
|
||||
# mirrored with semOperand but only on efTypeAllowed
|
||||
@@ -100,7 +100,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType
|
||||
else:
|
||||
errProcHasNoConcreteType % n.renderTree
|
||||
localError(c.config, n.info, err)
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
else:
|
||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||
|
||||
@@ -109,7 +109,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if result.typ == nil:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
@@ -195,7 +195,7 @@ proc semOpenSym(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType,
|
||||
result = nil
|
||||
if not isSym:
|
||||
# set symchoice node type back to None
|
||||
n.typ = newTypeS(tyNone, c)
|
||||
n.typ() = newTypeS(tyNone, c)
|
||||
|
||||
proc semSymChoice(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
if n.kind == nkOpenSymChoice:
|
||||
@@ -217,7 +217,7 @@ proc semSymChoice(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: P
|
||||
err.add " " & candidate.owner.name.s & "." & candidate.name.s
|
||||
err.add ": " & typeToString(candidate.typ) & "\n"
|
||||
localError(c.config, n.info, err)
|
||||
n.typ = errorType(c)
|
||||
n.typ() = errorType(c)
|
||||
result = n
|
||||
if result.kind == nkSym:
|
||||
result = semSym(c, result, result.sym, flags)
|
||||
@@ -228,7 +228,7 @@ proc inlineConst(c: PContext, n: PNode, s: PSym): PNode {.inline.} =
|
||||
localError(c.config, n.info, "constant of type '" & typeToString(s.typ) & "' has no value")
|
||||
result = newSymNode(s)
|
||||
else:
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
result.info = n.info
|
||||
|
||||
type
|
||||
@@ -396,7 +396,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
var evaluated = semStaticExpr(c, n[1], expectedType)
|
||||
if evaluated.kind == nkType or evaluated.typ.kind == tyTypeDesc:
|
||||
result = n
|
||||
result.typ = c.makeTypeDesc semStaticType(c, evaluated, nil)
|
||||
result.typ() = c.makeTypeDesc semStaticType(c, evaluated, nil)
|
||||
return
|
||||
elif targetType.base.kind == tyNone:
|
||||
return evaluated
|
||||
@@ -412,9 +412,9 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
let baseType = semTypeNode(c, n[1], nil).skipTypes({tyTypeDesc})
|
||||
let t = newTypeS(targetType.kind, c, baseType)
|
||||
if targetType.kind == tyOwned:
|
||||
t.incl tfHasOwned
|
||||
t.flags.incl tfHasOwned
|
||||
result = newNodeI(nkType, n.info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ() = makeTypeDesc(c, t)
|
||||
return
|
||||
|
||||
result.add copyTree(n[0])
|
||||
@@ -430,10 +430,10 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
if targetType.kind != tyGenericParam and targetType.isMetaType:
|
||||
let final = inferWithMetatype(c, targetType, op, true)
|
||||
result.add final
|
||||
result.typ = final.typ
|
||||
result.typ() = final.typ
|
||||
return
|
||||
|
||||
result.typ = targetType
|
||||
result.typ() = targetType
|
||||
# XXX op is overwritten later on, this is likely added too early
|
||||
# here or needs to be overwritten too then.
|
||||
result.add op
|
||||
@@ -441,7 +441,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
if targetType.kind == tyGenericParam or
|
||||
(op.typ != nil and op.typ.kind == tyFromExpr and c.inGenericContext > 0):
|
||||
# expression is compiled early in a generic body
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
return result
|
||||
|
||||
if not isSymChoice(op):
|
||||
@@ -491,7 +491,7 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
if not isCastable(c, targetType, castedExpr.typ, n.info):
|
||||
localError(c.config, n.info, "expression cannot be cast to '$1'" % $targetType)
|
||||
result = newNodeI(nkCast, n.info)
|
||||
result.typ = targetType
|
||||
result.typ() = targetType
|
||||
result.add copyTree(n[0])
|
||||
result.add castedExpr
|
||||
|
||||
@@ -505,18 +505,18 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
var typ = skipTypes(n[1].typ, abstractVarRange + {tyTypeDesc, tyUserTypeClassInst})
|
||||
case typ.kind
|
||||
of tySequence, tyString, tyCstring, tyOpenArray, tyVarargs:
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
of tyArray:
|
||||
n.typ = typ.indexType
|
||||
n.typ() = typ.indexType
|
||||
if n.typ.kind == tyRange and emptyRange(n.typ.n[0], n.typ.n[1]): #Invalid range
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt..tyUInt64, tyFloat..tyFloat64:
|
||||
n.typ = n[1].typ.skipTypes({tyTypeDesc})
|
||||
n.typ() = n[1].typ.skipTypes({tyTypeDesc})
|
||||
of tyGenericParam:
|
||||
# prepare this for resolving in semtypinst:
|
||||
# we must use copyTree here in order to avoid creating a cycle
|
||||
# that could easily turn into an infinite recursion in semtypinst
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
else:
|
||||
localError(c.config, n.info, "invalid argument for: " & opToStr[m])
|
||||
result = n
|
||||
@@ -532,7 +532,7 @@ proc fixupStaticType(c: PContext, n: PNode) =
|
||||
# apply this measure only in code that is enlightened to work
|
||||
# with static types.
|
||||
if n.typ.kind != tyStatic:
|
||||
n.typ = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ() = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ.n = n # XXX: cycles like the one here look dangerous.
|
||||
# Consider using `n.copyTree`
|
||||
|
||||
@@ -582,7 +582,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# `res = sameType(t1, t2)` would be wrong, e.g. for `int is (int|float)`
|
||||
|
||||
result = newIntNode(nkIntLit, ord(res))
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if n.len != 3 or n[2].kind == nkEmpty:
|
||||
@@ -591,7 +591,7 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
let boolType = getSysType(c.graph, n.info, tyBool)
|
||||
result = n
|
||||
n.typ = boolType
|
||||
n.typ() = boolType
|
||||
var liftLhs = true
|
||||
|
||||
n[1] = semExprWithType(c, n[1], {efDetermineType, efWantIterator})
|
||||
@@ -605,7 +605,7 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
n[1] = evaluated
|
||||
else:
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.typ = boolType
|
||||
result.typ() = boolType
|
||||
return
|
||||
elif t2.kind == tyTypeDesc and
|
||||
(t2.base.kind == tyNone or tfExplicit in t2.flags):
|
||||
@@ -635,7 +635,7 @@ proc semOpAux(c: PContext, n: PNode) =
|
||||
let info = a[0].info
|
||||
a[0] = newIdentNode(considerQuotedIdent(c, a[0], a), info)
|
||||
a[1] = semExprWithType(c, a[1], flags)
|
||||
a.typ = a[1].typ
|
||||
a.typ() = a[1].typ
|
||||
else:
|
||||
n[i] = semExprWithType(c, a, flags)
|
||||
|
||||
@@ -708,7 +708,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
localError(c.config, n.info, "cannot convert '" & n.sym.name.s &
|
||||
"' to '" & typeNameAndDesc(newType) & "'")
|
||||
else: discard
|
||||
n.typ = newType
|
||||
n.typ() = newType
|
||||
|
||||
proc arrayConstrType(c: PContext, n: PNode): PType =
|
||||
var typ = newTypeS(tyArray, c)
|
||||
@@ -730,12 +730,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
var expectedElementType, expectedIndexType: PType = nil
|
||||
var expectedBase: PType = nil
|
||||
if constructType:
|
||||
result.typ = newTypeS(tyArray, c)
|
||||
result.typ() = newTypeS(tyArray, c)
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
if expectedType != nil:
|
||||
expectedBase = expectedType.skipTypes(abstractRange-{tyDistinct})
|
||||
else:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
expectedBase = n.typ.skipTypes(abstractRange) # include tyDistinct this time
|
||||
if expectedBase != nil:
|
||||
case expectedBase.kind
|
||||
@@ -815,9 +815,9 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
for i in 0..<result.len:
|
||||
if isIntLit(result[i].typ):
|
||||
# generic instantiation strips int lit type which makes conversions fail
|
||||
result[i].typ = nil
|
||||
result.typ = nil # current result.typ is invalid, index type is nil
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result[i].typ() = nil
|
||||
result.typ() = nil # current result.typ is invalid, index type is nil
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
if constructType:
|
||||
addSonSkipIntLit(result.typ, typ, c.idgen)
|
||||
@@ -918,8 +918,8 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
if n[i].typ.isNil or n[i].typ.kind != tyStatic or
|
||||
tfUnresolved notin n[i].typ.flags:
|
||||
break maybeLabelAsStatic
|
||||
n.typ = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ.incl tfUnresolved
|
||||
n.typ() = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ.flags.incl tfUnresolved
|
||||
|
||||
# optimization pass: not necessary for correctness of the semantic pass
|
||||
if (callee.kind == skConst or
|
||||
@@ -951,15 +951,11 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
result = evalStaticExpr(c.module, c.idgen, c.graph, call, c.p.owner)
|
||||
if result.isNil:
|
||||
localError(c.config, n.info, errCannotInterpretNodeX % renderTree(call))
|
||||
else:
|
||||
var producedClosure = false
|
||||
result = fixupTypeAfterEval(c, result, n, producedClosure)
|
||||
else: result = fixupTypeAfterEval(c, result, n)
|
||||
else:
|
||||
result = evalConstExpr(c.module, c.idgen, c.graph, call)
|
||||
if result.isNil: result = n
|
||||
else:
|
||||
var producedClosure = false
|
||||
result = fixupTypeAfterEval(c, result, n, producedClosure)
|
||||
else: result = fixupTypeAfterEval(c, result, n)
|
||||
else:
|
||||
result = n
|
||||
#if result != n:
|
||||
@@ -977,8 +973,7 @@ proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
localError(c.config, n.info, errCannotInterpretNodeX % renderTree(n))
|
||||
result = c.graph.emptyNode
|
||||
else:
|
||||
var producedClosure = false
|
||||
result = fixupTypeAfterEval(c, result, a, producedClosure)
|
||||
result = fixupTypeAfterEval(c, result, a)
|
||||
|
||||
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -1012,7 +1007,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
if efWantIterable in flags:
|
||||
let typ = newTypeS(tyIterable, c)
|
||||
rawAddSon(typ, result.typ)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||
t: PType): TCandidate =
|
||||
@@ -1099,7 +1094,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
elif n0.typ.kind == tyFromExpr and c.inGenericContext > 0:
|
||||
# don't make assumptions, entire expression needs to be tyFromExpr
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
else:
|
||||
n[0] = n0
|
||||
@@ -1361,7 +1356,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
of tyStatic:
|
||||
if typ.n != nil:
|
||||
result = typ.n
|
||||
result.typ = typ.base
|
||||
result.typ() = typ.base
|
||||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
@@ -1407,11 +1402,11 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
onUse(n.info, s)
|
||||
if s.typ.kind == tyStatic:
|
||||
result = newSymNode(s, n.info)
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
elif s.ast != nil:
|
||||
result = semExpr(c, s.ast)
|
||||
else:
|
||||
n.typ = s.typ
|
||||
n.typ() = s.typ
|
||||
return n
|
||||
of skType:
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
@@ -1422,7 +1417,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
|
||||
return s.typ.n
|
||||
result = newSymNode(s, n.info)
|
||||
result.typ = makeTypeDesc(c, s.typ)
|
||||
result.typ() = makeTypeDesc(c, s.typ)
|
||||
of skField:
|
||||
# old code, not sure if it's live code:
|
||||
markUsed(c, n.info, s)
|
||||
@@ -1448,7 +1443,7 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
if result == c.graph.emptyNode:
|
||||
if c.inGenericContext > 0:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
else:
|
||||
result = nil
|
||||
of tyUserTypeClasses:
|
||||
@@ -1456,7 +1451,7 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
result = readTypeParameter(c, t, i, n.info)
|
||||
elif c.inGenericContext > 0:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
of tyGenericBody, tyCompositeTypeClass:
|
||||
@@ -1465,12 +1460,12 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
if result != nil:
|
||||
# generic parameter exists, stop here but delay until instantiation
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
elif c.inGenericContext > 0 and t.containsUnresolvedType:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
|
||||
@@ -1488,14 +1483,14 @@ proc tryReadingTypeField(c: PContext, n: PNode, i: PIdent, ty: PType): PNode =
|
||||
if f != nil:
|
||||
result = newSymNode(f)
|
||||
result.info = n.info
|
||||
result.typ = ty
|
||||
result.typ() = ty
|
||||
markUsed(c, n.info, f)
|
||||
onUse(n.info, f)
|
||||
of tyObject, tyTuple:
|
||||
if ty.n != nil and ty.n.kind == nkRecList:
|
||||
let field = lookupInRecord(ty.n, i)
|
||||
if field != nil:
|
||||
n.typ = makeTypeDesc(c, field.typ)
|
||||
n.typ() = makeTypeDesc(c, field.typ)
|
||||
result = n
|
||||
of tyGenericInst:
|
||||
result = tryReadingTypeField(c, n, i, ty.skipModifier)
|
||||
@@ -1542,7 +1537,7 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
# tyFromExpr, but when this happen in a macro this is not a built-in
|
||||
# field access and we leave the compiler to compile a normal call:
|
||||
if getCurrOwner(c).kind != skMacro:
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
flags.incl efCannotBeDotCall
|
||||
return n
|
||||
else:
|
||||
@@ -1582,12 +1577,12 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
n[0] = makeDeref(n[0])
|
||||
n[1] = newSymNode(f) # we now have the correct field
|
||||
n[1].info = info # preserve the original info
|
||||
n.typ = f.typ
|
||||
n.typ() = f.typ
|
||||
if check == nil:
|
||||
result = n
|
||||
else:
|
||||
check[0] = n
|
||||
check.typ = n.typ
|
||||
check.typ() = n.typ
|
||||
result = check
|
||||
elif ty.kind == tyTuple and ty.n != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
@@ -1596,7 +1591,7 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
onUse(n[1].info, f)
|
||||
n[0] = makeDeref(n[0])
|
||||
n[1] = newSymNode(f)
|
||||
n.typ = f.typ
|
||||
n.typ() = f.typ
|
||||
result = n
|
||||
|
||||
# we didn't find any field, let's look for a generic param
|
||||
@@ -1662,9 +1657,9 @@ proc semDeref(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
var t = skipTypes(n[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink, tyOwned})
|
||||
case t.kind
|
||||
of tyRef, tyPtr: n.typ = t.elementType
|
||||
of tyRef, tyPtr: n.typ() = t.elementType
|
||||
of tyMetaTypes, tyFromExpr:
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
else: result = nil
|
||||
#GlobalError(n[0].info, errCircumNeedsPointer)
|
||||
|
||||
@@ -1697,7 +1692,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = f
|
||||
if arr.kind == tyStatic:
|
||||
if arr.base.kind == tyNone:
|
||||
result = n
|
||||
result.typ = semStaticType(c, n[1], nil)
|
||||
result.typ() = semStaticType(c, n[1], nil)
|
||||
return
|
||||
elif arr.n != nil:
|
||||
return semSubscript(c, arr.n, flags, afterOverloading)
|
||||
@@ -1719,18 +1714,18 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = f
|
||||
if arg != nil:
|
||||
n[1] = arg
|
||||
result = n
|
||||
result.typ = elemType(arr)
|
||||
result.typ() = elemType(arr)
|
||||
# Other types have a bit more of leeway
|
||||
elif n[1].typ.skipTypes(abstractRange-{tyDistinct}).kind in
|
||||
{tyInt..tyInt64, tyUInt..tyUInt64}:
|
||||
result = n
|
||||
result.typ = elemType(arr)
|
||||
result.typ() = elemType(arr)
|
||||
of tyTypeDesc:
|
||||
# The result so far is a tyTypeDesc bound
|
||||
# a tyGenericBody. The line below will substitute
|
||||
# it with the instantiated type.
|
||||
result = n
|
||||
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||
result.typ() = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||
#result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
of tyTuple:
|
||||
if n.len != 2: return nil
|
||||
@@ -1740,7 +1735,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = f
|
||||
if skipTypes(n[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
|
||||
{tyInt..tyInt64}:
|
||||
let idx = getOrdValue(n[1])
|
||||
if idx >= 0 and idx < arr.len: n.typ = arr[toInt(idx)]
|
||||
if idx >= 0 and idx < arr.len: n.typ() = arr[toInt(idx)]
|
||||
else:
|
||||
localError(c.config, n.info,
|
||||
"invalid index $1 in subscript for tuple of length $2" %
|
||||
@@ -1837,7 +1832,7 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = newNodeIT(nkHiddenAddr, n.info, if n.typ.kind in {tyVar, tyLent}: n.typ else: makePtrType(c, n.typ))
|
||||
if n.typ.kind in {tyVar, tyLent}:
|
||||
n.typ = n.typ.elementType
|
||||
n.typ() = n.typ.elementType
|
||||
result.add(n)
|
||||
|
||||
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||
@@ -1847,10 +1842,10 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||
if x.sym.kind == skResult and (x.typ.kind in {tyVar, tyLent} or classifyViewType(x.typ) != noView):
|
||||
n[0] = x # 'result[]' --> 'result'
|
||||
n[1] = takeImplicitAddr(c, ri, x.typ.kind == tyLent)
|
||||
x.typ.incl tfVarIsPtr
|
||||
x.typ.flags.incl tfVarIsPtr
|
||||
#echo x.info, " setting it for this type ", typeToString(x.typ), " ", n.info
|
||||
elif sfGlobal in x.sym.flags:
|
||||
x.typ.incl tfVarIsPtr
|
||||
x.typ.flags.incl tfVarIsPtr
|
||||
|
||||
proc borrowCheck(c: PContext, n, le, ri: PNode) =
|
||||
const
|
||||
@@ -1920,7 +1915,7 @@ proc makeTupleAssignments(c: PContext; n: PNode): PNode =
|
||||
|
||||
let temp = newSym(skTemp, getIdent(c.cache, "tmpTupleAsgn"), c.idgen, getCurrOwner(c), n.info)
|
||||
temp.typ = value.typ
|
||||
temp.flagsImpl.incl(sfGenSym)
|
||||
temp.flags.incl(sfGenSym)
|
||||
var v = newNodeI(nkLetSection, value.info)
|
||||
let tempNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
|
||||
var vpart = newNodeI(nkIdentDefs, v.info, 3)
|
||||
@@ -1937,7 +1932,7 @@ proc makeTupleAssignments(c: PContext; n: PNode): PNode =
|
||||
# generate `let _ = temp[i]` which should generate a destructor
|
||||
let utemp = newSym(skLet, lhs[i].ident, c.idgen, getCurrOwner(c), lhs[i].info)
|
||||
utemp.typ = value.typ[i]
|
||||
temp.flagsImpl.incl(sfGenSym)
|
||||
temp.flags.incl(sfGenSym)
|
||||
var uv = newNodeI(nkLetSection, lhs[i].info)
|
||||
let utempNode = newSymNode(utemp)
|
||||
var uvpart = newNodeI(nkIdentDefs, v.info, 3)
|
||||
@@ -2031,7 +2026,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
let lhs = n[0]
|
||||
let rhs = semExprWithType(c, n[1], {efTypeAllowed}, le)
|
||||
if lhs.kind == nkSym and lhs.sym.kind == skResult:
|
||||
n.typ = c.enforceVoidContext
|
||||
n.typ() = c.enforceVoidContext
|
||||
if c.p.owner.kind != skMacro and resultTypeIsInferrable(lhs.sym.typ):
|
||||
var rhsTyp = rhs.typ
|
||||
if rhsTyp.kind in tyUserTypeClasses and rhsTyp.isResolvedUserTypeClass:
|
||||
@@ -2042,7 +2037,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
internalAssert c.config, c.p.resultSym != nil
|
||||
# Make sure the type is valid for the result variable
|
||||
typeAllowedCheck(c, n.info, rhsTyp, skResult)
|
||||
lhs.typ = rhsTyp
|
||||
lhs.typ() = rhsTyp
|
||||
c.p.resultSym.typ = rhsTyp
|
||||
c.p.owner.typ.setReturnType rhsTyp
|
||||
else:
|
||||
@@ -2090,7 +2085,7 @@ proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
if result.kind == nkNilLit:
|
||||
# or ImplicitlyDiscardable(result):
|
||||
# new semantic: 'result = x' triggers the void context
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
elif result.kind == nkStmtListExpr and result.typ.kind == tyNil:
|
||||
# to keep backwards compatibility bodies like:
|
||||
# nil
|
||||
@@ -2124,7 +2119,7 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||
var t = skipTypes(restype, {tyGenericInst, tyAlias, tySink})
|
||||
case t.kind
|
||||
of tyVar, tyLent:
|
||||
t.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
if n[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
n[0] = n[0][1]
|
||||
n[0] = takeImplicitAddr(c, n[0], t.kind == tyLent)
|
||||
@@ -2132,7 +2127,7 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||
for i in 0..<t.len:
|
||||
let e = skipTypes(t[i], {tyGenericInst, tyAlias, tySink})
|
||||
if e.kind in {tyVar, tyLent}:
|
||||
e.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
let tupleConstr = if n[0].kind in {nkHiddenStdConv, nkHiddenSubConv}: n[0][1] else: n[0]
|
||||
if tupleConstr.kind in {nkPar, nkTupleConstr}:
|
||||
if tupleConstr[i].kind == nkExprColonExpr:
|
||||
@@ -2193,7 +2188,7 @@ proc semDefined(c: PContext, n: PNode): PNode =
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.intVal = ord isDefined(c.config, considerQuotedIdentOrDot(c, n[1], n).s)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc lookUpForDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
|
||||
case n.kind
|
||||
@@ -2229,7 +2224,7 @@ proc semDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.intVal = ord lookUpForDeclared(c, n[1], onlyCurrentScope) != nil
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
|
||||
## The argument to the proc should be nkCall(...) or similar
|
||||
@@ -2302,10 +2297,10 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
localError(c.config, n.info, "getAst takes a call, but got " & n.renderTree)
|
||||
# Preserve the magic symbol in order to be handled in evals.nim
|
||||
internalAssert c.config, n[0].sym.magic == mExpandToAst
|
||||
#n.typ = getSysSym("NimNode").typ # expandedSym.getReturnType
|
||||
#n.typ() = getSysSym("NimNode").typ # expandedSym.getReturnType
|
||||
if n.kind == nkStmtList and n.len == 1: result = n[0]
|
||||
else: result = n
|
||||
result.typ = sysTypeFromName(c.graph, n.info, "NimNode")
|
||||
result.typ() = sysTypeFromName(c.graph, n.info, "NimNode")
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
@@ -2376,7 +2371,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
|
||||
processQuotations(c, quotedBlock, op, quotes, ids)
|
||||
|
||||
let dummyTemplateSym = newAnonSym(c, skTemplate, n.info)
|
||||
incl(dummyTemplateSym.flagsImpl, sfTemplateRedefinition)
|
||||
incl(dummyTemplateSym.flags, sfTemplateRedefinition)
|
||||
var dummyTemplate = newProcNode(
|
||||
nkTemplateDef, quotedBlock.info, body = quotedBlock,
|
||||
params = c.graph.emptyNode,
|
||||
@@ -2475,7 +2470,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if n.len == 3:
|
||||
@@ -2505,9 +2500,8 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
|
||||
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
|
||||
# codegen would fail:
|
||||
if sfCompilerProc in result.flags:
|
||||
ensureMutable result
|
||||
result.flagsImpl.excl {sfCompilerProc, sfExportc, sfImportc}
|
||||
result.locImpl.snippet = ""
|
||||
result.flags.excl {sfCompilerProc, sfExportc, sfImportc}
|
||||
result.loc.snippet = ""
|
||||
|
||||
proc setMs(n: PNode, s: PSym): PNode =
|
||||
result = n
|
||||
@@ -2520,7 +2514,7 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
n[1] = semExprWithType(c, n[1], {efDetermineType})
|
||||
#restoreOldStyleType(n[1])
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
result = foldSizeOf(c.config, n, n)
|
||||
|
||||
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -2562,7 +2556,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of mParallel:
|
||||
markUsed(c, n.info, s)
|
||||
if parallel notin c.features:
|
||||
@@ -2588,9 +2582,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
let typ = result[^1].typ
|
||||
if not typ.isEmptyType:
|
||||
if spawnResult(typ, c.inParallelStmt > 0) == srFlowVar:
|
||||
result.typ = createFlowVar(c, typ, n.info)
|
||||
result.typ() = createFlowVar(c, typ, n.info)
|
||||
else:
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
result.add instantiateCreateFlowVarCall(c, typ, n.info).newSymNode
|
||||
else:
|
||||
result.add c.graph.emptyNode
|
||||
@@ -2598,7 +2592,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
markUsed(c, n.info, s)
|
||||
result = setMs(n, s)
|
||||
result[1] = semExpr(c, n[1])
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
of mPlugin:
|
||||
markUsed(c, n.info, s)
|
||||
# semDirectOp with conditional 'afterCallActions':
|
||||
@@ -2729,19 +2723,19 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
else: illFormedAst(n, c.config)
|
||||
if cannotResolve:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
if result == nil:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
if whenNimvm:
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if n.len == 1:
|
||||
result.add(newTree(nkElse, newNode(nkStmtList)))
|
||||
|
||||
proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkCurly, n.info)
|
||||
result.typ = newTypeS(tySet, c)
|
||||
result.typ.incl tfIsConstructor
|
||||
result.typ() = newTypeS(tySet, c)
|
||||
result.typ.flags.incl tfIsConstructor
|
||||
var expectedElementType: PType = nil
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
@@ -2771,7 +2765,7 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
if doSetType:
|
||||
typ = skipTypes(n[i][1].typ,
|
||||
{tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
n[i].typ = n[i][2].typ # range node needs type too
|
||||
n[i].typ() = n[i][2].typ # range node needs type too
|
||||
elif n[i].kind == nkRange:
|
||||
# already semchecked
|
||||
if doSetType:
|
||||
@@ -2802,9 +2796,9 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
for i in 0..<n.len:
|
||||
if isIntLit(n[i].typ):
|
||||
# generic instantiation strips int lit type which makes conversions fail
|
||||
n[i].typ = nil
|
||||
n[i].typ() = nil
|
||||
result.add n[i]
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
addSonSkipIntLit(result.typ, typ, c.idgen)
|
||||
for i in 0..<n.len:
|
||||
@@ -2902,7 +2896,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType
|
||||
|
||||
if n[i][1].typ.kind == tyTypeDesc:
|
||||
localError(c.config, n[i][1].info, "typedesc not allowed as tuple field.")
|
||||
n[i][1].typ = errorType(c)
|
||||
n[i][1].typ() = errorType(c)
|
||||
|
||||
var f = newSymS(skField, n[i][0], c)
|
||||
f.typ = skipIntLit(n[i][1].typ.skipTypes({tySink}), c.idgen)
|
||||
@@ -2915,17 +2909,17 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType
|
||||
for i in 0..<result.len:
|
||||
if isIntLit(result[i][1].typ):
|
||||
# generic instantiation strips int lit type which makes conversions fail
|
||||
result[i][1].typ = nil
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result[i][1].typ() = nil
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
let oldType = n.typ
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if oldType != nil and not hasEmpty(oldType): # see hasEmpty comment above
|
||||
# convert back to old type
|
||||
let conversion = indexTypesMatch(c, oldType, typ, result)
|
||||
# ignore matching error, the goal is just to keep the original type info
|
||||
if conversion != nil:
|
||||
result.typ = oldType
|
||||
result.typ() = oldType
|
||||
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n # we don't modify n, but compute the type:
|
||||
@@ -2956,17 +2950,17 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedT
|
||||
for i in 0..<result.len:
|
||||
if isIntLit(result[i].typ):
|
||||
# generic instantiation strips int lit type which makes conversions fail
|
||||
result[i].typ = nil
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result[i].typ() = nil
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
let oldType = n.typ
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if oldType != nil and not hasEmpty(oldType): # see hasEmpty comment above
|
||||
# convert back to old type
|
||||
let conversion = indexTypesMatch(c, oldType, typ, result)
|
||||
# ignore matching error, the goal is just to keep the original type info
|
||||
if conversion != nil:
|
||||
result.typ = oldType
|
||||
result.typ() = oldType
|
||||
|
||||
include semobjconstr
|
||||
|
||||
@@ -2988,7 +2982,7 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = ni
|
||||
styleCheckDef(c, labl)
|
||||
onDef(n[0].info, labl)
|
||||
n[1] = semExpr(c, n[1], flags, expectedType)
|
||||
n.typ = n[1].typ
|
||||
n.typ() = n[1].typ
|
||||
if isEmptyType(n.typ): n.transitionSonsKind(nkBlockStmt)
|
||||
else: n.transitionSonsKind(nkBlockExpr)
|
||||
closeScope(c)
|
||||
@@ -3054,13 +3048,6 @@ proc semExport(c: PContext, n: PNode): PNode =
|
||||
|
||||
s = nextOverloadIter(o, c, a)
|
||||
|
||||
proc isTypeTupleField(n: PNode): bool {.inline.} =
|
||||
result = n.typ.kind == tyTypeDesc or
|
||||
(n.typ.kind == tyGenericParam and n.typ.sym.kind == skGenericParam)
|
||||
# `skGenericParam` stays as `tyGenericParam` type rather than being wrapped in `tyTypeDesc`
|
||||
# would check if `n` itself is an `skGenericParam` symbol, but these symbols semcheck to an ident
|
||||
# maybe check if `n` is an ident to ensure this is not a value with the generic param type?
|
||||
|
||||
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = semTuplePositionsConstr(c, n, flags, expectedType)
|
||||
if result.typ.kind == tyFromExpr:
|
||||
@@ -3071,22 +3058,22 @@ proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
var isTupleType: bool = false
|
||||
if tupexp.len > 0: # don't interpret () as type
|
||||
internalAssert c.config, tupexp.kind == nkTupleConstr
|
||||
isTupleType = isTypeTupleField(tupexp[0])
|
||||
isTupleType = tupexp[0].typ.kind == tyTypeDesc
|
||||
# check if either everything or nothing is tyTypeDesc
|
||||
for i in 1..<tupexp.len:
|
||||
if isTupleType != isTypeTupleField(tupexp[i]):
|
||||
if isTupleType != (tupexp[i].typ.kind == tyTypeDesc):
|
||||
return localErrorNode(c, n, tupexp[i].info, "Mixing types and values in tuples is not allowed.")
|
||||
if isTupleType: # expressions as ``(int, string)`` are reinterpret as type expressions
|
||||
result = n
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
|
||||
proc isExplicitGenericCall(c: PContext, n: PNode): bool =
|
||||
## checks if a call node `n` is a routine call with explicit generic params
|
||||
##
|
||||
##
|
||||
## the callee node needs to be either an nkBracketExpr or a call to a
|
||||
## symchoice of `[]` in which case it will be transformed into nkBracketExpr
|
||||
##
|
||||
##
|
||||
## the LHS of the bracket expr has to either be a symchoice or resolve to
|
||||
## a routine symbol
|
||||
template checkCallee(n: PNode) =
|
||||
@@ -3224,7 +3211,7 @@ proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym; flags: TExprFlags): PNod
|
||||
a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
if a.kind == skEnumField:
|
||||
incl(a.flagsImpl, sfUsed)
|
||||
incl(a.flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, a)
|
||||
result.add newSymNode(a, info)
|
||||
onUse(info, a)
|
||||
@@ -3299,10 +3286,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind == typeKind):
|
||||
result.typ = expected
|
||||
result.typ() = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, typeKind)
|
||||
result.typ() = getSysType(c.graph, n.info, typeKind)
|
||||
|
||||
result = n
|
||||
when defined(nimsuggest):
|
||||
@@ -3338,7 +3325,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
# localError(c.config, n.info, errInstantiateXExplicitly, s.name.s)
|
||||
# "procs literals" are 'owned'
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
of skEnumField:
|
||||
result = enumFieldSymChoice(c, n, s, flags)
|
||||
else:
|
||||
@@ -3367,11 +3354,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
discard
|
||||
of nkNilLit:
|
||||
if result.typ == nil:
|
||||
result.typ = getNilType(c)
|
||||
result.typ() = getNilType(c)
|
||||
if expectedType != nil and expectedType.kind notin {tyUntyped, tyTyped}:
|
||||
var m = newCandidate(c, result.typ)
|
||||
if typeRel(m, expectedType, result.typ) >= isSubtype:
|
||||
result.typ = expectedType
|
||||
result.typ() = expectedType
|
||||
# or: result = fitNode(c, expectedType, result, n.info)
|
||||
of nkIntLit:
|
||||
if result.typ == nil:
|
||||
@@ -3399,10 +3386,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyFloat..tyFloat128}):
|
||||
result.typ = expected
|
||||
result.typ() = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyFloat64)
|
||||
result.typ() = getSysType(c.graph, n.info, tyFloat64)
|
||||
of nkFloat32Lit: directLiteral(tyFloat32)
|
||||
of nkFloat64Lit: directLiteral(tyFloat64)
|
||||
of nkFloat128Lit: directLiteral(tyFloat128)
|
||||
@@ -3411,9 +3398,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyString, tyCstring}):
|
||||
result.typ = expectedType
|
||||
result.typ() = expectedType
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of nkCharLit: directLiteral(tyChar)
|
||||
of nkDotExpr:
|
||||
result = semFieldAccess(c, n, flags)
|
||||
@@ -3428,13 +3415,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
let modifier = n.modifierTypeKindOfNode
|
||||
if modifier != tyNone:
|
||||
var baseType = semExpr(c, n[0]).typ.skipTypes({tyTypeDesc})
|
||||
result.typ = c.makeTypeDesc(newTypeS(modifier, c, baseType))
|
||||
result.typ() = c.makeTypeDesc(newTypeS(modifier, c, baseType))
|
||||
return
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
of nkStmtListType:
|
||||
let typ = semTypeNode(c, n, nil)
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
# check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
|
||||
@@ -24,7 +24,7 @@ proc wrapNewScope(c: PContext, n: PNode): PNode {.inline.} =
|
||||
# a scope has to be opened in the codegen as well for reused
|
||||
# template instantiations
|
||||
let trueLit = newIntLit(c.graph, n.info, 1)
|
||||
trueLit.typ = getSysType(c.graph, n.info, tyBool)
|
||||
trueLit.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
result = newTreeI(nkIfStmt, n.info, newTreeI(nkElifBranch, n.info, trueLit, n))
|
||||
|
||||
proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
|
||||
@@ -16,7 +16,7 @@ import
|
||||
commands, magicsys, modulegraphs, lineinfos, wordrecg
|
||||
|
||||
import std/[strutils, math, strtabs]
|
||||
#from system/memory import nimCStrLen
|
||||
from system/memory import nimCStrLen
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[assertions, formatfloat]
|
||||
@@ -24,7 +24,7 @@ when defined(nimPreviewSlimSystem):
|
||||
proc errorType*(g: ModuleGraph): PType =
|
||||
## creates a type representing an error state
|
||||
result = newType(tyError, g.idgen, g.owners[^1])
|
||||
result.flagsImpl.incl tfCheckedForDestructor
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc getIntLitTypeG(g: ModuleGraph; literal: PNode; idgen: IdGenerator): PType =
|
||||
# we cache some common integer literal types for performance:
|
||||
@@ -38,7 +38,7 @@ proc newIntNodeT*(intVal: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph):
|
||||
# original type was 'int', not a distinct int etc.
|
||||
if n.typ.kind == tyInt:
|
||||
# access cache for the int lit type
|
||||
result.typ = getIntLitTypeG(g, result, idgen)
|
||||
result.typ() = getIntLitTypeG(g, result, idgen)
|
||||
result.info = n.info
|
||||
|
||||
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
@@ -46,12 +46,12 @@ proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newFloatNode(nkFloat32Lit, floatVal)
|
||||
else:
|
||||
result = newFloatNode(nkFloatLit, floatVal)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newStrNode(nkStrLit, strVal)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
@@ -179,30 +179,29 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
let argB = getInt(b)
|
||||
result = newIntNodeT(if argA > argB: argA else: argB, n, idgen, g)
|
||||
of mShlI:
|
||||
let valueB = toInt64(getInt(b)) and (n.typ.size * 8 - 1)
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(toInt128(toInt8(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyInt16: result = newIntNodeT(toInt128(toInt16(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyInt32: result = newIntNodeT(toInt128(toInt32(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyInt64: result = newIntNodeT(toInt128(toInt64(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyInt8: result = newIntNodeT(toInt128(toInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyInt16: result = newIntNodeT(toInt128(toInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyInt32: result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyInt64: result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(toInt128(toInt32(getInt(a)) shl valueB), n, idgen, g)
|
||||
result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toInt64(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl valueB), n, idgen, g)
|
||||
of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl valueB), n, idgen, g)
|
||||
result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
of tyUInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl valueB), n, idgen, g)
|
||||
result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl valueB), n, idgen, g)
|
||||
result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
|
||||
else: internalError(g.config, n.info, "constant folding for shl")
|
||||
of mShrI:
|
||||
var a = castToUInt64(getInt(a))
|
||||
let b = castToUInt64(getInt(b)) and cast[uint64](n.typ.size * 8 - 1)
|
||||
var a = cast[uint64](getInt(a))
|
||||
let b = cast[uint64](getInt(b))
|
||||
# To support the ``-d:nimOldShiftRight`` flag, we need to mask the
|
||||
# signed integers to cut off the extended sign bit in the internal
|
||||
# representation.
|
||||
@@ -221,13 +220,12 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
let c = cast[BiggestInt](a shr b)
|
||||
result = newIntNodeT(toInt128(c), n, idgen, g)
|
||||
of mAshrI:
|
||||
let valueB = toInt64(getInt(b)) and (n.typ.size * 8 - 1)
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(toInt128(ashr(toInt8(getInt(a)), valueB)), n, idgen, g)
|
||||
of tyInt16: result = newIntNodeT(toInt128(ashr(toInt16(getInt(a)), valueB)), n, idgen, g)
|
||||
of tyInt32: result = newIntNodeT(toInt128(ashr(toInt32(getInt(a)), valueB)), n, idgen, g)
|
||||
of tyInt8: result = newIntNodeT(toInt128(ashr(toInt8(getInt(a)), toInt8(getInt(b)))), n, idgen, g)
|
||||
of tyInt16: result = newIntNodeT(toInt128(ashr(toInt16(getInt(a)), toInt16(getInt(b)))), n, idgen, g)
|
||||
of tyInt32: result = newIntNodeT(toInt128(ashr(toInt32(getInt(a)), toInt32(getInt(b)))), n, idgen, g)
|
||||
of tyInt64, tyInt:
|
||||
result = newIntNodeT(toInt128(ashr(toInt64(getInt(a)), valueB)), n, idgen, g)
|
||||
result = newIntNodeT(toInt128(ashr(toInt64(getInt(a)), toInt64(getInt(b)))), n, idgen, g)
|
||||
else: internalError(g.config, n.info, "constant folding for ashr")
|
||||
of mDivI:
|
||||
let argA = getInt(a)
|
||||
@@ -321,7 +319,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
|
||||
of mArrToSeq:
|
||||
result = copyTree(a)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of mCompileOption:
|
||||
result = newIntNodeT(toInt128(ord(commands.testCompileOption(g.config, a.getStr, n.info))), n, idgen, g)
|
||||
of mCompileOptionArg:
|
||||
@@ -416,7 +414,7 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newIntNodeT(toInt128(a.getOrdValue != 0), n, idgen, g)
|
||||
of tyBool, tyEnum: # xxx shouldn't we disallow `tyEnum`?
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
else:
|
||||
raiseAssert $srcTyp.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
@@ -433,7 +431,7 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newIntNodeT(val, n, idgen, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
if check and result.kind in {nkCharLit..nkUInt64Lit} and
|
||||
dstTyp.kind notin {tyUInt..tyUInt64}:
|
||||
rangeCheck(n, getInt(result), g)
|
||||
@@ -443,12 +441,12 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of tyOpenArray, tyVarargs, tyProc, tyPointer:
|
||||
result = nil
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc getArrayConstr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
if n.kind == nkBracket:
|
||||
@@ -520,10 +518,10 @@ proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
|
||||
result = newSymNode(s, info)
|
||||
if s.typ.kind != tyTypeDesc:
|
||||
result.typ = newType(tyTypeDesc, idgen, s.owner)
|
||||
result.typ() = newType(tyTypeDesc, idgen, s.owner)
|
||||
result.typ.addSonSkipIntLit(s.typ, idgen)
|
||||
else:
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
|
||||
proc foldDefine(m, s: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
result = nil
|
||||
@@ -642,7 +640,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
if s.typ.kind == tyStatic:
|
||||
if s.typ.n != nil and tfUnresolved notin s.typ.flags:
|
||||
result = s.typ.n
|
||||
result.typ = s.typ.base
|
||||
result.typ() = s.typ.base
|
||||
elif s.typ.isIntLit:
|
||||
result = s.typ.n
|
||||
else:
|
||||
@@ -755,7 +753,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
if a == nil: return
|
||||
if leValueConv(n[1], a) and leValueConv(a, n[2]):
|
||||
result = a # a <= x and x <= b
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.kind in {tyUInt..tyUInt64}:
|
||||
discard "don't check uints"
|
||||
else:
|
||||
@@ -766,7 +764,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
var a = getConstExpr(m, n[0], idgen, g)
|
||||
if a == nil: return
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var a = getConstExpr(m, n[1], idgen, g)
|
||||
if a == nil: return
|
||||
@@ -783,7 +781,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
not (n.typ.kind == tyProc and a.typ.kind == tyProc):
|
||||
# we allow compile-time 'cast' for pointer types:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n, idgen, g)
|
||||
of nkCheckedFieldExpr:
|
||||
|
||||
@@ -50,13 +50,13 @@ proc semGenericStmtScope(c: PContext, n: PNode,
|
||||
result = semGenericStmt(c, n, flags, ctx)
|
||||
closeScope(c)
|
||||
|
||||
template isMixedIn(sym): bool {.dirty.} =
|
||||
template isMixedIn(sym): bool =
|
||||
let s = sym
|
||||
s.name.id in ctx.toMixin or (withinConcept in flags and
|
||||
s.magic == mNone and
|
||||
s.kind in OverloadableSyms)
|
||||
|
||||
template canOpenSym(s): bool {.dirty.} =
|
||||
template canOpenSym(s): bool =
|
||||
{withinMixin, withinConcept} * flags == {withinMixin} and s.id notin ctx.toBind
|
||||
|
||||
proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
@@ -65,7 +65,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
fromDotExpr=false): PNode =
|
||||
result = nil
|
||||
semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
template maybeDotChoice(c: PContext, n: PNode, s: PSym, fromDotExpr: bool) =
|
||||
if fromDotExpr:
|
||||
result = symChoice(c, n, s, scForceOpen)
|
||||
@@ -78,10 +78,10 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
case s.kind
|
||||
of skUnknown:
|
||||
# Introduced in this pass! Leave it as an identifier.
|
||||
@@ -116,7 +116,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
@@ -126,7 +126,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
onUse(n.info, s)
|
||||
of skParam:
|
||||
result = n
|
||||
@@ -145,7 +145,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
elif c.inGenericContext > 0 and withinConcept notin flags:
|
||||
# don't leave generic param as identifier node in generic type,
|
||||
# sigmatch will try to instantiate generic type AST without all params
|
||||
@@ -157,7 +157,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result = n
|
||||
onUse(n.info, s)
|
||||
@@ -168,7 +168,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
onUse(n.info, s)
|
||||
|
||||
proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
|
||||
@@ -248,13 +248,13 @@ proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
|
||||
onDef(n.info, s)
|
||||
|
||||
proc addTempDeclToIdents(c: PContext; n: PNode; kind: TSymKind; inCall: bool) =
|
||||
case n.kind
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
if inCall:
|
||||
addTempDecl(c, n, kind)
|
||||
of nkCallKinds:
|
||||
for s in n:
|
||||
addTempDeclToIdents(c, s, kind, true)
|
||||
addTempDeclToIdents(c, s, kind, true)
|
||||
else:
|
||||
for s in n:
|
||||
addTempDeclToIdents(c, s, kind, inCall)
|
||||
@@ -274,7 +274,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result = lookup(c, n, flags, ctx)
|
||||
if result != nil and result.kind == nkSym:
|
||||
assert result.sym != nil
|
||||
incl result.sym.flagsImpl, sfUsed
|
||||
incl result.sym.flags, sfUsed
|
||||
markOwnerModuleAsUsed(c, result.sym)
|
||||
of nkDotExpr:
|
||||
#let luf = if withinMixin notin flags: {checkUndeclared} else: {}
|
||||
@@ -318,7 +318,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
var first = int ord(withinConcept in flags)
|
||||
var mixinContext = false
|
||||
if s != nil:
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
mixinContext = s.magic in {mDefined, mDeclared, mDeclaredInScope, mCompiles, mAstToStr}
|
||||
let whichChoice = if s.id in ctx.toBind: scClosed
|
||||
elif s.isMixedIn: scForceOpen
|
||||
@@ -632,7 +632,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
# treat as mixin context for user pragmas & macro args
|
||||
x[j] = semGenericStmt(c, x[j], flags+{withinMixin}, ctx)
|
||||
elif prag == wInvalid:
|
||||
# only sem if not a language-level pragma
|
||||
# only sem if not a language-level pragma
|
||||
# treat as mixin context for user pragmas & macro args
|
||||
result[i] = semGenericStmt(c, x, flags+{withinMixin}, ctx)
|
||||
of nkExprColonExpr, nkExprEqExpr:
|
||||
|
||||
@@ -24,7 +24,7 @@ proc addObjFieldsToLocalScope(c: PContext; n: PNode) =
|
||||
let f = n.sym
|
||||
if f.kind == skField and fieldVisible(c, f):
|
||||
c.currentScope.symbols.strTableIncl(f, onConflictKeepOld=true)
|
||||
incl(f.flagsImpl, sfUsed)
|
||||
incl(f.flags, sfUsed)
|
||||
# it is not an error to shadow fields via parameters
|
||||
else: discard
|
||||
|
||||
@@ -42,7 +42,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: LayeredIdTable):
|
||||
if q.typ.kind in {tyTypeDesc, tyGenericParam, tyStatic, tyConcept}+tyTypeClasses:
|
||||
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
||||
var s = newSym(symKind, q.name, c.idgen, getCurrOwner(c), q.info)
|
||||
s.flagsImpl.incl {sfUsed, sfFromGeneric}
|
||||
s.flags.incl {sfUsed, sfFromGeneric}
|
||||
var t = lookup(pt, q.typ)
|
||||
if t == nil:
|
||||
if tfRetType in q.typ.flags:
|
||||
@@ -149,7 +149,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
|
||||
nil
|
||||
b = semProcBody(c, b, resultType)
|
||||
result.ast[bodyPos] = hloBody(c, b)
|
||||
excl(result, sfForward)
|
||||
excl(result.flags, sfForward)
|
||||
trackProc(c, result, result.ast[bodyPos])
|
||||
dec c.inGenericInst
|
||||
|
||||
@@ -208,7 +208,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
|
||||
|
||||
# this scope was not created by the user,
|
||||
# unused params shouldn't be reported.
|
||||
param.flagsImpl.incl sfUsed
|
||||
param.flags.incl sfUsed
|
||||
addDecl(c, param)
|
||||
|
||||
result = replaceTypeVarsT(cl, header)
|
||||
@@ -244,8 +244,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
var result = instCopyType(cl, prc.typ)
|
||||
let originalParams = result.n
|
||||
result.n = originalParams.shallowCopy
|
||||
for i in 1 ..< originalParams.len:
|
||||
let resulti = originalParams[i].sym.typ
|
||||
for i, resulti in paramTypes(result):
|
||||
# twrong_field_caching requires these 'resetIdTable' calls:
|
||||
if i > FirstParamAt:
|
||||
resetIdTable(cl.symMap)
|
||||
@@ -258,24 +257,24 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
let needsStaticSkipping = resulti.kind == tyFromExpr
|
||||
let needsTypeDescSkipping = resulti.kind == tyTypeDesc and tfUnresolved in resulti.flags
|
||||
if resulti.kind == tyFromExpr:
|
||||
resulti.incl tfNonConstExpr
|
||||
var paramType = replaceTypeVarsT(cl, resulti)
|
||||
resulti.flags.incl tfNonConstExpr
|
||||
result[i] = replaceTypeVarsT(cl, resulti)
|
||||
if needsStaticSkipping:
|
||||
paramType = paramType.skipTypes({tyStatic})
|
||||
result[i] = result[i].skipTypes({tyStatic})
|
||||
if needsTypeDescSkipping:
|
||||
paramType = paramType.skipTypes({tyTypeDesc})
|
||||
typeToFit = paramType
|
||||
result[i] = result[i].skipTypes({tyTypeDesc})
|
||||
typeToFit = result[i]
|
||||
|
||||
# ...otherwise, we use the instantiated type in `fitNode`
|
||||
if (typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone) and
|
||||
(typeToFit.kind != tyStatic):
|
||||
typeToFit = paramType
|
||||
typeToFit = result[i]
|
||||
|
||||
internalAssert c.config, originalParams[i].kind == nkSym
|
||||
let oldParam = originalParams[i].sym
|
||||
let param = copySym(oldParam, c.idgen)
|
||||
setOwner(param, prc)
|
||||
param.typ = paramType
|
||||
param.typ = result[i]
|
||||
|
||||
# The default value is instantiated and fitted against the final
|
||||
# concrete param type. We avoid calling `replaceTypeVarsN` on the
|
||||
@@ -283,7 +282,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
if oldParam.ast != nil:
|
||||
var def = oldParam.ast.copyTree
|
||||
if def.typ.kind == tyFromExpr:
|
||||
def.typ.incl tfNonConstExpr
|
||||
def.typ.flags.incl tfNonConstExpr
|
||||
if not isIntLit(def.typ):
|
||||
def = prepareNode(cl, def)
|
||||
|
||||
@@ -303,15 +302,15 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
# the only way the default value might be inserted).
|
||||
param.ast = errorNode(c, def)
|
||||
# we know the node is empty, we need the actual type for error message
|
||||
param.ast.typ = def.typ
|
||||
param.ast.typ() = def.typ
|
||||
else:
|
||||
param.ast = fitNodePostMatch(c, typeToFit, converted)
|
||||
param.typ = paramType
|
||||
param.typ = result[i]
|
||||
|
||||
result.n[i] = newSymNode(param)
|
||||
if isRecursiveStructuralType(paramType):
|
||||
if isRecursiveStructuralType(result[i]):
|
||||
localError(c.config, originalParams[i].sym.info, "illegal recursion in type '" & typeToString(result[i]) & "'")
|
||||
propagateToOwner(result, paramType)
|
||||
propagateToOwner(result, result[i])
|
||||
addDecl(c, param)
|
||||
|
||||
resetIdTable(cl.symMap)
|
||||
@@ -338,7 +337,7 @@ proc instantiateOnlyProcType(c: PContext, pt: LayeredIdTable, prc: PSym, info: T
|
||||
# examples are in texplicitgenerics
|
||||
# might be buggy, see rest of generateInstance if problems occur
|
||||
let fakeSym = copySym(prc, c.idgen)
|
||||
incl(fakeSym.flagsImpl, sfFromGeneric)
|
||||
incl(fakeSym.flags, sfFromGeneric)
|
||||
fakeSym.instantiatedFrom = prc
|
||||
openScope(c)
|
||||
for s in instantiateGenericParamList(c, prc.ast[genericParamsPos], pt):
|
||||
@@ -394,7 +393,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable,
|
||||
let oldScope = c.currentScope
|
||||
while not isTopLevel(c): c.currentScope = c.currentScope.parent
|
||||
result = copySym(fn, c.idgen)
|
||||
incl(result, sfFromGeneric)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
result.instantiatedFrom = fn
|
||||
if sfGlobal in result.flags and c.config.symbolFiles != disabledSf:
|
||||
let passc = getLocalPassC(c, producer)
|
||||
@@ -439,7 +438,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable,
|
||||
inc i
|
||||
#echo "INSTAN ", fn.name.s, " ", typeToString(result.typ), " ", entry.concreteTypes.len
|
||||
if tfTriggersCompileTime in result.typ.flags:
|
||||
incl(result, sfCompileTime)
|
||||
incl(result.flags, sfCompileTime)
|
||||
n[genericParamsPos] = c.graph.emptyNode
|
||||
var oldPrc = genericCacheGet(c.graph, fn, entry[], c.compilesContextId)
|
||||
if oldPrc == nil:
|
||||
@@ -451,10 +450,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable,
|
||||
entry.compilesId = c.compilesContextId
|
||||
addToGenericProcCache(c, fn, entry)
|
||||
c.generics.add(makeInstPair(fn, entry))
|
||||
# Log the generic instance so it gets written to the NIF file.
|
||||
# This is needed for cyclic module dependencies where generic instances
|
||||
# may be created in one module but referenced from another.
|
||||
logGenericInstance(c.graph, result)
|
||||
# bug #12985 bug #22913
|
||||
# TODO: use the context of the declaration of generic functions instead
|
||||
# TODO: consider fixing options as well
|
||||
|
||||
@@ -86,15 +86,15 @@ proc ithField(t: PType, field: var FieldTracker): FieldInfo =
|
||||
base = b.baseClass
|
||||
result = ithField(t.n, field)
|
||||
|
||||
proc annotateType*(n: PNode, t: PType; conf: ConfigRef; producedClosure: var bool) =
|
||||
proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
let x = t.skipTypes(abstractInst+{tyRange})
|
||||
# Note: x can be unequal to t and we need to be careful to use 't'
|
||||
# to not to skip tyGenericInst
|
||||
case n.kind
|
||||
of nkObjConstr:
|
||||
let x = t.skipTypes(abstractPtrs)
|
||||
n.typ = t
|
||||
n[0].typ = t
|
||||
n.typ() = t
|
||||
n[0].typ() = t
|
||||
for i in 1..<n.len:
|
||||
var tracker = FieldTracker(index: i-1, remaining: i-1, constr: n, delete: false)
|
||||
let field = x.ithField(tracker)
|
||||
@@ -102,20 +102,18 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef; producedClosure: var boo
|
||||
globalError conf, n.info, "invalid field at index " & $i
|
||||
else:
|
||||
internalAssert(conf, n[i].kind == nkExprColonExpr)
|
||||
annotateType(n[i][1], field.sym.typ, conf, producedClosure)
|
||||
annotateType(n[i][1], field.sym.typ, conf)
|
||||
if field.delete:
|
||||
# only codegen fields from active case branches
|
||||
incl(n[i].flags, nfPreventCg)
|
||||
of nkPar, nkTupleConstr:
|
||||
if x.kind == tyTuple:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
for i in 0..<n.len:
|
||||
if i >= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i
|
||||
else: annotateType(n[i], x[i], conf, producedClosure)
|
||||
else: annotateType(n[i], x[i], conf)
|
||||
elif x.kind == tyProc and x.callConv == ccClosure:
|
||||
n.typ = t
|
||||
if n.len > 1 and n[1].kind notin {nkEmpty, nkNilLit}:
|
||||
producedClosure = true
|
||||
n.typ() = t
|
||||
elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples
|
||||
if n.kind == nkTupleConstr:
|
||||
let
|
||||
@@ -127,53 +125,53 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef; producedClosure: var boo
|
||||
of nkStrKinds:
|
||||
for i in left..right:
|
||||
bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i])
|
||||
annotateType(bracketExpr[^1], x.elementType, conf, producedClosure)
|
||||
annotateType(bracketExpr[^1], x.elementType, conf)
|
||||
of nkBracket:
|
||||
for i in left..right:
|
||||
bracketExpr.add n[0][i]
|
||||
annotateType(bracketExpr[^1], x.elementType, conf, producedClosure)
|
||||
annotateType(bracketExpr[^1], x.elementType, conf)
|
||||
else:
|
||||
globalError(conf, n.info, "Incorrectly generated tuple constr")
|
||||
n[] = bracketExpr[]
|
||||
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "() must have a tuple type")
|
||||
of nkBracket:
|
||||
if x.kind in {tyArray, tySequence, tyOpenArray}:
|
||||
n.typ = t
|
||||
for m in n: annotateType(m, x.elemType, conf, producedClosure)
|
||||
n.typ() = t
|
||||
for m in n: annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(conf, n.info, "[] must have some form of array type")
|
||||
of nkCurly:
|
||||
if x.kind in {tySet}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
for m in n:
|
||||
if m.kind == nkRange:
|
||||
annotateType(m[0], x.elemType, conf, producedClosure)
|
||||
annotateType(m[1], x.elemType, conf, producedClosure)
|
||||
annotateType(m[0], x.elemType, conf)
|
||||
annotateType(m[1], x.elemType, conf)
|
||||
else:
|
||||
annotateType(m, x.elemType, conf, producedClosure)
|
||||
annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(conf, n.info, "{} must have the set type")
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
if x.kind in {tyFloat..tyFloat128}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "float literal must have some float type")
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "integer literal must have some int type")
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if x.kind in {tyString, tyCstring}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "string literal must be of some string type")
|
||||
of nkNilLit:
|
||||
if x.kind in NilableTypes+{tyString, tySequence}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "nil literal must be of some pointer type")
|
||||
else: discard
|
||||
|
||||
@@ -18,7 +18,7 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode =
|
||||
let typ = result[1].typ # new(x)
|
||||
if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyRef and typ.skipTypes({tyGenericInst, tyAlias, tySink})[0].kind == tyObject:
|
||||
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[1].info, typ))
|
||||
asgnExpr.typ = typ
|
||||
asgnExpr.typ() = typ
|
||||
var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0]
|
||||
while true:
|
||||
asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, false)
|
||||
@@ -34,11 +34,11 @@ proc semAddr(c: PContext; n: PNode): PNode =
|
||||
result = newNodeI(nkAddr, n.info)
|
||||
let x = semExprWithType(c, n)
|
||||
if x.kind == nkSym:
|
||||
x.sym.flagsImpl.incl(sfAddrTaken)
|
||||
x.sym.flags.incl(sfAddrTaken)
|
||||
if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result.add x
|
||||
result.typ = makePtrType(c, x.typ.skipTypes({tySink}))
|
||||
result.typ() = makePtrType(c, x.typ.skipTypes({tySink}))
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
var m = BiggestInt 1 # typeOfIter
|
||||
@@ -54,16 +54,16 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
|
||||
result.add typExpr
|
||||
if typExpr.typ.kind == tyFromExpr:
|
||||
typExpr.typ.incl tfNonConstExpr
|
||||
typExpr.typ.flags.incl tfNonConstExpr
|
||||
var t = typExpr.typ
|
||||
if t.kind == tyStatic:
|
||||
let base = t.skipTypes({tyStatic})
|
||||
if c.inGenericContext > 0 and base.containsGenericType:
|
||||
t = makeTypeFromExpr(c, copyTree(typExpr))
|
||||
t.incl tfNonConstExpr
|
||||
t.flags.incl tfNonConstExpr
|
||||
else:
|
||||
t = base
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ() = makeTypeDesc(c, t)
|
||||
|
||||
type
|
||||
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
|
||||
@@ -84,8 +84,8 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
if a.typ != nil and a.typ.kind in {tyGenericParam, tyFromExpr}:
|
||||
# expression is compiled early in a generic body
|
||||
result = semGenericStmt(c, x)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ.incl tfNonConstExpr
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ.flags.incl tfNonConstExpr
|
||||
return
|
||||
let s = # extract sym from first arg
|
||||
if n.len > 1:
|
||||
@@ -208,15 +208,15 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
let preferStr = traitCall[2].strVal
|
||||
prefer = parseEnum[TPreferedDesc](preferStr)
|
||||
result = newStrNode(nkStrLit, operand.typeToString(prefer))
|
||||
result.typ = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.typ() = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.info = traitCall.info
|
||||
of "name", "$":
|
||||
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
|
||||
result.typ = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.typ() = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.info = traitCall.info
|
||||
of "arity":
|
||||
result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc))
|
||||
result.typ = newType(tyInt, c.idgen, context)
|
||||
result.typ() = newType(tyInt, c.idgen, context)
|
||||
result.info = traitCall.info
|
||||
of "genericHead":
|
||||
var arg = operand
|
||||
@@ -243,7 +243,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
let cond = operand.kind == tyTuple and operand.n != nil
|
||||
result = newIntNodeT(toInt128(ord(cond)), traitCall, c.idgen, c.graph)
|
||||
of "tupleLen":
|
||||
var operand = operand.skipTypes({tyGenericInst, tyAlias})
|
||||
var operand = operand.skipTypes({tyGenericInst})
|
||||
assert operand.kind == tyTuple, $operand.kind
|
||||
result = newIntNodeT(toInt128(operand.len), traitCall, c.idgen, c.graph)
|
||||
of "distinctBase":
|
||||
@@ -286,7 +286,7 @@ proc semOrd(c: PContext, n: PNode): PNode =
|
||||
discard
|
||||
else:
|
||||
localError(c.config, n.info, errOrdinalTypeExpected % typeToString(parType, preferDesc))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semBindSym(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
@@ -402,7 +402,7 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
message(c.config, n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
if commonSuperclass(a, b) == nil:
|
||||
@@ -411,10 +411,10 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
message(c.config, n.info, hintConditionAlwaysFalse, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
else:
|
||||
localError(c.config, n.info, "'of' takes 2 arguments")
|
||||
n.typ = getSysType(c.graph, n.info, tyBool)
|
||||
n.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
result = n
|
||||
|
||||
proc semUnown(c: PContext; n: PNode): PNode =
|
||||
@@ -442,16 +442,16 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||
copyTypeProps(c.graph, c.idgen.module, result, t)
|
||||
|
||||
result[^1] = b
|
||||
result.excl tfHasOwned
|
||||
result.flags.excl tfHasOwned
|
||||
else:
|
||||
result = t
|
||||
else:
|
||||
result = t
|
||||
|
||||
result = copyTree(n[1])
|
||||
result.typ = unownedType(c, result.typ)
|
||||
result.typ() = unownedType(c, result.typ)
|
||||
# little hack for injectdestructors.nim (see bug #11350):
|
||||
#result[0].typ = nil
|
||||
#result[0].typ() = nil
|
||||
|
||||
proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym =
|
||||
# We need to do 2 things: Replace n.typ which is a 'ref T' by a 'var T' type.
|
||||
@@ -461,7 +461,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
|
||||
proc transform(c: PContext; n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode =
|
||||
result = shallowCopy(n)
|
||||
if sameTypeOrNil(n.typ, old):
|
||||
result.typ = fresh
|
||||
result.typ() = fresh
|
||||
if n.kind == nkSym and n.sym == oldParam:
|
||||
result.sym = newParam
|
||||
for i in 0 ..< safeLen(n):
|
||||
@@ -471,7 +471,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
|
||||
|
||||
result = copySym(orig, c.idgen)
|
||||
result.info = info
|
||||
result.incl sfFromGeneric
|
||||
result.flags.incl sfFromGeneric
|
||||
setOwner(result, orig)
|
||||
let origParamType = orig.typ.firstParamType
|
||||
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs), c.idgen)
|
||||
@@ -550,8 +550,8 @@ proc semNewFinalize(c: PContext; n: PNode): PNode =
|
||||
else:
|
||||
let wrapperSym = newSym(skProc, getIdent(c.graph.cache, fin.name.s & "FinalizerWrapper"), c.idgen, fin.owner, fin.info)
|
||||
let selfSymNode = newSymNode(copySym(fin.ast[paramsPos][1][0].sym, c.idgen))
|
||||
selfSymNode.typ = fin.typ.firstParamType
|
||||
wrapperSym.flagsImpl.incl sfUsed
|
||||
selfSymNode.typ() = fin.typ.firstParamType
|
||||
wrapperSym.flags.incl sfUsed
|
||||
|
||||
let wrapper = c.semExpr(c, newProcNode(nkProcDef, fin.info, body = newTree(nkCall, newSymNode(fin), selfSymNode),
|
||||
params = nkFormalParams.newTree(c.graph.emptyNode,
|
||||
@@ -568,7 +568,7 @@ proc semNewFinalize(c: PContext; n: PNode): PNode =
|
||||
let selfSymbolType = makePtrType(c, origParamType.skipTypes(abstractPtrs))
|
||||
let selfPtr = newNodeI(nkHiddenAddr, transFormedSym.ast[bodyPos][1].info)
|
||||
selfPtr.add transFormedSym.ast[bodyPos][1]
|
||||
selfPtr.typ = selfSymbolType
|
||||
selfPtr.typ() = selfSymbolType
|
||||
transFormedSym.ast[bodyPos][1] = c.semExpr(c, selfPtr)
|
||||
bindTypeHook(c, transFormedSym, n, attachedDestructor)
|
||||
result = addDefaultFieldForNew(c, n)
|
||||
@@ -580,12 +580,18 @@ proc semPrivateAccess(c: PContext, n: PNode): PNode =
|
||||
c.currentScope.allowPrivateAccess.add t.sym
|
||||
result = newNodeIT(nkEmpty, n.info, getSysType(c.graph, n.info, tyVoid))
|
||||
|
||||
proc checkDefault(c: PContext, n: PNode): PNode =
|
||||
proc checkDefault(c: PContext, n: PNode; isDefault: bool): PNode =
|
||||
result = n
|
||||
c.config.internalAssert result[1].typ.kind == tyTypeDesc
|
||||
let constructed = result[1].typ.base
|
||||
if constructed.requiresInit:
|
||||
message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
|
||||
# allows simple range types because they now have a valid default value
|
||||
if constructed.requiresInit and constructed.skipTypes({tyGenericInst}).kind != tyRange:
|
||||
# TODO: sorts out `nimPreviewRangeDefault` with `ranges` in the future
|
||||
# TODO: be lenient with views and notnil types for now
|
||||
if isDefault and c.config.features * {views, notnil} == {}:
|
||||
localError(c.config, n.info, "The '$1' type doesn't have a valid default value" % typeToString(constructed))
|
||||
else:
|
||||
message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
|
||||
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -623,7 +629,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
of mTypeTrait: result = semTypeTraits(c, n)
|
||||
of mAstToStr:
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||
of mOrd: result = semOrd(c, n)
|
||||
of mOf: result = semOf(c, n)
|
||||
@@ -636,7 +642,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result = semDynamicBindSym(c, n)
|
||||
of mProcCall:
|
||||
result = n
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
of mDotDot:
|
||||
result = n
|
||||
of mPlugin:
|
||||
@@ -672,16 +678,18 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
let seqType = result[1].typ.skipTypes({tyPtr, tyRef, # in case we had auto-dereferencing
|
||||
tyVar, tyGenericInst, tyOwned, tySink,
|
||||
tyAlias, tyUserTypeClassInst})
|
||||
if seqType.kind == tySequence and seqType.base.requiresInit:
|
||||
if seqType.kind == tySequence and seqType.base.requiresInit and
|
||||
seqType.base.skipTypes({tyGenericInst}).kind != tyRange:
|
||||
# allows simple range types because they now have a valid default value
|
||||
message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base))
|
||||
of mDefault:
|
||||
result = checkDefault(c, n)
|
||||
result = checkDefault(c, n, true)
|
||||
let typ = result[^1].typ.skipTypes({tyTypeDesc})
|
||||
let defaultExpr = defaultNodeField(c, result[^1], typ, false)
|
||||
if defaultExpr != nil:
|
||||
result = defaultExpr
|
||||
of mZeroDefault:
|
||||
result = checkDefault(c, n)
|
||||
result = checkDefault(c, n, false)
|
||||
of mIsolate:
|
||||
if not checkIsolate(n[1]):
|
||||
localError(c.config, n.info, "expression cannot be isolated: " & $n[1])
|
||||
@@ -692,7 +700,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result = n
|
||||
if result.typ != nil and expectedType != nil and result.typ.kind == tySequence and
|
||||
expectedType.kind == tySequence and result.typ.elementType.kind == tyEmpty:
|
||||
result.typ = expectedType # type inference for empty sequence # bug #21377
|
||||
result.typ() = expectedType # type inference for empty sequence # bug #21377
|
||||
of mEnsureMove:
|
||||
result = n
|
||||
if n[1].kind in {nkStmtListExpr, nkBlockExpr,
|
||||
|
||||
@@ -68,10 +68,6 @@ proc locateFieldInInitExpr(c: PContext, field: PSym, initExpr: PNode): PNode =
|
||||
let assignment = initExpr[i]
|
||||
if assignment.kind != nkExprColonExpr:
|
||||
invalidObjConstr(c, assignment)
|
||||
elif nfPreventCg in assignment.flags:
|
||||
# this is an object constructor node generated by the VM and
|
||||
# this field is in an inactive case branch, just ignore it
|
||||
discard
|
||||
elif fieldId == considerQuotedIdent(c, assignment[0]).id:
|
||||
return assignment
|
||||
|
||||
@@ -192,7 +188,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
|
||||
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recTyp
|
||||
asgnExpr.typ() = recTyp
|
||||
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)
|
||||
|
||||
proc collectBranchFields(c: PContext, n: PNode, discriminatorVal: PNode,
|
||||
@@ -240,7 +236,7 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
|
||||
let prevFields = fieldsPresentInBranch(selectedBranch)
|
||||
let currentFields = fieldsPresentInBranch(i)
|
||||
localError(c.config, constrCtx.initExpr.info,
|
||||
("The fields $1 and $2 cannot be initialized together, " &
|
||||
("The fields '$1' and '$2' cannot be initialized together, " &
|
||||
"because they are from conflicting branches in the case object.") %
|
||||
[prevFields, currentFields])
|
||||
result.status = initConflict
|
||||
@@ -482,10 +478,10 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
if t.kind == tyRef:
|
||||
t = skipTypes(t.elementType, {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
# we have to watch out, there are also 'owned proc' types that can be used
|
||||
# multiple times as long as they don't have closures.
|
||||
result.typ.incl tfHasOwned
|
||||
result.typ.flags.incl tfHasOwned
|
||||
if t.kind != tyObject:
|
||||
return localErrorNode(c, result, if t.kind != tyGenericBody:
|
||||
"object constructor needs an object type".dup(addTypeNodeDeclaredLoc(c.config, t))
|
||||
@@ -519,10 +515,6 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
invalidObjConstr(c, field)
|
||||
hasError = true
|
||||
continue
|
||||
elif nfPreventCg in field.flags:
|
||||
# this is an object constructor node generated by the VM and
|
||||
# this field is in an inactive case branch, just ignore it
|
||||
continue
|
||||
let id = considerQuotedIdent(c, field[0])
|
||||
# This node was not processed. There are two possible reasons:
|
||||
# 1) It was shadowed by a field with the same name on the left
|
||||
|
||||
@@ -407,9 +407,9 @@ proc transformSlices(g: ModuleGraph; idgen: IdGenerator; n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
var typ = newType(tyOpenArray, idgen, result.typ.owner)
|
||||
typ.add result.typ.elementType
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
let opSlice = newSymNode(createMagic(g, idgen, "slice", mSlice))
|
||||
opSlice.typ = getSysType(g, n.info, tyInt)
|
||||
opSlice.typ() = getSysType(g, n.info, tyInt)
|
||||
result.add opSlice
|
||||
result.add n[1]
|
||||
let slice = n[2].skipStmtList
|
||||
@@ -491,7 +491,7 @@ proc liftParallel*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): P
|
||||
var varSection = newNodeI(nkVarSection, n.info)
|
||||
var temp = newSym(skTemp, getIdent(g.cache, "barrier"), idgen, owner, n.info)
|
||||
temp.typ = magicsys.getCompilerProc(g, "Barrier").typ
|
||||
incl(temp.flagsImpl, sfFromGeneric)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
let tempNode = newSymNode(temp)
|
||||
varSection.addVar tempNode
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import
|
||||
ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
wordrecg, options, guards, lineinfos, semfold, semdata,
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling,
|
||||
semstrictfuncs, suggestsymdb, pushpoppragmas
|
||||
semstrictfuncs, suggestsymdb, pushpoppragmas, lowerings
|
||||
|
||||
import std/[tables, intsets, strutils, sequtils]
|
||||
|
||||
@@ -141,7 +141,7 @@ proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo; explicit
|
||||
if tracked.config.selectedGC == gcRefc or
|
||||
optSeqDestructors in tracked.config.globalOptions or
|
||||
tfHasAsgn in typ.flags:
|
||||
tracked.owner.incl sfInjectDestructors
|
||||
tracked.owner.flags.incl sfInjectDestructors
|
||||
|
||||
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
|
||||
@@ -196,7 +196,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
|
||||
let dot = newNodeI(nkDotExpr, n.info, 2)
|
||||
dot[0] = n[0]
|
||||
dot[1] = newSymNode(g)
|
||||
dot.typ = g.typ
|
||||
dot.typ() = g.typ
|
||||
for L in a.locked:
|
||||
#if a.guards.sameSubexprs(dot, L): return
|
||||
if guards.sameTree(dot, L): return
|
||||
@@ -206,7 +206,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
|
||||
|
||||
proc makeVolatile(a: PEffects; s: PSym) {.inline.} =
|
||||
if a.inTryStmt > 0 and a.config.exc == excSetjmp:
|
||||
incl(s, sfVolatile)
|
||||
incl(s.flags, sfVolatile)
|
||||
|
||||
proc varDecl(a: PEffects; n: PNode) {.inline.} =
|
||||
if n.kind == nkSym:
|
||||
@@ -372,9 +372,9 @@ proc useVarNoInitCheck(a: PEffects; n: PNode; s: PSym) =
|
||||
|
||||
proc useVar(a: PEffects, n: PNode) =
|
||||
let s = n.sym
|
||||
if a.inExceptOrFinallyStmt > 0:
|
||||
incl s.flags, sfUsedInFinallyOrExcept
|
||||
if isLocalSym(a, s):
|
||||
if a.inExceptOrFinallyStmt > 0:
|
||||
incl s, sfUsedInFinallyOrExcept
|
||||
if sfNoInit in s.flags:
|
||||
# If the variable is explicitly marked as .noinit. do not emit any error
|
||||
a.init.add s.id
|
||||
@@ -417,7 +417,7 @@ proc throws(tracked, n, orig: PNode) =
|
||||
if n.typ == nil or n.typ.kind != tyError:
|
||||
if orig != nil:
|
||||
let x = copyTree(orig)
|
||||
x.typ = n.typ
|
||||
x.typ() = n.typ
|
||||
tracked.add x
|
||||
else:
|
||||
tracked.add n
|
||||
@@ -432,12 +432,12 @@ proc excType(g: ModuleGraph; n: PNode): PType =
|
||||
|
||||
proc createRaise(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newNode(nkType)
|
||||
result.typ = getEbase(g, n.info)
|
||||
result.typ() = getEbase(g, n.info)
|
||||
if not n.isNil: result.info = n.info
|
||||
|
||||
proc createTag(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newNode(nkType)
|
||||
result.typ = g.sysTypeFromName(n.info, "RootEffect")
|
||||
result.typ() = g.sysTypeFromName(n.info, "RootEffect")
|
||||
if not n.isNil: result.info = n.info
|
||||
|
||||
proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) =
|
||||
@@ -707,7 +707,7 @@ proc isNoEffectList(n: PNode): bool {.inline.} =
|
||||
assert n.kind == nkEffectList
|
||||
n.len == 0 or (n[tagEffects] == nil and n[exceptionEffects] == nil and n[forbiddenEffects] == nil)
|
||||
|
||||
proc isTrivial(caller: PNode): bool {.inline.} =
|
||||
proc isTrival(caller: PNode): bool {.inline.} =
|
||||
result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved, mSwap}
|
||||
|
||||
proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; argIndex: int; caller: PNode) =
|
||||
@@ -716,7 +716,7 @@ proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; ar
|
||||
let param = if formals != nil and formals.n != nil and argIndex < formals.n.len: formals.n[argIndex].sym else: nil
|
||||
# assume indirect calls are taken here:
|
||||
if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and
|
||||
not isTrivial(caller) and
|
||||
not isTrival(caller) and
|
||||
((param != nil and sfEffectsDelayed in param.flags) or laxEffects in tracked.c.config.legacyFeatures):
|
||||
|
||||
internalAssert tracked.config, op.n[0].kind == nkEffectList
|
||||
@@ -888,9 +888,8 @@ proc trackIf(tracked: PEffects, n: PNode) =
|
||||
setLen(tracked.guards.s, oldFacts)
|
||||
dec tracked.inIfStmt
|
||||
|
||||
proc trackBlock(tracked: PEffects, n: PNode; typ: PType) =
|
||||
proc trackBlock(tracked: PEffects, n: PNode) =
|
||||
if n.kind in {nkStmtList, nkStmtListExpr}:
|
||||
let myBlock = tracked.currentBlock
|
||||
var oldState = -1
|
||||
for i in 0..<n.len:
|
||||
if hasSubnodeWith(n[i], nkBreakStmt):
|
||||
@@ -902,14 +901,6 @@ proc trackBlock(tracked: PEffects, n: PNode; typ: PType) =
|
||||
if oldState < 0: oldState = tracked.init.len
|
||||
track(tracked, n[i])
|
||||
if oldState > 0: setLen(tracked.init, oldState)
|
||||
if typ != nil and typ.kind in {tyVar, tyLent, tyOpenArray, tyVarargs}:
|
||||
let last = lastSon(n)
|
||||
let root = getRoot(last)
|
||||
if root != nil:
|
||||
let owner = tracked.scopes.getOrDefault(root.id, -1)
|
||||
if owner >= 0:
|
||||
localError(tracked.config, last.info, "'" & renderTree(last) & "' borrows from location '" & root.name.s &
|
||||
"' which does not live long enough")
|
||||
else:
|
||||
track(tracked, n)
|
||||
|
||||
@@ -1243,9 +1234,9 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
of nkSym:
|
||||
useVar(tracked, n)
|
||||
if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags:
|
||||
tracked.owner.incl sfInjectDestructors
|
||||
tracked.owner.flags.incl sfInjectDestructors
|
||||
# bug #15038: ensure consistency
|
||||
if n.typ == nil or (not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ)): n.typ = n.sym.typ
|
||||
if n.typ == nil or (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 isLocalSym(tracked, n[0].sym) and
|
||||
n.typ.kind notin {tyVar, tyLent}:
|
||||
@@ -1342,12 +1333,12 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
tracked.init.setLen(oldState)
|
||||
track(tracked, n[1][0])
|
||||
of nkIfStmt, nkIfExpr: trackIf(tracked, n)
|
||||
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n[1], n.typ)
|
||||
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n[1])
|
||||
of nkWhileStmt:
|
||||
# 'while true' loop?
|
||||
inc tracked.currentBlock
|
||||
if isTrue(n[0]):
|
||||
trackBlock(tracked, n[1], nil)
|
||||
trackBlock(tracked, n[1])
|
||||
else:
|
||||
# loop may never execute:
|
||||
let oldState = tracked.init.len
|
||||
@@ -1627,7 +1618,7 @@ proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode; s: PSym = nil) =
|
||||
effects[pragmasEffects] = n
|
||||
if s != nil and s.magic != mNone:
|
||||
if s.magic != mEcho:
|
||||
t.incl tfNoSideEffect
|
||||
t.flags.incl tfNoSideEffect
|
||||
|
||||
proc rawInitEffects(g: ModuleGraph; effects: PNode) =
|
||||
newSeq(effects.sons, effectListLen)
|
||||
@@ -1682,7 +1673,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
t.scopes[res.id] = t.currentBlock
|
||||
if sfNoInit in s.flags:
|
||||
# marks result "noinit"
|
||||
incl res, sfNoInit
|
||||
incl res.flags, sfNoInit
|
||||
|
||||
track(t, body)
|
||||
|
||||
@@ -1769,9 +1760,9 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
else:
|
||||
localError(g.config, s.info, "") # simple error for `system.compiles` context
|
||||
if not t.gcUnsafe:
|
||||
s.typ.incl tfGcSafe
|
||||
s.typ.flags.incl tfGcSafe
|
||||
if not t.hasSideEffect and sfSideEffect notin s.flags:
|
||||
s.typ.incl tfNoSideEffect
|
||||
s.typ.flags.incl tfNoSideEffect
|
||||
when defined(drnim):
|
||||
if c.graph.strongSemCheck != nil: c.graph.strongSemCheck(c.graph, s, body)
|
||||
when defined(useDfa):
|
||||
|
||||
@@ -79,7 +79,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
||||
if s.kind == skLabel and s.owner.id == c.p.owner.id:
|
||||
var x = newSymNode(s)
|
||||
x.info = n.info
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
n[0] = x
|
||||
suggestSym(c.graph, x.info, s, c.graph.usageSym)
|
||||
onUse(x.info, s)
|
||||
@@ -112,11 +112,11 @@ proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
dec(c.p.nestedLoopCounter)
|
||||
closeScope(c)
|
||||
if n[1].typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
elif efInTypeof in flags:
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
elif implicitlyDiscardable(n[1]):
|
||||
result[1].typ = c.enforceVoidContext
|
||||
result[1].typ() = c.enforceVoidContext
|
||||
|
||||
proc semProc(c: PContext, n: PNode): PNode
|
||||
|
||||
@@ -275,7 +275,7 @@ proc fixNilType(c: PContext; n: PNode) =
|
||||
elif n.kind in {nkStmtList, nkStmtListExpr}:
|
||||
n.transitionSonsKind(nkStmtList)
|
||||
for it in n: fixNilType(c, it)
|
||||
n.typ = nil
|
||||
n.typ() = nil
|
||||
|
||||
proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
|
||||
if c.matchedConcept != nil or efInTypeof in flags: return
|
||||
@@ -331,14 +331,14 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil):
|
||||
for it in n: discardCheck(c, it.lastSon, flags)
|
||||
result.transitionSonsKind(nkIfStmt)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
|
||||
if typ == c.enforceVoidContext: result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
for it in n:
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.transitionSonsKind(nkIfExpr)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
var check = initIntSet()
|
||||
@@ -394,9 +394,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
|
||||
elif a.len == 1:
|
||||
# count number of ``except: body`` blocks
|
||||
inc catchAllExcepts
|
||||
if noPanicOnExcept in c.graph.config.legacyFeatures:
|
||||
message(c.config, a.info, warnBareExcept,
|
||||
"The bare except clause is deprecated; use `except CatchableError:` instead")
|
||||
message(c.config, a.info, warnBareExcept,
|
||||
"The bare except clause is deprecated; use `except CatchableError:` instead")
|
||||
else:
|
||||
# support ``except KeyError, ValueError, ... : body``
|
||||
if catchAllExcepts > 0:
|
||||
@@ -439,7 +438,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
|
||||
discardCheck(c, n[0], flags)
|
||||
for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
|
||||
if not endsInNoReturn(n[0]):
|
||||
@@ -449,7 +448,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
|
||||
result = fitNode(c, typ, n, n.info)
|
||||
@@ -458,7 +457,7 @@ proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
|
||||
if r1.kind in {nkCharLit..nkUInt64Lit} and typ.skipTypes(abstractRange).kind in {tyFloat..tyFloat128}:
|
||||
result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
|
||||
result.info = n.info
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if not floatRangeCheck(result.floatVal, typ):
|
||||
localError(c.config, n.info, errFloatToString % [$result.floatVal, typeToString(typ)])
|
||||
elif r1.kind == nkSym and typ.skipTypes(abstractRange).kind == tyCstring:
|
||||
@@ -484,13 +483,13 @@ proc identWithin(n: PNode, s: PIdent): bool =
|
||||
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind, reportToNimsuggest = true): PSym =
|
||||
if isTopLevel(c):
|
||||
result = semIdentWithPragma(c, kind, n, {sfExported}, fromTopLevel = true)
|
||||
incl(result, sfGlobal)
|
||||
incl(result.flags, sfGlobal)
|
||||
#if kind in {skVar, skLet}:
|
||||
# echo "global variable here ", n.info, " ", result.name.s
|
||||
else:
|
||||
result = semIdentWithPragma(c, kind, n, {})
|
||||
if result.owner.kind == skModule:
|
||||
incl(result, sfGlobal)
|
||||
incl(result.flags, sfGlobal)
|
||||
result.options = c.config.options
|
||||
|
||||
if reportToNimsuggest:
|
||||
@@ -521,7 +520,7 @@ proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
||||
|
||||
proc isDiscardUnderscore(v: PSym): bool =
|
||||
if v.name.id == ord(wUnderscore):
|
||||
v.incl(sfGenSym)
|
||||
v.flags.incl(sfGenSym)
|
||||
result = true
|
||||
else:
|
||||
result = false
|
||||
@@ -595,7 +594,7 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
|
||||
obj.n.add newSymNode(field)
|
||||
n[0] = makeDeref x
|
||||
n[1] = newSymNode(field)
|
||||
n.typ = field.typ
|
||||
n.typ() = field.typ
|
||||
else:
|
||||
localError(c.config, n.info, "implicit object field construction " &
|
||||
"requires a .partial object, but got " & typeToString(obj))
|
||||
@@ -617,7 +616,7 @@ proc checkDefineType(c: PContext; v: PSym; t: PType) =
|
||||
# no distinct types for generic define
|
||||
skipped.excl tyDistinct
|
||||
if t.skipTypes(skipped).kind notin typeKinds:
|
||||
let name =
|
||||
let name =
|
||||
case v.magic
|
||||
of mStrDefine: "strdefine"
|
||||
of mIntDefine: "intdefine"
|
||||
@@ -726,7 +725,7 @@ template isLocalSym(sym: PSym): bool =
|
||||
sym.typ.kind == tyTypeDesc or
|
||||
sfCompileTime in sym.flags) or
|
||||
sym.kind in {skProc, skFunc, skIterator} and
|
||||
sfGlobal notin sym.flags and sym.typ.callConv == ccClosure
|
||||
sfGlobal notin sym.flags
|
||||
|
||||
proc usesLocalVar(n: PNode): bool =
|
||||
case n.kind
|
||||
@@ -780,7 +779,7 @@ proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSy
|
||||
# use same symkind for compatibility with original section
|
||||
let temp = newSym(symkind, getIdent(c.cache, "tmpTuple"), c.idgen, getCurrOwner(c), n.info)
|
||||
temp.typ = typ
|
||||
temp.flagsImpl.incl(sfGenSym)
|
||||
temp.flags.incl(sfGenSym)
|
||||
lastDef = newNodeI(defkind, a.info)
|
||||
newSons(lastDef, 3)
|
||||
lastDef[0] = newSymNode(temp)
|
||||
@@ -938,11 +937,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
else:
|
||||
if v.owner == nil: setOwner(v, c.p.owner)
|
||||
when oKeepVariableNames:
|
||||
if c.inUnrolledContext > 0: v.incl(sfShadowed)
|
||||
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
||||
else:
|
||||
let shadowed = findShadowedVar(c, v)
|
||||
if shadowed != nil:
|
||||
shadowed.incl(sfShadowed)
|
||||
shadowed.flags.incl(sfShadowed)
|
||||
if shadowed.kind == skResult and sfGenSym notin v.flags:
|
||||
message(c.config, a.info, warnResultShadowed)
|
||||
if def.kind != nkEmpty:
|
||||
@@ -1114,13 +1113,13 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
|
||||
for i in 0..<n[0].len-1:
|
||||
var v = symForVar(c, n[0][i])
|
||||
if getCurrOwner(c).kind == skModule: incl(v, sfGlobal)
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
case iter.kind
|
||||
of tyVar, tyLent:
|
||||
v.typ = newTypeS(iter.kind, c)
|
||||
v.typ.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.incl tfVarIsPtr
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
else:
|
||||
v.typ = iter[i]
|
||||
n[0][i] = newSymNode(v)
|
||||
@@ -1128,7 +1127,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
else:
|
||||
var v = symForVar(c, n[0])
|
||||
if getCurrOwner(c).kind == skModule: incl(v, sfGlobal)
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
# BUGFIX: don't use `iter` here as that would strip away
|
||||
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
|
||||
# for an example:
|
||||
@@ -1158,7 +1157,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
localError(c.config, n[i].info, errWrongNumberOfVariables)
|
||||
for j in 0..<n[i].len-1:
|
||||
var v = symForVar(c, n[i][j])
|
||||
if getCurrOwner(c).kind == skModule: incl(v, sfGlobal)
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
if mutable:
|
||||
v.typ = newTypeS(tyVar, c)
|
||||
v.typ.add iter[i][j]
|
||||
@@ -1172,13 +1171,13 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
else:
|
||||
var v = symForVar(c, n[i])
|
||||
if getCurrOwner(c).kind == skModule: incl(v, sfGlobal)
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
case iter.kind
|
||||
of tyVar, tyLent:
|
||||
v.typ = newTypeS(iter.kind, c)
|
||||
v.typ.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.incl tfVarIsPtr
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
else:
|
||||
v.typ = iter[i]
|
||||
n[i] = newSymNode(v)
|
||||
@@ -1319,9 +1318,9 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
result = semForVars(c, n, flags)
|
||||
# propagate any enforced VoidContext:
|
||||
if n[^1].typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
elif efInTypeof in flags:
|
||||
result.typ = result.lastSon.typ
|
||||
result.typ() = result.lastSon.typ
|
||||
closeScope(c)
|
||||
|
||||
proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -1401,14 +1400,14 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil
|
||||
for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
for i in 1..<n.len:
|
||||
var it = n[i]
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc semRaise(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -1459,7 +1458,7 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) =
|
||||
onDef(name[1].info, s)
|
||||
s.typ = newTypeS(tyObject, c)
|
||||
s.typ.sym = s
|
||||
s.incl sfForward
|
||||
s.flags.incl sfForward
|
||||
c.graph.packageTypes.strTableAdd s
|
||||
addInterfaceDecl(c, s)
|
||||
elif typsym.kind == skType and sfForward in typsym.flags:
|
||||
@@ -1550,7 +1549,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
|
||||
|
||||
case t.kind
|
||||
of tyGenericParam:
|
||||
t.incl tfWeakCovariant
|
||||
t.flags.incl tfWeakCovariant
|
||||
return true
|
||||
of tyObject:
|
||||
for field in t.n:
|
||||
@@ -1576,7 +1575,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
|
||||
error("covariant param '" & param.sym.name.s &
|
||||
"' used in a non-covariant position")
|
||||
elif tfWeakCovariant in formalFlags:
|
||||
param.incl tfWeakCovariant
|
||||
param.flags.incl tfWeakCovariant
|
||||
result = true
|
||||
elif tfContravariant in param.flags:
|
||||
let formalParam = targetBody[i-1].sym
|
||||
@@ -1668,11 +1667,11 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
body.size = -1 # could not be computed properly
|
||||
if body.kind == tyObject:
|
||||
# add flags applied to generic type to object (nominal) type
|
||||
incl(body, oldFlags)
|
||||
incl(body.flags, oldFlags)
|
||||
# {.inheritable, final.} is already disallowed, but
|
||||
# object might have been assumed to be final
|
||||
if tfInheritable in oldFlags and tfFinal in body.flags:
|
||||
excl(body, tfFinal)
|
||||
excl(body.flags, tfFinal)
|
||||
s.typ[^1] = body
|
||||
if tfCovariant in s.typ.flags:
|
||||
checkCovariantParamsUsages(c, s.typ)
|
||||
@@ -1721,7 +1720,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
# flag might be copied from alias/instantiation:
|
||||
let t = body.skipTypes({tyAlias, tyGenericInst})
|
||||
if not (t.kind == tyDistinct and tfBorrowDot in t.flags):
|
||||
excl s.typ, tfBorrowDot
|
||||
excl s.typ.flags, tfBorrowDot
|
||||
localError(c.config, name.info, "only a 'distinct' type can borrow `.`")
|
||||
let aa = a[2]
|
||||
if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
|
||||
@@ -1731,17 +1730,17 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
if st.kind == tyGenericBody: st = st.typeBodyImpl
|
||||
internalAssert c.config, st.kind in {tyPtr, tyRef}
|
||||
internalAssert c.config, st.last.sym == nil
|
||||
incl st, tfRefsAnonObj
|
||||
incl st.flags, tfRefsAnonObj
|
||||
let objTy = st.last
|
||||
# add flags for `ref object` etc to underlying `object`
|
||||
incl(objTy, oldFlags)
|
||||
incl(objTy.flags, oldFlags)
|
||||
# {.inheritable, final.} is already disallowed, but
|
||||
# object might have been assumed to be final
|
||||
if tfInheritable in oldFlags and tfFinal in objTy.flags:
|
||||
excl(objTy, tfFinal)
|
||||
excl(objTy.flags, tfFinal)
|
||||
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
||||
c.idgen, getCurrOwner(c), s.info)
|
||||
obj.flagsImpl.incl sfGeneratedType
|
||||
obj.flags.incl sfGeneratedType
|
||||
let symNode = newSymNode(obj)
|
||||
obj.ast = a.shallowCopy
|
||||
case a[0].kind
|
||||
@@ -1763,7 +1762,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
obj.ast[1] = a[1]
|
||||
obj.ast[2] = a[2][0]
|
||||
if sfPure in s.flags:
|
||||
obj.incl sfPure
|
||||
obj.flags.incl sfPure
|
||||
obj.typ = objTy
|
||||
objTy.sym = obj
|
||||
|
||||
@@ -1954,7 +1953,7 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), c.idgen,
|
||||
getCurrOwner(c), n.info)
|
||||
s.typ = t
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
|
||||
if owner == skMacro or t != nil:
|
||||
if n.len > resultPos and n[resultPos] != nil:
|
||||
@@ -2059,7 +2058,7 @@ proc semInferredLambda(c: PContext, pt: LayeredIdTable, n: PNode): PNode =
|
||||
popOwner(c)
|
||||
closeScope(c)
|
||||
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
# alternative variant (not quite working):
|
||||
# var prc = arg[0].sym
|
||||
# let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
|
||||
@@ -2130,7 +2129,7 @@ proc bindDupHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||
if cond:
|
||||
var obj = t.firstParamType
|
||||
while true:
|
||||
incl(obj, tfHasAsgn)
|
||||
incl(obj.flags, tfHasAsgn)
|
||||
if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier
|
||||
elif obj.kind == tyGenericInvocation: obj = obj.genericHead
|
||||
else: break
|
||||
@@ -2159,8 +2158,8 @@ proc bindDupHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||
localError(c.config, n.info, errGenerated,
|
||||
"signature for '=dup' must be proc[T: object](x: T): T")
|
||||
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s, sfOverridden)
|
||||
incl(s.flags, sfUsed)
|
||||
incl(s.flags, sfOverridden)
|
||||
|
||||
proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||
let t = s.typ
|
||||
@@ -2185,7 +2184,7 @@ proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||
if cond:
|
||||
var obj = t.firstParamType.skipTypes({tyVar})
|
||||
while true:
|
||||
incl(obj, tfHasAsgn)
|
||||
incl(obj.flags, tfHasAsgn)
|
||||
if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier
|
||||
elif obj.kind == tyGenericInvocation: obj = obj.genericHead
|
||||
else: break
|
||||
@@ -2217,8 +2216,8 @@ proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated,
|
||||
"signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s, sfOverridden)
|
||||
incl(s.flags, sfUsed)
|
||||
incl(s.flags, sfOverridden)
|
||||
|
||||
proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
let name = s.name.s.normalize
|
||||
@@ -2258,19 +2257,19 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated,
|
||||
"signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s, sfOverridden)
|
||||
incl(s.flags, sfUsed)
|
||||
incl(s.flags, sfOverridden)
|
||||
of "=", "=copy", "=sink":
|
||||
if s.magic == mAsgn: return
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s, sfOverridden)
|
||||
incl(s.flags, sfUsed)
|
||||
incl(s.flags, sfOverridden)
|
||||
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.returnType == nil and t.firstParamType.kind == tyVar:
|
||||
var obj = t.firstParamType.elementType
|
||||
while true:
|
||||
incl(obj, tfHasAsgn)
|
||||
incl(obj.flags, tfHasAsgn)
|
||||
if obj.kind == tyGenericBody: obj = obj.skipModifier
|
||||
elif obj.kind == tyGenericInvocation: obj = obj.genericHead
|
||||
else: break
|
||||
@@ -2361,7 +2360,7 @@ proc semCppMember(c: PContext; s: PSym; n: PNode) =
|
||||
typ = typ.elementType
|
||||
if typ.kind != tyObject:
|
||||
localError(c.config, n.info, pragmaName & " must be either ptr to object or object type.")
|
||||
if sameOwners(typ.owner, s.owner) and sameOwners(c.module, s.owner):
|
||||
if typ.owner.id == s.owner.id and c.module.id == s.owner.id:
|
||||
c.graph.memberProcsPerType.mgetOrPut(typ.itemId, @[]).add s
|
||||
else:
|
||||
localError(c.config, n.info,
|
||||
@@ -2429,8 +2428,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
case n[namePos].kind
|
||||
of nkEmpty:
|
||||
s = newSym(kind, c.cache.idAnon, c.idgen, c.getCurrOwner, n.info)
|
||||
s.flagsImpl.incl sfUsed
|
||||
s.incl sfGenSym
|
||||
s.flags.incl sfUsed
|
||||
s.flags.incl sfGenSym
|
||||
n[namePos] = newSymNode(s)
|
||||
of nkSym:
|
||||
s = n[namePos].sym
|
||||
@@ -2456,7 +2455,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
#s.scope = c.currentScope
|
||||
if s.kind in {skMacro, skTemplate}:
|
||||
# push noalias flag at first to prevent unwanted recursive calls:
|
||||
incl(s, sfNoalias)
|
||||
incl(s.flags, sfNoalias)
|
||||
|
||||
# before compiling the proc params & body, set as current the scope
|
||||
# where the proc was declared
|
||||
@@ -2494,14 +2493,14 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
n[genericParamsPos] = n[miscPos][1]
|
||||
n[miscPos] = c.graph.emptyNode
|
||||
|
||||
if tfTriggersCompileTime in s.typ.flags: incl(s, sfCompileTime)
|
||||
if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
|
||||
if n[patternPos].kind != nkEmpty:
|
||||
n[patternPos] = semPattern(c, n[patternPos], s)
|
||||
if s.kind == skIterator:
|
||||
s.typ.incl(tfIterator)
|
||||
s.typ.flags.incl(tfIterator)
|
||||
elif s.kind == skFunc:
|
||||
incl(s, sfNoSideEffect)
|
||||
incl(s.typ, tfNoSideEffect)
|
||||
incl(s.flags, sfNoSideEffect)
|
||||
incl(s.typ.flags, tfNoSideEffect)
|
||||
|
||||
var (proto, comesFromShadowScope) =
|
||||
if isAnon: (nil, false)
|
||||
@@ -2547,7 +2546,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
|
||||
if n[pragmasPos].kind != nkEmpty and sfBorrow notin s.flags:
|
||||
setEffectsForProcType(c.graph, s.typ, n[pragmasPos], s)
|
||||
s.typ.incl tfEffectSystemWorkaround
|
||||
s.typ.flags.incl tfEffectSystemWorkaround
|
||||
|
||||
# To ease macro generation that produce forwarded .async procs we now
|
||||
# allow a bit redundancy in the pragma declarations. The rule is
|
||||
@@ -2574,8 +2573,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if sfForward notin proto.flags and proto.magic == mNone:
|
||||
wrongRedefinition(c, n.info, proto.name.s, proto.info)
|
||||
if not comesFromShadowScope:
|
||||
excl(proto, sfForward)
|
||||
incl(proto, sfWasForwarded)
|
||||
excl(proto.flags, sfForward)
|
||||
incl(proto.flags, sfWasForwarded)
|
||||
suggestSym(c.graph, s.info, proto, c.graph.usageSym)
|
||||
closeScope(c) # close scope with wrong parameter symbols
|
||||
openScope(c) # open scope for old (correct) parameter symbols
|
||||
@@ -2645,18 +2644,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
else:
|
||||
nil
|
||||
# semantic checking also needed with importc in case used in VM
|
||||
|
||||
let isInlineIterator = isInlineIterator(s.typ)
|
||||
s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], resultType))
|
||||
# unfortunately we cannot skip this step when in 'system.compiles'
|
||||
# context as it may even be evaluated in 'system.compiles':
|
||||
|
||||
if isInlineIterator and s.typ.callConv == ccClosure:
|
||||
# iterators without explicit callconvs are lifted to closure,
|
||||
# we need to add a result symbol for them
|
||||
maybeAddResult(c, s, n)
|
||||
|
||||
|
||||
trackProc(c, s, s.ast[bodyPos])
|
||||
else:
|
||||
if (s.typ.returnType != nil and s.kind != skIterator):
|
||||
@@ -2677,8 +2667,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if s.kind in {skProc, skFunc} and s.typ.returnType != nil and s.typ.returnType.kind == tyAnything:
|
||||
localError(c.config, n[paramsPos][0].info, "return type 'auto' cannot be used in forward declarations")
|
||||
|
||||
incl(s, sfForward)
|
||||
incl(s, sfWasForwarded)
|
||||
incl(s.flags, sfForward)
|
||||
incl(s.flags, sfWasForwarded)
|
||||
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
||||
sideEffectsCheck(c, s)
|
||||
|
||||
@@ -2689,9 +2679,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
c.patterns.add(s)
|
||||
if isAnon:
|
||||
n.transitionSonsKind(nkLambda)
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
elif isTopLevel(c) and s.kind != skIterator and s.typ.callConv == ccClosure:
|
||||
localError(c.config, s.info, "'.closure' calling convention for top level routines is invalid")
|
||||
|
||||
@@ -2725,13 +2715,13 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||
# we require first class iterators to be marked with 'closure' explicitly
|
||||
# -- at least for 0.9.2.
|
||||
if s.typ.callConv == ccClosure:
|
||||
incl(s.typ, tfCapturesEnv)
|
||||
incl(s.typ.flags, tfCapturesEnv)
|
||||
else:
|
||||
s.typ.callConv = ccInline
|
||||
if result[bodyPos].kind == nkEmpty and s.magic == mNone and c.inConceptDecl == 0:
|
||||
localError(c.config, n.info, errImplOfXexpected % s.name.s)
|
||||
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ.callConv = ccClosure
|
||||
|
||||
proc semProc(c: PContext, n: PNode): PNode =
|
||||
@@ -2795,14 +2785,14 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
if param.typ.kind != tyUntyped: allUntyped = false
|
||||
# no default value, parameters required in call
|
||||
if param.ast == nil: nullary = false
|
||||
if allUntyped: incl(s, sfAllUntyped)
|
||||
if allUntyped: incl(s.flags, sfAllUntyped)
|
||||
if nullary and n[genericParamsPos].kind == nkEmpty:
|
||||
# macro can be called with alias syntax, remove pushed noalias flag
|
||||
excl(s, sfNoalias)
|
||||
excl(s.flags, sfNoalias)
|
||||
if n[bodyPos].kind == nkEmpty:
|
||||
localError(c.config, n.info, errImplOfXexpected % s.name.s)
|
||||
|
||||
proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult, resolvedIncStmt: PNode) =
|
||||
proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
|
||||
var f = checkModuleName(c.config, it)
|
||||
if f != InvalidFileIdx:
|
||||
addIncludeFileDep(c, f)
|
||||
@@ -2810,22 +2800,12 @@ proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult, resolvedIncStmt
|
||||
if containsOrIncl(c.includedFiles, f.int):
|
||||
localError(c.config, n.info, errRecursiveDependencyX % toMsgFilename(c.config, f))
|
||||
else:
|
||||
if resolvedIncStmt != nil:
|
||||
resolvedIncStmt.add newStrNode(toFullPath(c.config, f), it.info)
|
||||
includeStmtResult.add semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {})
|
||||
excl(c.includedFiles, f.int)
|
||||
|
||||
proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
var resolvedIncStmt: PNode = nil
|
||||
if optCompress in c.config.globalOptions:
|
||||
# New resolve the include filenames to string literals that contain absolute paths,
|
||||
# nicer for IC:
|
||||
resolvedIncStmt = newNodeI(nkIncludeStmt, n.info)
|
||||
result.add resolvedIncStmt
|
||||
else:
|
||||
# Legacy: Keep `include` statement as is:
|
||||
result.add n
|
||||
result.add n
|
||||
template checkAs(it: PNode) =
|
||||
if it.kind == nkInfix and it.len == 3:
|
||||
let op = it[0].getPIdent
|
||||
@@ -2843,9 +2823,9 @@ proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
for x in it[lastPos]:
|
||||
checkAs(x)
|
||||
imp[lastPos] = x
|
||||
incMod(c, n, imp, result, resolvedIncStmt)
|
||||
incMod(c, n, imp, result)
|
||||
else:
|
||||
incMod(c, n, it, result, resolvedIncStmt)
|
||||
incMod(c, n, it, result)
|
||||
|
||||
proc recursiveSetFlag(n: PNode, flag: TNodeFlag) =
|
||||
if n != nil:
|
||||
@@ -2887,7 +2867,7 @@ proc semPragmaBlock(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
n[1] = semExpr(c, n[1], expectedType = expectedType)
|
||||
dec c.inUncheckedAssignSection, inUncheckedAssignSection
|
||||
result = n
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
for i in 0..<pragmaList.len:
|
||||
case whichPragma(pragmaList[i])
|
||||
of wLine: setInfoRecursive(result, pragmaList[i].info)
|
||||
@@ -2974,14 +2954,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType =
|
||||
else: discard
|
||||
if n[i].typ == c.enforceVoidContext: #or usesResult(n[i]):
|
||||
voidContext = true
|
||||
n.typ = c.enforceVoidContext
|
||||
n.typ() = c.enforceVoidContext
|
||||
if i == last and (n.len == 1 or ({efWantValue, efInTypeof} * flags != {})):
|
||||
n.typ = n[i].typ
|
||||
n.typ() = n[i].typ
|
||||
if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
|
||||
elif i != last or voidContext:
|
||||
discardCheck(c, n[i], flags)
|
||||
else:
|
||||
n.typ = n[i].typ
|
||||
n.typ() = n[i].typ
|
||||
if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
|
||||
var m = n[i]
|
||||
while m.kind in {nkStmtListExpr, nkStmtList} and m.len > 0: # from templates
|
||||
|
||||
@@ -68,7 +68,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
if not isField or sfGenSym notin s.flags:
|
||||
result = newSymNode(s, info)
|
||||
# possibly not final field sym
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, s)
|
||||
onUse(info, s)
|
||||
else:
|
||||
@@ -85,7 +85,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
if a.kind != skModule and (not isField or sfGenSym notin a.flags):
|
||||
incl(a.flagsImpl, sfUsed)
|
||||
incl(a.flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, a)
|
||||
result.add newSymNode(a, info)
|
||||
onUse(info, a)
|
||||
@@ -180,7 +180,8 @@ proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
|
||||
|
||||
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
|
||||
result = newSym(kind, considerQuotedIdent(c.c, n), c.c.idgen, c.owner, n.info)
|
||||
incl(result.flagsImpl, {sfGenSym, sfShadowed})
|
||||
incl(result.flags, sfGenSym)
|
||||
incl(result.flags, sfShadowed)
|
||||
|
||||
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||
# locals default to 'gensym', fields default to 'inject':
|
||||
@@ -217,10 +218,10 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||
onDef(n.info, local)
|
||||
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
|
||||
if k == skParam and c.inTemplateHeader > 0:
|
||||
local.incl sfTemplateParam
|
||||
local.flags.incl sfTemplateParam
|
||||
|
||||
proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bool): PNode =
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
# bug #12885; ideally sem'checking is performed again afterwards marking
|
||||
# the symbol as used properly, but the nfSem mechanism currently prevents
|
||||
# that from happening, so we mark the module as used here already:
|
||||
@@ -238,10 +239,10 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
of skGenericParam:
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else:
|
||||
@@ -251,7 +252,7 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
of skParam:
|
||||
result = n
|
||||
of skType:
|
||||
@@ -269,10 +270,10 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else:
|
||||
@@ -282,7 +283,7 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
# Issue #12832
|
||||
when defined(nimsuggest):
|
||||
suggestSym(c.c.graph, n.info, s, c.c.graph.usageSym, false)
|
||||
@@ -297,7 +298,7 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode, explicitInject: bool): PNo
|
||||
if s != nil:
|
||||
if s.owner == c.owner and (s.kind == skParam or
|
||||
(sfGenSym in s.flags and not explicitInject)):
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
onUse(n.info, s)
|
||||
else:
|
||||
@@ -383,7 +384,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
let s = qualifiedLookUp(c.c, n, {})
|
||||
if s != nil:
|
||||
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
onUse(n.info, s)
|
||||
elif contains(c.toBind, s.id):
|
||||
@@ -393,7 +394,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
elif s.owner == c.owner and sfGenSym in s.flags and c.noGenSym == 0:
|
||||
# template tmp[T](x: var seq[T]) =
|
||||
# var yz: T
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
onUse(n.info, s)
|
||||
else:
|
||||
@@ -544,7 +545,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
let x = n[i]
|
||||
let prag = whichPragma(x)
|
||||
if prag == wInvalid:
|
||||
# only sem if not a language-level pragma
|
||||
# only sem if not a language-level pragma
|
||||
result[i] = semTemplBody(c, x)
|
||||
elif x.kind in nkPragmaCallKinds:
|
||||
# is pragma, but value still needs to be checked
|
||||
@@ -607,7 +608,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
# do not symchoice a quoted template parameter (bug #2390):
|
||||
if s.owner == c.owner and s.kind == skParam and
|
||||
n.kind == nkAccQuoted and n.len == 1:
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
onUse(n.info, s)
|
||||
return newSymNode(s, n.info)
|
||||
elif contains(c.toBind, s.id):
|
||||
@@ -687,7 +688,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
var s: PSym
|
||||
if isTopLevel(c):
|
||||
s = semIdentVis(c, skTemplate, n[namePos], {sfExported})
|
||||
incl(s, sfGlobal)
|
||||
incl(s.flags, sfGlobal)
|
||||
else:
|
||||
s = semIdentVis(c, skTemplate, n[namePos], {})
|
||||
assert s.kind == skTemplate
|
||||
@@ -700,7 +701,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
# check parameter list:
|
||||
#s.scope = c.currentScope
|
||||
# push noalias flag at first to prevent unwanted recursive calls:
|
||||
incl(s, sfNoalias)
|
||||
incl(s.flags, sfNoalias)
|
||||
pushOwner(c, s)
|
||||
openScope(c)
|
||||
n[namePos] = newSymNode(s)
|
||||
@@ -723,8 +724,8 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
for i in 1..<s.typ.n.len:
|
||||
let param = s.typ.n[i].sym
|
||||
if param.name.id != ord(wUnderscore):
|
||||
param.incl sfTemplateParam
|
||||
param.excl sfGenSym
|
||||
param.flags.incl sfTemplateParam
|
||||
param.flags.excl sfGenSym
|
||||
if param.typ.kind != tyUntyped: allUntyped = false
|
||||
# no default value, parameters required in call
|
||||
if param.ast == nil: nullary = false
|
||||
@@ -738,12 +739,12 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
# restore original generic type params as no explicit or implicit were found
|
||||
n[genericParamsPos] = n[miscPos][1]
|
||||
n[miscPos] = c.graph.emptyNode
|
||||
if allUntyped: incl(s, sfAllUntyped)
|
||||
if allUntyped: incl(s.flags, sfAllUntyped)
|
||||
if nullary and
|
||||
n[genericParamsPos].kind == nkEmpty and
|
||||
n[bodyPos].kind != nkEmpty:
|
||||
# template can be called with alias syntax, remove pushed noalias flag
|
||||
excl(s, sfNoalias)
|
||||
excl(s.flags, sfNoalias)
|
||||
|
||||
if n[patternPos].kind != nkEmpty:
|
||||
n[patternPos] = semPattern(c, n[patternPos], s)
|
||||
@@ -800,7 +801,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||
# macros because they have a shadowed param of type 'PNimNode' (see
|
||||
# semtypes.addParamOrResult). Within the pattern we have to ensure
|
||||
# to use the param with the proper type though:
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
onUse(n.info, s)
|
||||
let x = c.owner.typ.n[s.position+1].sym
|
||||
assert x.name == s.name
|
||||
|
||||
@@ -62,7 +62,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
||||
|
||||
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||
result = newTypeS(tyBuiltInTypeClass, c)
|
||||
result.incl tfCheckedForDestructor
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
result.addSonSkipIntLit(newTypeS(k, c), c.idgen)
|
||||
|
||||
proc skipGenericPrev(prev: PType): PType =
|
||||
@@ -151,7 +151,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if i != 1:
|
||||
if x != counter:
|
||||
needsReorder = true
|
||||
incl(result, tfEnumHasHoles)
|
||||
incl(result.flags, tfEnumHasHoles)
|
||||
e.ast = strVal # might be nil
|
||||
counter = x
|
||||
of nkSym:
|
||||
@@ -184,7 +184,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
identToReplace[] = symNode
|
||||
if e.position == 0: hasNull = true
|
||||
if result.sym != nil and sfExported in result.sym.flags:
|
||||
e.incl {sfUsed, sfExported}
|
||||
e.flags.incl {sfUsed, sfExported}
|
||||
|
||||
result.n.add symNode
|
||||
styleCheckDef(c, e)
|
||||
@@ -212,7 +212,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if isPure and sfExported in result.sym.flags:
|
||||
addPureEnum(c, LazySym(sym: result.sym))
|
||||
if tfNotNil in e.typ.flags and not hasNull:
|
||||
result.incl tfRequiresInit
|
||||
result.flags.incl tfRequiresInit
|
||||
setToStringProc(c.graph, result, genEnumToStrProc(result, n.info, c.graph, c.idgen))
|
||||
|
||||
proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
@@ -378,7 +378,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
for i in 0..1:
|
||||
if hasUnresolvedArgs(c, range[i]):
|
||||
result.n.add makeStaticExpr(c, range[i])
|
||||
result.incl tfUnresolved
|
||||
result.flags.incl tfUnresolved
|
||||
else:
|
||||
result.n.add semConstExpr(c, range[i])
|
||||
|
||||
@@ -398,15 +398,15 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
|
||||
if not isDefined(c.config, "nimPreviewRangeDefault"):
|
||||
let n = result.n
|
||||
if n[0].kind in {nkCharLit..nkUInt64Lit} and n[0].intVal > 0:
|
||||
incl(result, tfRequiresInit)
|
||||
incl(result.flags, tfRequiresInit)
|
||||
elif n[1].kind in {nkCharLit..nkUInt64Lit} and n[1].intVal < 0:
|
||||
incl(result, tfRequiresInit)
|
||||
incl(result.flags, tfRequiresInit)
|
||||
elif n[0].kind in {nkFloatLit..nkFloat64Lit} and
|
||||
n[0].floatVal > 0.0:
|
||||
incl(result, tfRequiresInit)
|
||||
incl(result.flags, tfRequiresInit)
|
||||
elif n[1].kind in {nkFloatLit..nkFloat64Lit} and
|
||||
n[1].floatVal < 0.0:
|
||||
incl(result, tfRequiresInit)
|
||||
incl(result.flags, tfRequiresInit)
|
||||
else:
|
||||
if n[1].kind == nkInfix and considerQuotedIdent(c, n[1][0]).s == "..<":
|
||||
localError(c.config, n[0].info, "range types need to be constructed with '..', '..<' is not supported")
|
||||
@@ -453,10 +453,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||
let info = if n.safeLen > 1: n[1].info else: n.info
|
||||
localError(c.config, info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc))
|
||||
result = makeRangeWithStaticExpr(c, e)
|
||||
if c.inGenericContext > 0: result.incl tfUnresolved
|
||||
if c.inGenericContext > 0: result.flags.incl tfUnresolved
|
||||
else:
|
||||
result = e.typ.skipTypes({tyTypeDesc})
|
||||
result.incl tfImplicitStatic
|
||||
result.flags.incl tfImplicitStatic
|
||||
elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e):
|
||||
if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})):
|
||||
localError(c.config, n[1].info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc))
|
||||
@@ -535,7 +535,7 @@ proc firstRange(config: ConfigRef, t: PType): PNode =
|
||||
result = newFloatNode(nkFloatLit, firstFloat(t))
|
||||
else:
|
||||
result = newIntNode(nkIntLit, firstOrd(config, t))
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
var typ: PType
|
||||
@@ -556,7 +556,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
typ = a[^1].typ
|
||||
else:
|
||||
fitDefaultNode(c, a[^1], typ)
|
||||
typ = a[^1].typ.skipIntLit(c.idgen)
|
||||
typ = a[^1].typ
|
||||
elif a[^2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a[^2], nil)
|
||||
if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind == tyRange:
|
||||
@@ -595,7 +595,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
result = newSymG(kind, n[1], c)
|
||||
var v = considerQuotedIdent(c, n[0])
|
||||
if sfExported in allowed and v.id == ord(wStar):
|
||||
incl(result, sfExported)
|
||||
incl(result.flags, sfExported)
|
||||
else:
|
||||
if not (sfExported in allowed):
|
||||
localError(c.config, n[0].info, errXOnlyAtModuleScope % "export")
|
||||
@@ -805,7 +805,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
if a[0].kind != nkSym:
|
||||
internalError(c.config, "semRecordCase: discriminant is no symbol")
|
||||
return
|
||||
incl(a[0].sym, sfDiscriminant)
|
||||
incl(a[0].sym.flags, sfDiscriminant)
|
||||
var covered = toInt128(0)
|
||||
var chckCovered = false
|
||||
var typ = skipTypes(a[0].typ, abstractVar-{tyTypeDesc})
|
||||
@@ -928,7 +928,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
typ = n[^1].typ
|
||||
else:
|
||||
fitDefaultNode(c, n[^1], typ)
|
||||
typ = n[^1].typ.skipIntLit(c.idgen)
|
||||
typ = n[^1].typ
|
||||
propagateToOwner(rectype, typ)
|
||||
elif n[^2].kind == nkEmpty:
|
||||
localError(c.config, n.info, errTypeExpected)
|
||||
@@ -958,9 +958,8 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
if fieldOwner != nil and
|
||||
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
||||
not hasCaseFields and f.loc.snippet == "":
|
||||
ensureMutable f
|
||||
f.locImpl.snippet = rope(f.name.s)
|
||||
f.incl {sfImportc, sfExportc} * fieldOwner.flags
|
||||
f.loc.snippet = rope(f.name.s)
|
||||
f.flags.incl {sfImportc, sfExportc} * fieldOwner.flags
|
||||
inc(pos)
|
||||
if containsOrIncl(check, f.name.id):
|
||||
localError(c.config, info, "attempt to redefine: '" & f.name.s & "'")
|
||||
@@ -1075,8 +1074,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType
|
||||
c.forwardTypeUpdates.add (result, n) # we retry in the final pass
|
||||
rawAddSon(result, realBase)
|
||||
if realBase == nil and tfInheritable in flags:
|
||||
result.incl tfInheritable
|
||||
if tfAcyclic in flags: result.incl tfAcyclic
|
||||
result.flags.incl tfInheritable
|
||||
if tfAcyclic in flags: result.flags.incl tfAcyclic
|
||||
if result.n.isNil:
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
@@ -1091,9 +1090,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType
|
||||
s.typ = result
|
||||
pragma(c, s, n[0], typePragmas)
|
||||
if base == nil and tfInheritable notin result.flags:
|
||||
incl(result, tfFinal)
|
||||
incl(result.flags, tfFinal)
|
||||
if c.inGenericContext == 0 and computeRequiresInit(c, result):
|
||||
result.incl tfRequiresInit
|
||||
result.flags.incl tfRequiresInit
|
||||
|
||||
proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
if n.len < 1:
|
||||
@@ -1136,22 +1135,22 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
addSonSkipIntLit(result, region, c.idgen)
|
||||
addSonSkipIntLit(result, t, c.idgen)
|
||||
if tfPartial in result.flags:
|
||||
if result.elementType.kind == tyObject: incl(result.elementType, tfPartial)
|
||||
if result.elementType.kind == tyObject: incl(result.elementType.flags, tfPartial)
|
||||
# if not isNilable: result.flags.incl tfNotNil
|
||||
case wrapperKind
|
||||
of tyOwned:
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
let t = newTypeS(tyOwned, c, result)
|
||||
t.incl tfHasOwned
|
||||
t.flags.incl tfHasOwned
|
||||
result = t
|
||||
of tySink:
|
||||
let t = newTypeS(tySink, c, result)
|
||||
result = t
|
||||
else: discard
|
||||
if result.kind == tyRef and
|
||||
if result.kind == tyRef and
|
||||
c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
|
||||
tfTriggersCompileTime notin result.flags:
|
||||
result.incl tfHasAsgn
|
||||
result.flags.incl tfHasAsgn
|
||||
|
||||
proc findEnforcedStaticType(t: PType): PType =
|
||||
# This handles types such as `static[T] and Foo`,
|
||||
@@ -1208,10 +1207,10 @@ proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent;
|
||||
let owner = if typeClass.sym != nil: typeClass.sym
|
||||
else: getCurrOwner(c)
|
||||
var s = newSym(skType, finalTypId, c.idgen, owner, info)
|
||||
if sfExplain in owner.flags: s.incl sfExplain
|
||||
if typId == nil: s.incl(sfAnon)
|
||||
if sfExplain in owner.flags: s.flags.incl sfExplain
|
||||
if typId == nil: s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
typeClass.incl tfImplicitTypeParam
|
||||
typeClass.flags.incl tfImplicitTypeParam
|
||||
s.position = genericParams.len
|
||||
genericParams.add newSymNode(s)
|
||||
result = typeClass
|
||||
@@ -1244,7 +1243,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName)
|
||||
result = addImplicitGeneric(c, newTypeS(tyStatic, c, base),
|
||||
paramTypId, info, genericParams, paramName)
|
||||
if result != nil: result.incl({tfHasStatic, tfUnresolved})
|
||||
if result != nil: result.flags.incl({tfHasStatic, tfUnresolved})
|
||||
|
||||
of tyTypeDesc:
|
||||
if tfUnresolved notin paramType.flags:
|
||||
@@ -1255,7 +1254,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
# XXX Why doesn't this check for tyTypeDesc instead?
|
||||
paramTypId = nil
|
||||
let t = newTypeS(tyTypeDesc, c, paramType.base)
|
||||
incl t, tfCheckedForDestructor
|
||||
incl t.flags, tfCheckedForDestructor
|
||||
result = addImplicitGeneric(c, t, paramTypId, info, genericParams, paramName)
|
||||
else:
|
||||
result = nil
|
||||
@@ -1305,7 +1304,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
for i in 0..<paramType.len - 1:
|
||||
if paramType[i].kind == tyStatic:
|
||||
var staticCopy = paramType[i].exactReplica
|
||||
staticCopy.incl tfInferrableStatic
|
||||
staticCopy.flags.incl tfInferrableStatic
|
||||
result.rawAddSon staticCopy
|
||||
else:
|
||||
result.rawAddSon newTypeS(tyAnything, c)
|
||||
@@ -1343,7 +1342,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
let liftBody = recurse(paramType.skipModifier, true)
|
||||
if liftBody != nil:
|
||||
result = liftBody
|
||||
result.incl tfHasMeta
|
||||
result.flags.incl tfHasMeta
|
||||
#result.shouldHaveMeta
|
||||
|
||||
of tyGenericInvocation:
|
||||
@@ -1374,7 +1373,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
markUsed(c, paramType.sym.info, paramType.sym)
|
||||
onUse(paramType.sym.info, paramType.sym)
|
||||
if tfWildcard in paramType.flags:
|
||||
paramType.excl tfWildcard
|
||||
paramType.flags.excl tfWildcard
|
||||
paramType.sym.transitionGenericParamToType()
|
||||
|
||||
else: result = nil
|
||||
@@ -1470,7 +1469,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
elif hasUnresolvedArgs(c, def):
|
||||
# template default value depends on other parameter
|
||||
# don't do any typechecking
|
||||
def.typ = makeTypeFromExpr(c, def.copyTree)
|
||||
def.typ() = makeTypeFromExpr(c, def.copyTree)
|
||||
break determineType
|
||||
elif typ != nil and typ.kind == tyTyped:
|
||||
canBeVoid = true
|
||||
@@ -1497,7 +1496,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# surprising behavior. We must instead fix the expected type of
|
||||
# the proc to be the unbound typedesc type:
|
||||
typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c))
|
||||
typ.incl tfCheckedForDestructor
|
||||
typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
elif def.typ != nil and def.typ.kind != tyFromExpr: # def.typ can be void
|
||||
# if def.typ != nil and def.typ.kind != tyNone:
|
||||
@@ -1522,7 +1521,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
for j in 0..<a.len-2:
|
||||
var arg = newSymG(skParam, if a[j].kind == nkPragmaExpr: a[j][0] else: a[j], c)
|
||||
if arg.name.id == ord(wUnderscore):
|
||||
arg.incl(sfGenSym)
|
||||
arg.flags.incl(sfGenSym)
|
||||
elif containsOrIncl(check, arg.name.id):
|
||||
localError(c.config, a[j].info, "attempt to redefine: '" & arg.name.s & "'")
|
||||
if a[j].kind == nkPragmaExpr:
|
||||
@@ -1588,7 +1587,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# 'auto' as a return type does not imply a generic:
|
||||
elif r.kind == tyAnything:
|
||||
r = copyType(r, c.idgen, r.owner)
|
||||
r.incl tfRetType
|
||||
r.flags.incl tfRetType
|
||||
elif r.kind == tyStatic:
|
||||
# type allowed should forbid this type
|
||||
discard
|
||||
@@ -1600,13 +1599,13 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
r = lifted
|
||||
#if r.kind != tyGenericParam:
|
||||
#echo "came here for ", typeToString(r)
|
||||
r.incl tfRetType
|
||||
r.flags.incl tfRetType
|
||||
r = skipIntLit(r, c.idgen)
|
||||
if kind == skIterator:
|
||||
# see tchainediterators
|
||||
# in cases like iterator foo(it: iterator): typeof(it)
|
||||
# we don't need to change the return type to iter[T]
|
||||
result.incl tfIterator
|
||||
result.flags.incl tfIterator
|
||||
# XXX Would be nice if we could get rid of this
|
||||
result[0] = r
|
||||
let oldFlags = result.flags
|
||||
@@ -1614,17 +1613,17 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
if oldFlags != result.flags:
|
||||
# XXX This rather hacky way keeps 'tflatmap' compiling:
|
||||
if tfHasMeta notin oldFlags:
|
||||
result.excl tfHasMeta
|
||||
result.n.typ = r
|
||||
result.flags.excl tfHasMeta
|
||||
result.n.typ() = r
|
||||
|
||||
if isCurrentlyGeneric():
|
||||
for n in genericParams:
|
||||
if {sfUsed, sfAnon} * n.sym.flags == {}:
|
||||
result.incl tfUnresolved
|
||||
result.flags.incl tfUnresolved
|
||||
|
||||
if tfWildcard in n.sym.typ.flags:
|
||||
n.sym.transitionGenericParamToType()
|
||||
n.sym.typ.excl tfWildcard
|
||||
n.sym.typ.flags.excl tfWildcard
|
||||
|
||||
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
@@ -1632,8 +1631,8 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||
n[i] = semStmt(c, n[i], {})
|
||||
if n.len > 0:
|
||||
result = semTypeNode(c, n[^1], prev)
|
||||
n.typ = result
|
||||
n[^1].typ = result
|
||||
n.typ() = result
|
||||
n[^1].typ() = result
|
||||
else:
|
||||
result = nil
|
||||
|
||||
@@ -1646,15 +1645,15 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n[0].kind notin {nkEmpty, nkSym}:
|
||||
addDecl(c, newSymS(skLabel, n[0], c))
|
||||
result = semStmtListType(c, n[1], prev)
|
||||
n[1].typ = result
|
||||
n.typ = result
|
||||
n[1].typ() = result
|
||||
n.typ() = result
|
||||
closeScope(c)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semGenericParamInInvocation(c: PContext, n: PNode): PType =
|
||||
result = semTypeNode(c, n, nil)
|
||||
n.typ = makeTypeDesc(c, result)
|
||||
n.typ() = makeTypeDesc(c, result)
|
||||
|
||||
proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): bool =
|
||||
var
|
||||
@@ -1777,10 +1776,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
if not trySemObjectTypeForInheritedGenericInst(c, n, tx):
|
||||
return newOrPrevType(tyError, prev, c)
|
||||
var position = 0
|
||||
# it can be that we cached this generic instance. In this case, we don't have to
|
||||
# recompute the field positions:
|
||||
if tx.state != Sealed:
|
||||
recomputeFieldPositions(tx, tx.n, position)
|
||||
recomputeFieldPositions(tx, tx.n, position)
|
||||
|
||||
proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType =
|
||||
if prev != nil and (prev.kind == tyGenericBody or
|
||||
@@ -1850,7 +1846,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
# if n.len == 0: return newConstraint(c, tyTypeClass)
|
||||
if isNewStyleConcept(n):
|
||||
result = newOrPrevType(tyConcept, prev, c)
|
||||
result.incl tfCheckedForDestructor
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
result.n = semConceptDeclaration(c, n)
|
||||
return result
|
||||
|
||||
@@ -1861,7 +1857,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
var owner = getCurrOwner(c)
|
||||
var candidateTypeSlot = newTypeS(tyAlias, c, c.errorType)
|
||||
result = newOrPrevType(tyUserTypeClass, prev, c, son = candidateTypeSlot)
|
||||
result.incl tfCheckedForDestructor
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
result.n = n
|
||||
|
||||
if inherited.kind != nkEmpty:
|
||||
@@ -1883,8 +1879,8 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
# if modifier == tyRef:
|
||||
# dummyType.flags.incl tfNotNil
|
||||
if modifier == tyTypeDesc:
|
||||
dummyType.incl tfConceptMatchedTypeSym
|
||||
dummyType.incl tfCheckedForDestructor
|
||||
dummyType.flags.incl tfConceptMatchedTypeSym
|
||||
dummyType.flags.incl tfCheckedForDestructor
|
||||
else:
|
||||
dummyName = param
|
||||
dummyType = candidateTypeSlot
|
||||
@@ -1897,7 +1893,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar,
|
||||
dummyName.ident, c.idgen, owner, param.info)
|
||||
dummyParam.typ = dummyType
|
||||
incl dummyParam.flagsImpl, sfUsed
|
||||
incl dummyParam.flags, sfUsed
|
||||
addDecl(c, dummyParam)
|
||||
|
||||
result.n[3] = semConceptBody(c, n[3])
|
||||
@@ -1982,7 +1978,7 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyStatic, prev, c)
|
||||
var base = semTypeNode(c, childNode, nil).skipTypes({tyTypeDesc, tyAlias})
|
||||
result.rawAddSon(base)
|
||||
result.incl tfHasStatic
|
||||
result.flags.incl tfHasStatic
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
|
||||
openScope(c)
|
||||
@@ -1992,12 +1988,12 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
|
||||
closeScope(c)
|
||||
result = ex.typ
|
||||
if result.kind == tyFromExpr:
|
||||
result.incl tfNonConstExpr
|
||||
result.flags.incl tfNonConstExpr
|
||||
elif result.kind == tyStatic:
|
||||
let base = result.skipTypes({tyStatic})
|
||||
if c.inGenericContext > 0 and base.containsGenericType:
|
||||
result = makeTypeFromExpr(c, copyTree(ex))
|
||||
result.incl tfNonConstExpr
|
||||
result.flags.incl tfNonConstExpr
|
||||
else:
|
||||
result = base
|
||||
fixupTypeOf(c, prev, result)
|
||||
@@ -2017,12 +2013,12 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
|
||||
closeScope(c)
|
||||
result = ex.typ
|
||||
if result.kind == tyFromExpr:
|
||||
result.incl tfNonConstExpr
|
||||
result.flags.incl tfNonConstExpr
|
||||
elif result.kind == tyStatic:
|
||||
let base = result.skipTypes({tyStatic})
|
||||
if c.inGenericContext > 0 and base.containsGenericType:
|
||||
result = makeTypeFromExpr(c, copyTree(ex))
|
||||
result.incl tfNonConstExpr
|
||||
result.flags.incl tfNonConstExpr
|
||||
else:
|
||||
result = base
|
||||
fixupTypeOf(c, prev, result)
|
||||
@@ -2056,14 +2052,14 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
return errorSym(c, n)
|
||||
result = result.typ.sym.copySym(c.idgen)
|
||||
result.typ = exactReplica(result.typ)
|
||||
result.typ.incl tfUnresolved
|
||||
result.typ.flags.incl tfUnresolved
|
||||
|
||||
if result.kind == skGenericParam:
|
||||
if result.typ.kind == tyGenericParam and result.typ.len == 0 and
|
||||
tfWildcard in result.typ.flags:
|
||||
# collapse the wild-card param to a type
|
||||
result.transitionGenericParamToType()
|
||||
result.typ.excl tfWildcard
|
||||
result.typ.flags.excl tfWildcard
|
||||
return
|
||||
else:
|
||||
localError(c.config, n.info, errTypeExpected)
|
||||
@@ -2089,7 +2085,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
n.transitionNoneToSym()
|
||||
n.sym = result
|
||||
n.info = oldInfo
|
||||
n.typ = result.typ
|
||||
n.typ() = result.typ
|
||||
else:
|
||||
localError(c.config, n.info, "identifier expected")
|
||||
result = errorSym(c, n)
|
||||
@@ -2105,7 +2101,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
# for ``typeof(countup(1,3))``, see ``tests/ttoseq``.
|
||||
checkSonsLen(n, 1, c.config)
|
||||
result = semTypeOf(c, n[0], prev)
|
||||
if result.kind == tyTypeDesc: result.incl tfExplicit
|
||||
if result.kind == tyTypeDesc: result.flags.incl tfExplicit
|
||||
of nkPar:
|
||||
if n.len == 1: result = semTypeNode(c, n[0], prev)
|
||||
else:
|
||||
@@ -2125,7 +2121,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes:
|
||||
if tfNotNil in result.flags:
|
||||
result = freshType(c, result, prev)
|
||||
result.excl(tfNotNil)
|
||||
result.flags.excl(tfNotNil)
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated, "invalid type")
|
||||
elif n[0].kind notin nkIdentKinds:
|
||||
@@ -2188,7 +2184,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = makeTypeFromExpr(c, newTree(nkStmtListType, n.copyTree))
|
||||
of NilableTypes + {tyGenericInvocation, tyForward}:
|
||||
result = freshType(c, result, prev)
|
||||
result.incl(tfNotNil)
|
||||
result.flags.incl(tfNotNil)
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated, "invalid type")
|
||||
of 2:
|
||||
@@ -2234,11 +2230,11 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of mSeq:
|
||||
result = semContainer(c, n, tySequence, "seq", prev)
|
||||
if optSeqDestructors in c.config.globalOptions:
|
||||
incl result, tfHasAsgn
|
||||
incl result.flags, tfHasAsgn
|
||||
of mVarargs: result = semVarargs(c, n, prev)
|
||||
of mTypeDesc, mType, mTypeOf:
|
||||
result = makeTypeDesc(c, semTypeNode(c, n[1], nil))
|
||||
result.incl tfExplicit
|
||||
result.flags.incl tfExplicit
|
||||
of mStatic:
|
||||
result = semStaticType(c, n[1], prev)
|
||||
of mExpr:
|
||||
@@ -2357,7 +2353,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newTypeS(tyBuiltInTypeClass, c)
|
||||
let child = newTypeS(tyProc, c)
|
||||
if n.kind == nkIteratorTy:
|
||||
child.incl tfIterator
|
||||
child.flags.incl tfIterator
|
||||
if n.len > 0 and n[1].kind != nkEmpty and n[1].len > 0:
|
||||
# typeclass with pragma
|
||||
let symKind = if n.kind == nkIteratorTy: skIterator else: skProc
|
||||
@@ -2375,9 +2371,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
|
||||
if n.kind == nkIteratorTy and result.kind == tyProc:
|
||||
result.incl(tfIterator)
|
||||
result.flags.incl(tfIterator)
|
||||
if result.callConv == ccClosure and c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
|
||||
result.incl tfHasAsgn
|
||||
result.flags.incl tfHasAsgn
|
||||
of nkEnumTy: result = semEnum(c, n, prev)
|
||||
of nkType: result = n.typ
|
||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||
@@ -2388,7 +2384,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
when false:
|
||||
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
n.typ = result
|
||||
n.typ() = result
|
||||
dec c.inTypeContext
|
||||
|
||||
proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
@@ -2407,7 +2403,7 @@ proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
|
||||
proc setMagicIntegral(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
setMagicType(conf, m, kind, size)
|
||||
incl m.typ, tfCheckedForDestructor
|
||||
incl m.typ.flags, tfCheckedForDestructor
|
||||
|
||||
proc processMagicType(c: PContext, m: PSym) =
|
||||
case m.magic
|
||||
@@ -2431,7 +2427,7 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
setMagicType(c.config, m, tyString, szUncomputedSize)
|
||||
rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
|
||||
if optSeqDestructors in c.config.globalOptions:
|
||||
incl m.typ, tfHasAsgn
|
||||
incl m.typ.flags, tfHasAsgn
|
||||
of mCstring:
|
||||
setMagicIntegral(c.config, m, tyCstring, c.config.target.ptrSize)
|
||||
rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
|
||||
@@ -2468,7 +2464,7 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of mSeq:
|
||||
setMagicType(c.config, m, tySequence, szUncomputedSize)
|
||||
if optSeqDestructors in c.config.globalOptions:
|
||||
incl m.typ, tfHasAsgn
|
||||
incl m.typ.flags, tfHasAsgn
|
||||
if defined(nimsuggest) or c.config.cmd == cmdCheck: # bug #18985
|
||||
discard
|
||||
else:
|
||||
@@ -2481,8 +2477,8 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
setMagicIntegral(c.config, m, tyIterable, 0)
|
||||
rawAddSon(m.typ, newTypeS(tyNone, c))
|
||||
of mPNimrodNode:
|
||||
incl m.typ, tfTriggersCompileTime
|
||||
incl m.typ, tfCheckedForDestructor
|
||||
incl m.typ.flags, tfTriggersCompileTime
|
||||
incl m.typ.flags, tfCheckedForDestructor
|
||||
of mException: discard
|
||||
of mBuiltinType:
|
||||
case m.name.s
|
||||
@@ -2490,7 +2486,7 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of "sink": setMagicType(c.config, m, tySink, szUncomputedSize)
|
||||
of "owned":
|
||||
setMagicType(c.config, m, tyOwned, c.config.target.ptrSize)
|
||||
incl m.typ, tfHasOwned
|
||||
incl m.typ.flags, tfHasOwned
|
||||
else: localError(c.config, m.info, errTypeExpected)
|
||||
else: localError(c.config, m.info, errTypeExpected)
|
||||
|
||||
@@ -2523,7 +2519,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
if typ.kind == tyTypeDesc:
|
||||
if typ.elementType.kind == tyNone:
|
||||
typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c))
|
||||
incl typ, tfCheckedForDestructor
|
||||
incl typ.flags, tfCheckedForDestructor
|
||||
else:
|
||||
typ = semGenericConstraints(c, typ)
|
||||
|
||||
@@ -2535,15 +2531,15 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
else:
|
||||
# the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]``
|
||||
# from manyloc/named_argument_bug/triengine:
|
||||
def.typ = def.typ.skipTypes({tyTypeDesc})
|
||||
def.typ() = def.typ.skipTypes({tyTypeDesc})
|
||||
if not containsGenericType(def.typ):
|
||||
def = fitNode(c, typ, def, def.info)
|
||||
|
||||
if typ == nil:
|
||||
typ = newTypeS(tyGenericParam, c)
|
||||
if father == nil: typ.incl tfWildcard
|
||||
if father == nil: typ.flags.incl tfWildcard
|
||||
|
||||
typ.incl tfGenericTypeParam
|
||||
typ.flags.incl tfGenericTypeParam
|
||||
|
||||
for j in 0..<a.len-2:
|
||||
var finalType: PType
|
||||
@@ -2565,7 +2561,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
localError(c.config, paramName.info, errInOutFlagNotExtern % $paramName[0])
|
||||
covarianceFlag = if paramName[0].ident.s == "in": tfContravariant
|
||||
else: tfCovariant
|
||||
if father != nil: father.incl tfCovariant
|
||||
if father != nil: father.flags.incl tfCovariant
|
||||
paramName = paramName[1]
|
||||
|
||||
var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
|
||||
@@ -2573,7 +2569,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
else:
|
||||
newSymG(skType, paramName, c).linkTo(finalType)
|
||||
|
||||
if covarianceFlag != tfUnresolved: s.typ.incl(covarianceFlag)
|
||||
if covarianceFlag != tfUnresolved: s.typ.flags.incl(covarianceFlag)
|
||||
if def.kind != nkEmpty: s.ast = def
|
||||
s.position = result.len
|
||||
result.addSym(s)
|
||||
|
||||
@@ -110,7 +110,7 @@ proc prepareNode*(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
return if tfUnresolved in t.flags: prepareNode(cl, t.n)
|
||||
else: t.n
|
||||
result = copyNode(n)
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
if result.kind == nkSym:
|
||||
result.sym =
|
||||
if n.typ != nil and n.typ == n.sym.typ:
|
||||
@@ -249,24 +249,13 @@ proc hasValuelessStatics(n: PNode): bool =
|
||||
a
|
||||
proc doThing(_: MyThing)
|
||||
]#
|
||||
result = false
|
||||
if n.safeLen == 0 and n.kind != nkEmpty: # Some empty nodes can get in here
|
||||
if n.typ == nil:
|
||||
result = true
|
||||
elif n.typ.kind == tyStatic:
|
||||
result = true
|
||||
elif n.typ.kind == tyTypeDesc:
|
||||
# Check if the base type is an unresolved generic parameter.
|
||||
# This handles cases where a template containing sizeof(T) is called
|
||||
# inside a generic object's when clause - the T needs to be resolved
|
||||
# before we can evaluate the condition.
|
||||
let base = n.typ.skipTypes({tyTypeDesc})
|
||||
if base.kind == tyGenericParam:
|
||||
result = true
|
||||
n.typ == nil or n.typ.kind == tyStatic
|
||||
else:
|
||||
for x in n:
|
||||
if hasValuelessStatics(x):
|
||||
return true
|
||||
false
|
||||
|
||||
proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PType = nil): PNode =
|
||||
if n == nil: return
|
||||
@@ -274,8 +263,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PT
|
||||
if n.typ != nil:
|
||||
if n.typ.kind == tyFromExpr:
|
||||
# type of node should not be evaluated as a static value
|
||||
n.typ.incl tfNonConstExpr
|
||||
result.typ = replaceTypeVarsT(cl, n.typ)
|
||||
n.typ.flags.incl tfNonConstExpr
|
||||
result.typ() = replaceTypeVarsT(cl, n.typ)
|
||||
checkMetaInvariants(cl, result.typ)
|
||||
case n.kind
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
@@ -290,10 +279,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PT
|
||||
if result.sym.kind == skField and result.sym.ast != nil and
|
||||
(cl.owner == nil or result.sym.owner == cl.owner):
|
||||
# instantiate default value of object/tuple field
|
||||
var n = result.sym.ast
|
||||
cl.c.fitDefaultNode(cl.c, n, result.sym.typ)
|
||||
result.sym.ast = n
|
||||
result.sym.typ = n.typ.skipIntLit(cl.c.idgen)
|
||||
cl.c.fitDefaultNode(cl.c, result.sym.ast, result.sym.typ)
|
||||
result.sym.typ = result.sym.ast.typ
|
||||
# sym type can be nil if was gensym created by macro, see #24048
|
||||
if result.sym.typ != nil and result.sym.typ.kind == tyVoid:
|
||||
# don't add the 'void' field
|
||||
@@ -374,7 +361,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym, t: PType): PSym =
|
||||
|
||||
]#
|
||||
result = copySym(s, cl.c.idgen)
|
||||
incl(result.flagsImpl, sfFromGeneric)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
#idTablePut(cl.symMap, s, result)
|
||||
setOwner(result, s.owner)
|
||||
result.typ = t
|
||||
@@ -407,12 +394,12 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
|
||||
#cl.typeMap.topLayer.idTablePut(result, t)
|
||||
|
||||
if cl.allowMetaTypes: return
|
||||
result.incl tfFromGeneric
|
||||
result.flags.incl tfFromGeneric
|
||||
if not (t.kind in tyMetaTypes or
|
||||
(t.kind == tyStatic and t.n == nil)):
|
||||
result.excl tfInstClearedFlags
|
||||
result.flags.excl tfInstClearedFlags
|
||||
else:
|
||||
result.excl tfHasAsgn
|
||||
result.flags.excl tfHasAsgn
|
||||
when false:
|
||||
if newDestructors:
|
||||
result.assignment = nil
|
||||
@@ -537,13 +524,13 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||
let mm = skipTypes(bbody, abstractPtrs)
|
||||
if tfFromGeneric notin mm.flags:
|
||||
# bug #5479, prevent endless recursions here:
|
||||
incl mm.flagsImpl, tfFromGeneric
|
||||
incl mm.flags, tfFromGeneric
|
||||
for col, meth in methodsForGeneric(cl.c.graph, mm):
|
||||
# we instantiate the known methods belonging to that type, this causes
|
||||
# them to be registered and that's enough, so we 'discard' the result.
|
||||
discard cl.c.instTypeBoundOp(cl.c, meth, result, cl.info,
|
||||
attachedAsgn, col)
|
||||
excl mm.flagsImpl, tfFromGeneric
|
||||
excl mm.flags, tfFromGeneric
|
||||
|
||||
proc eraseVoidParams*(t: PType) =
|
||||
# transform '(): void' into '()' because old parts of the compiler really
|
||||
@@ -553,12 +540,14 @@ proc eraseVoidParams*(t: PType) =
|
||||
|
||||
for i in FirstParamAt..<t.signatureLen:
|
||||
# don't touch any memory unless necessary
|
||||
if t.n[i].kind == nkRecList or t[i].kind == tyVoid:
|
||||
if t[i].kind == tyVoid:
|
||||
var pos = i
|
||||
for j in i+1..<t.signatureLen:
|
||||
if t[j].kind != tyVoid:
|
||||
t[pos] = t[j]
|
||||
t.n[pos] = t.n[j]
|
||||
inc pos
|
||||
newSons t, pos
|
||||
setLen t.n.sons, pos
|
||||
break
|
||||
|
||||
@@ -693,7 +682,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
|
||||
|
||||
of tyUserTypeClass:
|
||||
result = t
|
||||
|
||||
|
||||
of tyStatic:
|
||||
if cl.c.matchedConcept != nil:
|
||||
# allow concepts to not instantiate statics for now
|
||||
@@ -715,7 +704,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
|
||||
if not cl.allowMetaTypes and result.n != nil and
|
||||
result.base.kind != tyNone:
|
||||
result.n = cl.c.semConstExpr(cl.c, result.n)
|
||||
result.n.typ = result.base
|
||||
result.n.typ() = result.base
|
||||
|
||||
of tyGenericInst, tyUserTypeClassInst:
|
||||
bailout()
|
||||
@@ -752,8 +741,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
|
||||
let r2 = r.skipTypes({tyAlias, tySink, tyOwned})
|
||||
if r2.kind in {tyPtr, tyRef}:
|
||||
r = skipTypes(r2, {tyPtr, tyRef})
|
||||
if result.kind != tyProc or i == 0:
|
||||
result[i] = r
|
||||
result[i] = r
|
||||
if result.kind != tyArray or i != 0:
|
||||
propagateToOwner(result, r)
|
||||
# bug #4677: Do not instantiate effect lists
|
||||
@@ -766,7 +754,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
|
||||
of tyObject, tyTuple:
|
||||
propagateFieldFlags(result, result.n)
|
||||
if result.kind == tyObject and cl.c.computeRequiresInit(cl.c, result):
|
||||
result.incl tfRequiresInit
|
||||
result.flags.incl tfRequiresInit
|
||||
|
||||
of tyProc:
|
||||
eraseVoidParams(result)
|
||||
|
||||
@@ -106,10 +106,6 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: Confi
|
||||
c &= "\254"
|
||||
return
|
||||
|
||||
# Ensure type is fully loaded before hashing to avoid hash changing
|
||||
# as properties are accessed and trigger lazy loading.
|
||||
backendEnsureMutable(t)
|
||||
|
||||
case t.kind
|
||||
of tyGenericInvocation:
|
||||
for a in t.kids:
|
||||
@@ -147,15 +143,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: Confi
|
||||
if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}:
|
||||
c.hashSym(t.sym)
|
||||
of tyObject, tyEnum:
|
||||
if t.typeInstImpl != nil:
|
||||
if t.typeInst != nil:
|
||||
# prevent against infinite recursions here, see bug #8883:
|
||||
let inst = t.typeInstImpl
|
||||
t.typeInstImpl = nil # IC: spurious writes are ok since we set it back immediately
|
||||
let inst = t.typeInst
|
||||
t.typeInst = nil
|
||||
assert inst.kind == tyGenericInst
|
||||
c.hashType inst.genericHead, flags, conf
|
||||
for _, a in inst.genericInstParams:
|
||||
c.hashType a, flags, conf
|
||||
t.typeInstImpl = inst
|
||||
t.typeInst = inst
|
||||
return
|
||||
c &= char(t.kind)
|
||||
# Every cyclic type in Nim need to be constructed via some 't.sym', so this
|
||||
@@ -184,9 +180,9 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: Confi
|
||||
# Hack to prevent endless recursion
|
||||
# xxx instead, use a hash table to indicate we've already visited a type, which
|
||||
# would also be more efficient.
|
||||
symWithFlags.flagsImpl.excl {sfAnon, sfGenSym}
|
||||
symWithFlags.flags.excl {sfAnon, sfGenSym}
|
||||
hashTree(c, t.n, flags + {CoHashTypeInsideNode}, conf)
|
||||
symWithFlags.flagsImpl = oldFlags
|
||||
symWithFlags.flags = oldFlags
|
||||
else:
|
||||
# The object has no fields: we _must_ add something here in order to
|
||||
# make the hash different from the one we produce by hashing only the
|
||||
|
||||
@@ -233,11 +233,13 @@ proc copyingEraseVoidParams(m: TCandidate, t: var PType) =
|
||||
if not copied:
|
||||
# keep first i children
|
||||
t = copyType(original, m.c.idgen, t.owner)
|
||||
t.setSonsLen(i)
|
||||
t.n = copyNode(original.n)
|
||||
t.n.sons = original.n.sons
|
||||
t.n.sons.setLen(i)
|
||||
copied = true
|
||||
elif copied:
|
||||
t.add(f)
|
||||
t.n.add(original.n[i])
|
||||
|
||||
proc initCandidate*(ctx: PContext, callee: PSym,
|
||||
@@ -452,11 +454,11 @@ template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = p
|
||||
arg = c.semTryExpr(c, n[i][1])
|
||||
if arg == nil:
|
||||
arg = n[i][1]
|
||||
arg.typ = newTypeS(tyUntyped, c)
|
||||
arg.typ() = newTypeS(tyUntyped, c)
|
||||
else:
|
||||
if arg.typ == nil:
|
||||
arg.typ = newTypeS(tyVoid, c)
|
||||
n[i].typ = arg.typ
|
||||
arg.typ() = newTypeS(tyVoid, c)
|
||||
n[i].typ() = arg.typ
|
||||
n[i][1] = arg
|
||||
else:
|
||||
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
|
||||
@@ -465,10 +467,10 @@ template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = p
|
||||
arg = c.semTryExpr(c, n[i])
|
||||
if arg == nil:
|
||||
arg = n[i]
|
||||
arg.typ = newTypeS(tyUntyped, c)
|
||||
arg.typ() = newTypeS(tyUntyped, c)
|
||||
else:
|
||||
if arg.typ == nil:
|
||||
arg.typ = newTypeS(tyVoid, c)
|
||||
arg.typ() = newTypeS(tyVoid, c)
|
||||
n[i] = arg
|
||||
if arg.typ != nil and arg.typ.kind == tyError: return
|
||||
result.add argTypeToString(arg, prefer)
|
||||
@@ -895,7 +897,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
param.typ = typ.exactReplica
|
||||
#copyType(typ, c.idgen, typ.owner)
|
||||
if typ.n == nil:
|
||||
param.typ.incl tfInferrableStatic
|
||||
param.typ.flags.incl tfInferrableStatic
|
||||
else:
|
||||
param.ast = typ.n
|
||||
of tyFromExpr:
|
||||
@@ -928,8 +930,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
diagnostics = @[]
|
||||
flags = {efExplain}
|
||||
m.c.config.writelnHook = proc (s: string) =
|
||||
{.gcsafe.}:
|
||||
if errorPrefix.len == 0: errorPrefix = typeClass.sym.name.s & ":"
|
||||
if errorPrefix.len == 0: errorPrefix = typeClass.sym.name.s & ":"
|
||||
let msg = s.replace("Error:", errorPrefix)
|
||||
if oldWriteHook != nil: oldWriteHook msg
|
||||
diagnostics.add msg
|
||||
@@ -1670,7 +1671,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
|
||||
let roota = if skipBoth or deptha > depthf: a.skipGenericAlias else: a
|
||||
let rootf = if skipBoth or depthf > deptha: f.skipGenericAlias else: f
|
||||
|
||||
|
||||
if f.isConcept:
|
||||
result = enterConceptMatch(c, rootf, roota, flags)
|
||||
elif a.kind == tyGenericInst:
|
||||
@@ -1988,7 +1989,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
var concrete = a
|
||||
if tfWildcard in a.flags:
|
||||
a.sym.transitionGenericParamToType()
|
||||
a.excl tfWildcard
|
||||
a.flags.excl tfWildcard
|
||||
elif doBind:
|
||||
# careful: `trDontDont` (set by `checkGeneric`) is not always respected in this call graph.
|
||||
# typRel having two different modes (binding and non-binding) can make things harder to
|
||||
@@ -2179,18 +2180,18 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
result = newNodeI(kind, arg.info)
|
||||
if containsGenericType(f):
|
||||
if not m.matchedErrorType:
|
||||
result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
result.typ() = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
else:
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
else:
|
||||
result.typ = f.skipTypes({tySink})
|
||||
result.typ() = f.skipTypes({tySink})
|
||||
# keep varness
|
||||
if arg.typ != nil and arg.typ.kind == tyVar:
|
||||
result.typ = toVar(result.typ, tyVar, c.idgen)
|
||||
result.typ() = toVar(result.typ, tyVar, c.idgen)
|
||||
# copy the tfVarIsPtr flag
|
||||
result.typ.flags = arg.typ.flags
|
||||
else:
|
||||
result.typ = result.typ.skipTypes({tyVar})
|
||||
result.typ() = result.typ.skipTypes({tyVar})
|
||||
|
||||
if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv")
|
||||
result.add c.graph.emptyNode
|
||||
@@ -2218,13 +2219,13 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
result.add x
|
||||
else:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], elemType(newType))
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkBracket:
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], elemType(newType))
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkPar, nkTupleConstr:
|
||||
let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
@@ -2248,7 +2249,7 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], tup[i])
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if n.kind != nkUInt64Lit and not sameTypeOrNil(n.typ, newType) and isOrdinalType(newType):
|
||||
@@ -2256,14 +2257,14 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if newType.skipTypes(abstractVarRange-{tyTypeDesc}).kind == tyFloat:
|
||||
if not floatRangeCheck(n.floatVal, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkSym:
|
||||
if n.sym.kind == skEnumField and not sameTypeOrNil(n.sym.typ, newType) and isOrdinalType(newType):
|
||||
@@ -2271,7 +2272,7 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
else: discard
|
||||
return implicitConv(kind, newType, n, m, c)
|
||||
@@ -2315,10 +2316,10 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
let fdest = typeRel(m, f, dest)
|
||||
if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind in {tyVar}):
|
||||
# can't fully mark used yet, may not be used in final call
|
||||
incl(c.converters[i].flagsImpl, sfUsed)
|
||||
incl(c.converters[i].flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, c.converters[i])
|
||||
var s = newSymNode(c.converters[i])
|
||||
s.typ = c.converters[i].typ
|
||||
s.typ() = c.converters[i].typ
|
||||
s.info = arg.info
|
||||
result = newNodeIT(nkHiddenCallConv, arg.info, dest)
|
||||
result.add s
|
||||
@@ -2338,7 +2339,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
result.add param
|
||||
|
||||
if dest.kind in {tyVar, tyLent}:
|
||||
dest.incl tfVarIsPtr
|
||||
dest.flags.incl tfVarIsPtr
|
||||
result = newDeref(result)
|
||||
|
||||
inc(m.convMatches)
|
||||
@@ -2372,7 +2373,7 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
if result.kind == nkCall: result.transitionSonsKind(nkHiddenCallConv)
|
||||
inc(m.convMatches)
|
||||
if r == isGeneric:
|
||||
result.typ = getInstantiatedType(c, arg, m, base(f))
|
||||
result.typ() = getInstantiatedType(c, arg, m, base(f))
|
||||
m.baseTypeMatch = true
|
||||
|
||||
proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
|
||||
@@ -2428,13 +2429,13 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
let typ = newTypeS(tyStatic, c, son = evaluated.typ)
|
||||
typ.n = evaluated
|
||||
arg = copyTree(arg) # fix #12864
|
||||
arg.typ = typ
|
||||
arg.typ() = typ
|
||||
a = typ
|
||||
else:
|
||||
if m.callee.kind == tyGenericBody:
|
||||
if f.kind == tyStatic and typeRel(m, f.base, a) != isNone:
|
||||
result = makeStaticExpr(m.c, arg)
|
||||
result.typ.incl tfUnresolved
|
||||
result.typ.flags.incl tfUnresolved
|
||||
result.typ.n = arg
|
||||
return
|
||||
|
||||
@@ -2546,7 +2547,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
# doesn't work: `proc foo[T](): array[T, int] = ...; foo[3]()` (see #23204)
|
||||
(arg.typ.isIntLit and not m.isNoCall):
|
||||
result = arg.copyTree
|
||||
result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
result.typ() = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
else:
|
||||
result = arg
|
||||
of isBothMetaConvertible:
|
||||
@@ -2602,7 +2603,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
of isGeneric:
|
||||
inc(m.convMatches)
|
||||
result = copyTree(arg)
|
||||
result.typ = getInstantiatedType(c, arg, m, base(f))
|
||||
result.typ() = getInstantiatedType(c, arg, m, base(f))
|
||||
m.baseTypeMatch = true
|
||||
of isFromIntLit:
|
||||
inc(m.intConvMatches, 256)
|
||||
@@ -2628,7 +2629,7 @@ proc staticAwareTypeRel(m: var TCandidate, f: PType, arg: var PNode): TTypeRelat
|
||||
# The ast of the type does not point to the symbol.
|
||||
# Without this we will never resolve a `static proc` with overloads
|
||||
let copiedNode = copyNode(arg)
|
||||
copiedNode.typ = exactReplica(copiedNode.typ)
|
||||
copiedNode.typ() = exactReplica(copiedNode.typ)
|
||||
copiedNode.typ.n = arg
|
||||
arg = copiedNode
|
||||
typeRel(m, f, arg.typ)
|
||||
@@ -2897,7 +2898,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
var newlyTyped = false
|
||||
n[a][1] = prepareOperand(c, formal.typ, n[a][1], newlyTyped)
|
||||
if newlyTyped: m.newlyTypedOperands.add(a)
|
||||
n[a].typ = n[a][1].typ
|
||||
n[a].typ() = n[a][1].typ
|
||||
arg = paramTypesMatch(m, formal.typ, n[a].typ,
|
||||
n[a][1], n[a][1])
|
||||
m.firstMismatch.kind = kTypeMismatch
|
||||
@@ -2994,7 +2995,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
#assert(container == nil)
|
||||
if container.isNil:
|
||||
container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, arg))
|
||||
container.typ.incl tfVarargs
|
||||
container.typ.flags.incl tfVarargs
|
||||
else:
|
||||
incrIndexType(container.typ)
|
||||
container.add arg
|
||||
@@ -3077,7 +3078,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
if m.calleeSym != nil: m.calleeSym.detailedInfo else: "")
|
||||
typeMismatch(c.config, formal.ast.info, formal.typ, formal.ast.typ, formal.ast)
|
||||
popInfoContext(c.config)
|
||||
formal.ast.typ = errorType(c)
|
||||
formal.ast.typ() = errorType(c)
|
||||
if nfDefaultRefsParam in formal.ast.flags:
|
||||
m.call.flags.incl nfDefaultRefsParam
|
||||
var defaultValue = copyTree(formal.ast)
|
||||
|
||||
@@ -38,15 +38,14 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
|
||||
sinkType.add argType
|
||||
|
||||
arg.sym.typ = sinkType
|
||||
assert owner.typ.n[arg.sym.position+1].sym == arg.sym
|
||||
owner.typ[arg.sym.position+1] = sinkType
|
||||
|
||||
#message(config, arg.info, warnUser,
|
||||
# ("turned '$1' to a sink parameter") % [$arg])
|
||||
#echo config $ arg.info, " turned into a sink parameter ", arg.sym.name.s
|
||||
elif sfWasForwarded notin arg.sym.flags:
|
||||
# we only report every potential 'sink' parameter only once:
|
||||
ensureMutable arg.sym
|
||||
incl arg.sym.flagsImpl, sfWasForwarded
|
||||
incl arg.sym.flags, sfWasForwarded
|
||||
message(config, arg.info, hintPerformance,
|
||||
"could not turn '$1' to a sink parameter" % [arg.sym.name.s])
|
||||
#echo config $ arg.info, " candidate for a sink parameter here"
|
||||
|
||||
@@ -477,7 +477,7 @@ template foldSizeOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if size >= 0:
|
||||
let res = newIntNode(nkIntLit, size)
|
||||
res.info = node.info
|
||||
res.typ = node.typ
|
||||
res.typ() = node.typ
|
||||
res
|
||||
else:
|
||||
fallback
|
||||
@@ -491,7 +491,7 @@ template foldAlignOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if align >= 0:
|
||||
let res = newIntNode(nkIntLit, align)
|
||||
res.info = node.info
|
||||
res.typ = node.typ
|
||||
res.typ() = node.typ
|
||||
res
|
||||
else:
|
||||
fallback
|
||||
@@ -519,7 +519,7 @@ template foldOffsetOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if offset >= 0:
|
||||
let tmp = newIntNode(nkIntLit, offset)
|
||||
tmp.info = node.info
|
||||
tmp.typ = node.typ
|
||||
tmp.typ() = node.typ
|
||||
tmp
|
||||
else:
|
||||
fallback
|
||||
|
||||
@@ -16,7 +16,7 @@ from trees import getMagic, getRoot
|
||||
proc callProc(a: PNode): PNode =
|
||||
result = newNodeI(nkCall, a.info)
|
||||
result.add a
|
||||
result.typ = a.typ.returnType
|
||||
result.typ() = a.typ.returnType
|
||||
|
||||
# we have 4 cases to consider:
|
||||
# - a void proc --> nothing to do
|
||||
@@ -58,7 +58,7 @@ proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator;
|
||||
result = newSym(skTemp, getIdent(g.cache, genPrefix), idgen, owner, varSection.info,
|
||||
owner.options)
|
||||
result.typ = typ
|
||||
incl(result.flagsImpl, sfFromGeneric)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
|
||||
var vpart = newNodeI(nkIdentDefs, varSection.info, 3)
|
||||
vpart[0] = newSymNode(result)
|
||||
@@ -117,7 +117,7 @@ proc castToVoidPointer(g: ModuleGraph, n: PNode, fvField: PNode): PNode =
|
||||
result = newNodeI(nkCast, fvField.info)
|
||||
result.add newNodeI(nkEmpty, fvField.info)
|
||||
result.add fvField
|
||||
result.typ = ptrType
|
||||
result.typ() = ptrType
|
||||
|
||||
proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
|
||||
varSection, varInit, call, barrier, fv: PNode;
|
||||
@@ -200,7 +200,7 @@ proc createCastExpr(argsParam: PSym; objType: PType; idgen: IdGenerator): PNode
|
||||
result = newNodeI(nkCast, argsParam.info)
|
||||
result.add newNodeI(nkEmpty, argsParam.info)
|
||||
result.add newSymNode(argsParam)
|
||||
result.typ = newType(tyPtr, idgen, objType.owner)
|
||||
result.typ() = newType(tyPtr, idgen, objType.owner)
|
||||
result.typ.rawAddSon(objType)
|
||||
|
||||
template checkMagicProcs(g: ModuleGraph, n: PNode, formal: PNode) =
|
||||
@@ -266,9 +266,9 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
|
||||
if argType.kind in {tyVarargs, tyOpenArray}:
|
||||
# important special case: we always create a zero-copy slice:
|
||||
let slice = newNodeI(nkCall, n.info, 4)
|
||||
slice.typ = n.typ
|
||||
slice.typ() = n.typ
|
||||
slice[0] = newSymNode(createMagic(g, idgen, "slice", mSlice))
|
||||
slice[0].typ = getSysType(g, n.info, tyInt) # fake type
|
||||
slice[0].typ() = getSysType(g, n.info, tyInt) # fake type
|
||||
var fieldB = newSym(skField, tmpName, idgen, objType.owner, n.info, g.config.options)
|
||||
fieldB.typ = getSysType(g, n.info, tyInt)
|
||||
discard objType.addField(fieldB, g.cache, idgen)
|
||||
@@ -358,7 +358,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
threadParam = newSym(skParam, getIdent(g.cache, "thread"), idgen, wrapperProc, n.info, g.config.options)
|
||||
argsParam = newSym(skParam, getIdent(g.cache, "args"), idgen, wrapperProc, n.info, g.config.options)
|
||||
|
||||
wrapperProc.incl sfInjectDestructors
|
||||
wrapperProc.flags.incl sfInjectDestructors
|
||||
block:
|
||||
let ptrType = getSysType(g, n.info, tyPointer)
|
||||
threadParam.typ = ptrType
|
||||
@@ -366,13 +366,13 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
argsParam.position = 1
|
||||
|
||||
var objType = createObj(g, idgen, owner, n.info)
|
||||
incl(objType, tfFinal)
|
||||
incl(objType.flags, tfFinal)
|
||||
let castExpr = createCastExpr(argsParam, objType, idgen)
|
||||
|
||||
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), idgen, owner, n.info, g.config.options)
|
||||
block:
|
||||
scratchObj.typ = objType
|
||||
incl(scratchObj.flagsImpl, sfFromGeneric)
|
||||
incl(scratchObj.flags, sfFromGeneric)
|
||||
var varSectionB = newNodeI(nkVarSection, n.info)
|
||||
varSectionB.addVar(scratchObj.newSymNode)
|
||||
result.add varSectionB
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
import prefixmatches, suggestsymdb
|
||||
from wordrecg import wDeprecated, wError, wAddr, wYield
|
||||
|
||||
import std/[algorithm, sets, parseutils, os]
|
||||
import std/[algorithm, sets, parseutils, tables, os]
|
||||
|
||||
when defined(nimsuggest):
|
||||
import pathutils # importer
|
||||
@@ -43,7 +43,7 @@ when defined(nimsuggest):
|
||||
const
|
||||
sep = '\t'
|
||||
|
||||
type
|
||||
type
|
||||
ImportContext = object
|
||||
isMultiImport: bool # True if we're in a [...] context
|
||||
baseDir: string # e.g., "folder/" in "import folder/[..."
|
||||
@@ -356,12 +356,12 @@ proc filterSymNoOpr(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline
|
||||
not isKeyword(s.name)
|
||||
|
||||
proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
|
||||
let fmodule = getModule(f)
|
||||
result = sfExported in f.flags or sameModules(fmodule, c.module)
|
||||
let fmoduleId = getModule(f).id
|
||||
result = sfExported in f.flags or fmoduleId == c.module.id
|
||||
|
||||
if not result:
|
||||
for module in c.friendModules:
|
||||
if sameModules(fmodule, module): return true
|
||||
if fmoduleId == module.id: return true
|
||||
if f.kind == skField:
|
||||
var symObj = f.owner.typ.toObjectFromRefPtrGeneric.sym
|
||||
assert symObj != nil
|
||||
@@ -590,7 +590,7 @@ when defined(nimsuggest):
|
||||
let infoAsInt = info.infoToInt
|
||||
for infoB in s.allUsages:
|
||||
if infoB.infoToInt == infoAsInt: return
|
||||
s.allUsagesImpl.add(info)
|
||||
s.allUsages.add(info)
|
||||
|
||||
proc findUsages(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym) =
|
||||
if g.config.suggestVersion == 1:
|
||||
@@ -707,9 +707,9 @@ proc markOwnerModuleAsUsed(c: PContext; s: PSym) =
|
||||
proc markUsed(c: PContext; info: TLineInfo; s: PSym; checkStyle = true; isGenericInstance = false) =
|
||||
if not isGenericInstance:
|
||||
let conf = c.config
|
||||
incl(s.flagsImpl, sfUsed)
|
||||
incl(s.flags, sfUsed)
|
||||
if s.kind == skEnumField and s.owner != nil:
|
||||
incl(s.owner.flagsImpl, sfUsed)
|
||||
incl(s.owner.flags, sfUsed)
|
||||
if sfDeprecated in s.owner.flags:
|
||||
warnAboutDeprecated(conf, info, s)
|
||||
if {sfDeprecated, sfError} * s.flags != {}:
|
||||
@@ -788,7 +788,7 @@ proc extractImportContextFromAst(n: PNode, cursorCol: int): ImportContext =
|
||||
proc findModuleFile(c: PContext, partialPath: string): seq[string] =
|
||||
result = @[]
|
||||
let currentModuleDir = parentDir(toFullPath(c.config, FileIndex(c.module.position)))
|
||||
|
||||
|
||||
proc tryAddModule(path, baseName: string) =
|
||||
if fileExists(path & ".nim"):
|
||||
result.add(baseName)
|
||||
@@ -800,7 +800,7 @@ proc findModuleFile(c: PContext, partialPath: string): seq[string] =
|
||||
let (_, name, ext) = splitFile(path)
|
||||
if kind == pcFile:
|
||||
if ext == ".nim" and name.startsWith(file):
|
||||
result.add(name)
|
||||
result.add(name)
|
||||
|
||||
proc collectImportModulesFromDir(dir: string, result: var seq[string]) =
|
||||
for kind, path in walkDir(dir):
|
||||
@@ -809,10 +809,10 @@ proc findModuleFile(c: PContext, partialPath: string): seq[string] =
|
||||
if kind == pcFile:
|
||||
if ext == ".nim" and name.startsWith(partialPath):
|
||||
result.add(name)
|
||||
else:
|
||||
else:
|
||||
if name.startsWith(partialPath):
|
||||
result.add(name)
|
||||
|
||||
|
||||
if '/' in partialPath:
|
||||
let parts = partialPath.split('/')
|
||||
let dir = parts[0]
|
||||
@@ -839,13 +839,13 @@ proc suggestModuleNames(c: PContext, n: PNode) =
|
||||
column: n.info.col.int,
|
||||
doc: "",
|
||||
quality: 100,
|
||||
contextFits: true,
|
||||
contextFits: true,
|
||||
prefix: if partialPath.len > 0: prefixMatch(path, partialPath)
|
||||
else: PrefixMatch.None,
|
||||
symkind: byte skModule
|
||||
)
|
||||
suggestions.add(suggest)
|
||||
|
||||
|
||||
let importCtx = extractImportContextFromAst(n, c.config.m.trackPos.col)
|
||||
var searchPath = ""
|
||||
if importCtx.baseDir.len > 0:
|
||||
@@ -901,7 +901,7 @@ proc suggestExprNoCheck*(c: PContext, n: PNode) =
|
||||
if outputs.len > 0 and c.config.ideCmd in {ideSug, ideCon, ideDef}:
|
||||
produceOutput(outputs, c.config)
|
||||
suggestQuit()
|
||||
|
||||
|
||||
proc suggestExpr*(c: PContext, n: PNode) =
|
||||
if exactEquals(c.config.m.trackPos, n.info): suggestExprNoCheck(c, n)
|
||||
|
||||
|
||||
@@ -65,14 +65,16 @@ proc newTransNode(a: PNode): PNode {.inline.} =
|
||||
|
||||
proc newTransNode(kind: TNodeKind, info: TLineInfo,
|
||||
sons: int): PNode {.inline.} =
|
||||
result = newNodeI(kind, info)
|
||||
newSeq(result.sons, sons)
|
||||
var x = newNodeI(kind, info)
|
||||
newSeq(x.sons, sons)
|
||||
result = x
|
||||
|
||||
proc newTransNode(kind: TNodeKind, n: PNode,
|
||||
sons: int): PNode {.inline.} =
|
||||
result = newNodeIT(kind, n.info, n.typ)
|
||||
newSeq(result.sons, sons)
|
||||
# x.flags = n.flags
|
||||
var x = newNodeIT(kind, n.info, n.typ)
|
||||
newSeq(x.sons, sons)
|
||||
# x.flags = n.flags
|
||||
result = x
|
||||
|
||||
proc newTransCon(owner: PSym): PTransCon =
|
||||
assert owner != nil
|
||||
@@ -93,7 +95,7 @@ proc getCurrOwner(c: PTransf): PSym =
|
||||
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), c.idgen, getCurrOwner(c), info)
|
||||
r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
|
||||
incl(r.flagsImpl, sfFromGeneric)
|
||||
incl(r.flags, sfFromGeneric)
|
||||
let owner = getCurrOwner(c)
|
||||
result = newSymNode(r)
|
||||
|
||||
@@ -179,7 +181,7 @@ proc transformSym(c: PTransf, n: PNode): PNode =
|
||||
proc freshVar(c: PTransf; v: PSym): PNode =
|
||||
let owner = getCurrOwner(c)
|
||||
var newVar = copySym(v, c.idgen)
|
||||
incl(newVar.flagsImpl, sfFromGeneric)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
setOwner(newVar, owner)
|
||||
result = newSymNode(newVar)
|
||||
|
||||
@@ -245,7 +247,6 @@ proc hasContinue(n: PNode): bool =
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: result = false
|
||||
of nkContinueStmt: result = true
|
||||
of routineDefs: result = false
|
||||
else:
|
||||
result = false
|
||||
for i in 0..<n.len:
|
||||
@@ -328,7 +329,7 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PNode =
|
||||
if a.kind == nkSym:
|
||||
n[1] = transformSymAux(c, a)
|
||||
return n
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: # todo optimize nosideeffects?
|
||||
of nkProcDef: # todo optimize nosideeffects?
|
||||
result = newTransNode(n)
|
||||
let x = newSymNode(copySym(n[namePos].sym, c.idgen))
|
||||
c.transCon.mapping[n[namePos].sym.itemId] = x
|
||||
@@ -363,7 +364,7 @@ proc transformAsgn(c: PTransf, n: PNode): PNode =
|
||||
# given tuple type
|
||||
newTupleConstr[i] = def[0]
|
||||
|
||||
newTupleConstr.typ = rhs.typ
|
||||
newTupleConstr.typ() = rhs.typ
|
||||
|
||||
let asgnNode = newTransNode(nkAsgn, n.info, 2)
|
||||
asgnNode[0] = transform(c, n[0])
|
||||
@@ -497,9 +498,9 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false)
|
||||
n[0][0] = m[0]
|
||||
result = n[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var m = n[0][1]
|
||||
if m.kind in kinds:
|
||||
@@ -507,9 +508,9 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false)
|
||||
n[0][1] = m[0]
|
||||
result = n[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
else:
|
||||
if n[0].kind in kinds and
|
||||
not (n[0][0].kind == nkSym and n[0][0].sym.kind == skForVar and
|
||||
@@ -518,13 +519,14 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false)
|
||||
n.typ.kind == tyVar and
|
||||
n.typ.skipTypes(abstractVar).kind == tyOpenArray and
|
||||
n[0][0].typ.skipTypes(abstractVar).kind == tyString) and
|
||||
not (isAddr and n.typ.kind == tyVar and n[0][0].typ.kind == tyRef)
|
||||
not (isAddr and n.typ.kind == tyVar and n[0][0].typ.kind == tyRef and
|
||||
n[0][0].kind == nkObjConstr)
|
||||
: # elimination is harmful to `for tuple unpack` because of newTupleAccess
|
||||
# it is also harmful to openArrayLoc (var openArray) for strings
|
||||
# addr ( deref ( x )) --> x
|
||||
result = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode =
|
||||
## Converts 'prc' into '(thunk, nil)' so that it's compatible with
|
||||
@@ -565,7 +567,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
getSysType(c.graph, n.info, tyInt32)
|
||||
else:
|
||||
getSysType(c.graph, n.info, tyInt64)
|
||||
result[0] =
|
||||
result[0] =
|
||||
newTreeIT(n.kind, n.info, n.typ, n[0],
|
||||
newTreeIT(nkConv, n.info, intType,
|
||||
newNodeIT(nkType, n.info, intType), transform(c, n[1]))
|
||||
@@ -610,7 +612,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
#result = transformSons(c, n)
|
||||
result.typ = takeType(n.typ, n[1].typ, c.graph, c.idgen)
|
||||
result.typ() = takeType(n.typ, n[1].typ, c.graph, c.idgen)
|
||||
#echo n.info, " came here and produced ", typeToString(result.typ),
|
||||
# " from ", typeToString(n.typ), " and ", typeToString(n[1].typ)
|
||||
of tyCstring:
|
||||
@@ -638,7 +640,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
result[0] = transform(c, n[1])
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
else:
|
||||
result = transformSons(c, n)
|
||||
of tyObject:
|
||||
@@ -651,7 +653,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
result[0] = transform(c, n[1])
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of tyGenericParam, tyOrdinal:
|
||||
result = transform(c, n[1])
|
||||
# happens sometimes for generated assignments, etc.
|
||||
@@ -794,8 +796,7 @@ proc transformFor(c: PTransf, n: PNode): PNode =
|
||||
addVar(v, copyTree(n[i][j])) # declare new vars
|
||||
else:
|
||||
if n[i].kind == nkSym and isSimpleIteratorVar(c, iter, call, n[i].sym.owner):
|
||||
# IC: review this solution again later
|
||||
incl n[i].sym.flagsImpl, sfCursor
|
||||
incl n[i].sym.flags, sfCursor
|
||||
addVar(v, copyTree(n[i])) # declare new vars
|
||||
stmtList.add(v)
|
||||
|
||||
@@ -828,17 +829,12 @@ proc transformFor(c: PTransf, n: PNode): PNode =
|
||||
elif t.destructor == nil and arg.typ.destructor != nil:
|
||||
t = arg.typ
|
||||
|
||||
if arg.kind in {nkDerefExpr, nkHiddenDeref} and
|
||||
arg[0].typ.skipTypes(abstractInst).kind != tyLent:
|
||||
if arg.kind in {nkDerefExpr, nkHiddenDeref}:
|
||||
# optimizes for `[]` # bug #24093
|
||||
# bug #25251: enforce a copy if the arg is a deref of a lent pointer
|
||||
# since the arg could be a temporary that will go out of scope
|
||||
var temp = newTemp(c, arg[0].typ, formal.info)
|
||||
addVar(v, temp)
|
||||
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg[0], true))
|
||||
let newD = newDeref(temp)
|
||||
newD.typ = t
|
||||
newC.mapping[formal.itemId] = newD
|
||||
newC.mapping[formal.itemId] = newDeref(temp)
|
||||
else:
|
||||
# generate a temporary and produce an assignment statement:
|
||||
var temp = newTemp(c, t, formal.info)
|
||||
@@ -853,7 +849,7 @@ proc transformFor(c: PTransf, n: PNode): PNode =
|
||||
of paViaIndirection:
|
||||
let t = formal.typ
|
||||
let vt = makeVarType(t.owner, t, c.idgen)
|
||||
vt.incl tfVarIsPtr
|
||||
vt.flags.incl tfVarIsPtr
|
||||
var temp = newTemp(c, vt, formal.info)
|
||||
addVar(v, temp)
|
||||
var addrExp = newNodeIT(nkHiddenAddr, formal.info, makeVarType(t.owner, t, c.idgen, tyPtr))
|
||||
@@ -891,7 +887,7 @@ proc transformCase(c: PTransf, n: PNode): PNode =
|
||||
# as an expr
|
||||
let kind = if n.typ != nil: nkIfExpr else: nkIfStmt
|
||||
ifs = newTransNode(kind, it.info, 0)
|
||||
ifs.typ = n.typ
|
||||
ifs.typ() = n.typ
|
||||
ifs.add(e)
|
||||
of nkElse:
|
||||
if ifs == nil: result.add(e)
|
||||
@@ -1025,7 +1021,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode =
|
||||
let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2)
|
||||
convNode[0] = newNodeI(nkEmpty, n.info)
|
||||
convNode[1] = excCall
|
||||
convNode.typ = excTypeNode.typ.toRef(c.idgen)
|
||||
convNode.typ() = excTypeNode.typ.toRef(c.idgen)
|
||||
# -> let exc = ...
|
||||
let identDefs = newTransNode(nkIdentDefs, n[1].info, 3)
|
||||
identDefs[0] = n[0][2]
|
||||
@@ -1085,7 +1081,7 @@ proc transformDerefBlock(c: PTransf, n: PNode): PNode =
|
||||
# We transform (block: x)[] to (block: x[])
|
||||
let e0 = n[0]
|
||||
result = shallowCopy(e0)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
for i in 0 ..< e0.len - 1:
|
||||
result[i] = e0[i]
|
||||
result[e0.len-1] = newTreeIT(nkHiddenDeref, n.info, n.typ, e0[e0.len-1])
|
||||
@@ -1290,7 +1286,7 @@ proc liftDeferAux(n: PNode) =
|
||||
tryStmt.add deferPart
|
||||
n[i] = tryStmt
|
||||
n.sons.setLen(i+1)
|
||||
n.typ = tryStmt.typ
|
||||
n.typ() = tryStmt.typ
|
||||
goOn = true
|
||||
break
|
||||
for i in 0..n.safeLen-1:
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# Implements a table from trees to trees. Does structural equivalence checking.
|
||||
|
||||
import ast, types
|
||||
import ast, astalgo, types
|
||||
|
||||
import std/hashes
|
||||
|
||||
@@ -21,13 +21,20 @@ proc hashTree*(n: PNode): Hash =
|
||||
return
|
||||
result = ord(n.kind)
|
||||
case n.kind
|
||||
of nkEmpty: discard
|
||||
of nkSym: result = result !& n.sym.id
|
||||
of nkIdent: result = result !& n.ident.h
|
||||
of nkCharLit..nkUInt64Lit: result = result !& hash(n.intVal)
|
||||
of nkFloatLit..nkFloat64Lit: result = result !& hash(cast[uint64](n.floatVal))
|
||||
of nkStrLit..nkTripleStrLit: result = result !& hash(n.strVal)
|
||||
of nkType, nkNilLit: result = result !& hash(n.typ.itemId)
|
||||
of nkEmpty, nkNilLit, nkType:
|
||||
discard
|
||||
of nkIdent:
|
||||
result = result !& n.ident.h
|
||||
of nkSym:
|
||||
result = result !& n.sym.id
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if (n.intVal >= low(int)) and (n.intVal <= high(int)):
|
||||
result = result !& int(n.intVal)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
|
||||
result = result !& toInt(n.floatVal)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result = result !& hash(n.strVal)
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
result = result !& hashTree(n[i])
|
||||
@@ -46,6 +53,7 @@ proc treesEquivalent(a, b: PNode; ignoreTypes: bool): bool =
|
||||
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
result = cast[uint64](a.floatVal) == cast[uint64](b.floatVal)
|
||||
#result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||
of nkType, nkNilLit:
|
||||
result = a.typ == b.typ
|
||||
|
||||
@@ -18,8 +18,7 @@ when defined(nimPreviewSlimSystem):
|
||||
|
||||
type
|
||||
TTypeAllowedFlag* = enum
|
||||
taTupField, # field of a tuple
|
||||
taObjField, # field of an object
|
||||
taField,
|
||||
taHeap,
|
||||
taConcept,
|
||||
taIsOpenArray,
|
||||
@@ -70,8 +69,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
result = t
|
||||
elif taIsOpenArray in flags:
|
||||
result = t
|
||||
elif t.kind == tyLent and (((kind != skResult or taObjField in flags) and views notin c.features) or
|
||||
(kind == skParam and {taIsCastable, taObjField, taTupField} * flags == {})): # lent cannot be used as parameters.
|
||||
elif t.kind == tyLent and ((kind != skResult and views notin c.features) or
|
||||
(kind == skParam and {taIsCastable, taField} * flags == {})): # lent cannot be used as parameters.
|
||||
# except in the cast environment and as the field of an object
|
||||
result = t
|
||||
elif isOutParam(t) and kind != skParam:
|
||||
@@ -188,12 +187,12 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
t.baseClass != nil and taIsDefaultField notin flags:
|
||||
result = t
|
||||
else:
|
||||
let flags = flags+{taObjField, taVoid}
|
||||
let flags = flags+{taField, taVoid}
|
||||
result = typeAllowedAux(marker, t.baseClass, kind, c, flags)
|
||||
if result.isNil and t.n != nil:
|
||||
result = typeAllowedNode(marker, t.n, kind, c, flags)
|
||||
of tyTuple:
|
||||
let flags = flags+{taTupField, taVoid}
|
||||
let flags = flags+{taField, taVoid}
|
||||
for a in t.kids:
|
||||
result = typeAllowedAux(marker, a, kind, c, flags)
|
||||
if result != nil: break
|
||||
|
||||
@@ -1,285 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2025 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Based on sighashes.nim but works on astdef directly as we need it in ast2nif.nim.
|
||||
## Also produces more readable names thanks to treemangler.
|
||||
|
||||
import std/assertions
|
||||
|
||||
import "../dist/nimony/src/lib" / [treemangler]
|
||||
import "../dist/nimony/src/gear2" / modnames
|
||||
|
||||
import astdef, idents, options, lineinfos, msgs
|
||||
import ic / [enum2nif]
|
||||
|
||||
# -------------- Module name handling --------------------------------------------
|
||||
|
||||
proc cachedModuleSuffix*(config: ConfigRef; fileIdx: FileIndex): string =
|
||||
## Gets or computes the module suffix for a FileIndex.
|
||||
## For NIF modules, the suffix is already stored in the file info.
|
||||
## For source files, computes it from the path.
|
||||
let fullPath = toFullPath(config, fileIdx)
|
||||
if fileInfoKind(config, fileIdx) == fikNifModule:
|
||||
result = fullPath # Already a suffix
|
||||
else:
|
||||
result = moduleSuffix(fullPath, cast[seq[string]](config.searchPaths))
|
||||
|
||||
proc modname*(module: int; conf: ConfigRef): string =
|
||||
cachedModuleSuffix(conf, module.FileIndex)
|
||||
|
||||
proc modname*(module: PSym; conf: ConfigRef): string =
|
||||
assert module.kindImpl == skModule
|
||||
modname(module.positionImpl, conf)
|
||||
|
||||
# --------------- Type key generation --------------------------------------------
|
||||
|
||||
type
|
||||
ConsiderFlag = enum
|
||||
CoProc
|
||||
CoType
|
||||
CoIgnoreRange
|
||||
CoConsiderOwned
|
||||
CoDistinct
|
||||
CoHashTypeInsideNode
|
||||
|
||||
TypeLoader* = proc (t: PType) {.nimcall.}
|
||||
SymLoader* = proc (s: PSym) {.nimcall.}
|
||||
Context = object
|
||||
m: Mangler
|
||||
tl: TypeLoader
|
||||
sl: SymLoader
|
||||
|
||||
proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef)
|
||||
proc symKey(c: var Context; s: PSym; conf: ConfigRef) =
|
||||
if s.state == Partial:
|
||||
assert c.sl != nil
|
||||
c.sl(s)
|
||||
if sfAnon in s.flagsImpl or s.kindImpl == skGenericParam:
|
||||
c.m.addIdent("´anon")
|
||||
else:
|
||||
var name = s.name.s
|
||||
name.add '.'
|
||||
name.addInt s.disamb
|
||||
|
||||
let it =
|
||||
if s.kindImpl == skModule:
|
||||
s
|
||||
elif s.kindImpl in skProcKinds and sfFromGeneric in s.flagsImpl and s.ownerFieldImpl.kindImpl != skModule:
|
||||
s.ownerFieldImpl.ownerFieldImpl
|
||||
else:
|
||||
s.ownerFieldImpl
|
||||
if it.kindImpl == skModule:
|
||||
name.add '.'
|
||||
name.add modname(it, conf)
|
||||
c.m.addSymbol(name)
|
||||
|
||||
proc treeKey(c: var Context; n: PNode; flags: set[ConsiderFlag]; conf: ConfigRef) =
|
||||
if n == nil:
|
||||
c.m.addEmpty()
|
||||
return
|
||||
|
||||
let k = n.kind
|
||||
case k
|
||||
of nkEmpty, nkNilLit, nkType: discard
|
||||
of nkIdent:
|
||||
c.m.addIdent(n.ident.s)
|
||||
of nkSym:
|
||||
symKey(c, n.sym, conf)
|
||||
if CoHashTypeInsideNode in flags and n.sym.typImpl != nil:
|
||||
typeKey(c, n.sym.typImpl, flags, conf)
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
let v = n.intVal
|
||||
c.m.addIntLit v
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
let v = n.floatVal
|
||||
c.m.addFloatLit v
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
c.m.addStrLit n.strVal
|
||||
else:
|
||||
withTree c.m, toNifTag(k):
|
||||
for i in 0..<n.len: treeKey(c, n[i], flags, conf)
|
||||
|
||||
proc skipModifierB(n: PType): PType {.inline.} =
|
||||
n.sonsImpl[^1]
|
||||
|
||||
proc skipTypesB(t: PType, kinds: TTypeKinds): PType =
|
||||
result = t
|
||||
while result.kind in kinds: result = result.sonsImpl[^1]
|
||||
|
||||
proc isGenericAlias(t: PType): bool =
|
||||
result = t.kind == tyGenericInst and t.skipModifierB.skipTypesB({tyAlias}).kind == tyGenericInst
|
||||
|
||||
proc skipGenericAlias(t: PType): PType =
|
||||
result = t.skipTypesB({tyAlias})
|
||||
if result.isGenericAlias:
|
||||
result = result.skipModifierB.skipTypesB({tyAlias})
|
||||
|
||||
proc maybeImported(c: var Context; s: PSym; conf: ConfigRef) {.inline.} =
|
||||
if s != nil and {sfImportc, sfExportc} * s.flagsImpl != {}:
|
||||
c.symKey(s, conf)
|
||||
|
||||
proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) =
|
||||
if t == nil:
|
||||
c.m.addEmpty()
|
||||
return
|
||||
|
||||
if t.state == Partial:
|
||||
assert c.tl != nil
|
||||
c.tl(t)
|
||||
|
||||
case t.kind
|
||||
of tyGenericInvocation:
|
||||
for a in t.sonsImpl:
|
||||
c.typeKey a, flags, conf
|
||||
of tyDistinct:
|
||||
if CoDistinct in flags:
|
||||
if t.symImpl != nil: symKey(c, t.symImpl, conf)
|
||||
if t.symImpl == nil or tfFromGeneric in t.flagsImpl:
|
||||
c.typeKey t.sonsImpl[^1], flags, conf
|
||||
elif CoType in flags or t.symImpl == nil:
|
||||
c.typeKey t.sonsImpl[^1], flags, conf
|
||||
else:
|
||||
symKey(c, t.symImpl, conf)
|
||||
of tyGenericInst:
|
||||
if sfInfixCall in t.sonsImpl[0].symImpl.flagsImpl:
|
||||
# This is an imported C++ generic type.
|
||||
# We cannot trust the `lastSon` to hold a properly populated and unique
|
||||
# value for each instantiation, so we hash the generic parameters here:
|
||||
let normalizedType = t.skipGenericAlias
|
||||
c.typeKey normalizedType.sonsImpl[0], flags, conf
|
||||
for i in 1..<t.sonsImpl.len-1:
|
||||
c.typeKey t.sonsImpl[i], flags, conf
|
||||
else:
|
||||
c.typeKey t.skipModifierB, flags, conf
|
||||
of tyAlias, tySink, tyUserTypeClasses, tyInferred:
|
||||
c.typeKey t.skipModifierB, flags, conf
|
||||
of tyOwned:
|
||||
if CoConsiderOwned in flags:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
c.typeKey t.skipModifierB, flags, conf
|
||||
else:
|
||||
c.typeKey t.skipModifierB, flags, conf
|
||||
of tyBool:
|
||||
withTree c.m, "bool":
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyChar:
|
||||
withTree c.m, "c":
|
||||
c.m.addIntLit 8 # char is always 8 bits
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyInt:
|
||||
withTree c.m, "i":
|
||||
c.m.addIntLit -1
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyInt8:
|
||||
withTree c.m, "i":
|
||||
c.m.addIntLit 8
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyInt16:
|
||||
withTree c.m, "i":
|
||||
c.m.addIntLit 16
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyInt32:
|
||||
withTree c.m, "i":
|
||||
c.m.addIntLit 32
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyInt64:
|
||||
withTree c.m, "i":
|
||||
c.m.addIntLit 64
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyUInt:
|
||||
withTree c.m, "u":
|
||||
c.m.addIntLit -1
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyUInt8:
|
||||
withTree c.m, "u":
|
||||
c.m.addIntLit 8
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyUInt16:
|
||||
withTree c.m, "u":
|
||||
c.m.addIntLit 16
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyUInt32:
|
||||
withTree c.m, "u":
|
||||
c.m.addIntLit 32
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyUInt64:
|
||||
withTree c.m, "u":
|
||||
c.m.addIntLit 64
|
||||
maybeImported(c, t.symImpl, conf)
|
||||
of tyObject, tyEnum:
|
||||
if t.typeInstImpl != nil:
|
||||
# prevent against infinite recursions here, see bug #8883:
|
||||
let inst = t.typeInstImpl
|
||||
t.typeInstImpl = nil # IC: spurious writes are ok since we set it back immediately
|
||||
assert inst.kind == tyGenericInst
|
||||
c.typeKey inst.sonsImpl[0], flags, conf
|
||||
for i in 1..<inst.sonsImpl.len-1:
|
||||
c.typeKey inst.sonsImpl[i], flags, conf
|
||||
t.typeInstImpl = inst
|
||||
elif t.symImpl != nil:
|
||||
c.symKey(t.symImpl, conf)
|
||||
else:
|
||||
c.m.addIdent "`bug"
|
||||
of tyFromExpr:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
c.treeKey(t.nImpl, flags, conf)
|
||||
of tyTuple:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
if t.nImpl != nil and CoType notin flags:
|
||||
for i in 0..<t.nImpl.len:
|
||||
withTree c.m, "kv":
|
||||
assert(t.nImpl[i].kind == nkSym)
|
||||
c.symKey(t.nImpl[i].sym, conf)
|
||||
c.typeKey(t.nImpl[i].sym.typImpl, flags+{CoIgnoreRange}, conf)
|
||||
else:
|
||||
for i in 1..<t.sonsImpl.len:
|
||||
c.typeKey t.sonsImpl[i], flags+{CoIgnoreRange}, conf
|
||||
of tyRange:
|
||||
if CoIgnoreRange notin flags:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
c.treeKey(t.nImpl, {}, conf)
|
||||
c.typeKey(t.sonsImpl[^1], flags, conf)
|
||||
else:
|
||||
c.typeKey(t.sonsImpl[^1], flags, conf)
|
||||
of tyStatic:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
c.treeKey(t.nImpl, {}, conf)
|
||||
if t.sonsImpl.len > 0:
|
||||
c.typeKey(t.skipModifierB, flags, conf)
|
||||
of tyProc:
|
||||
withTree c.m, (if tfIterator in t.flagsImpl: "itertype" else: "proctype"):
|
||||
if CoProc in flags and t.nImpl != nil:
|
||||
let params = t.nImpl
|
||||
for i in 1..<params.len:
|
||||
let param = params[i].sym
|
||||
c.symKey(param, conf)
|
||||
c.typeKey(param.typImpl, flags, conf)
|
||||
else:
|
||||
for i in 1..<t.sonsImpl.len:
|
||||
c.typeKey(t.sonsImpl[i], flags, conf)
|
||||
if t.sonsImpl.len > 0:
|
||||
c.typeKey(t.sonsImpl[0], flags, conf)
|
||||
|
||||
c.m.addIdent toNifTag(t.callConvImpl)
|
||||
if tfVarargs in t.flagsImpl: c.m.addIdent "´varargs"
|
||||
of tyArray:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
c.typeKey(t.sonsImpl[^1], flags-{CoIgnoreRange}, conf)
|
||||
c.typeKey(t.sonsImpl[0], flags-{CoIgnoreRange}, conf)
|
||||
else:
|
||||
withTree c.m, toNifTag(t.kind):
|
||||
for i in 1..<t.sonsImpl.len:
|
||||
c.typeKey t.sonsImpl[i], flags, conf
|
||||
if tfNotNil in t.flagsImpl and CoType notin flags:
|
||||
c.m.addIdent "´notnil"
|
||||
|
||||
proc typeKey*(t: PType; conf: ConfigRef; tl: TypeLoader; sl: SymLoader): string =
|
||||
var c: Context = Context(m: createMangler(30, -1), tl: tl, sl: sl)
|
||||
typeKey(c, t, {}, conf)
|
||||
result = c.m.extract()
|
||||
@@ -102,7 +102,7 @@ const
|
||||
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
|
||||
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
||||
typedescInst* = abstractInst + {tyTypeDesc, tyOwned, tyUserTypeClass}
|
||||
|
||||
|
||||
# incorrect definition of `[]` and `[]=` for these types in system.nim
|
||||
arrPutGetMagicApplies* = {tyArray, tyOpenArray, tyString, tySequence, tyCstring, tyTuple}
|
||||
|
||||
@@ -498,7 +498,7 @@ const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
|
||||
|
||||
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
|
||||
tc.add concrete
|
||||
tc.incl tfResolved
|
||||
tc.flags.incl tfResolved
|
||||
|
||||
# TODO: It would be a good idea to kill the special state of a resolved
|
||||
# concept by switching to tyAlias within the instantiated procs.
|
||||
@@ -1238,7 +1238,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||
x + {tyRange}
|
||||
else:
|
||||
x
|
||||
|
||||
|
||||
template withoutShallowFlags(body) =
|
||||
let oldFlags = c.flags
|
||||
c.flags.excl IgnoreRangeShallow
|
||||
@@ -1744,7 +1744,7 @@ proc skipHidden*(n: PNode): PNode =
|
||||
|
||||
proc skipConvTakeType*(n: PNode): PNode =
|
||||
result = n.skipConv
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc isEmptyContainer*(t: PType): bool =
|
||||
case t.kind
|
||||
@@ -1784,7 +1784,7 @@ proc skipHiddenSubConv*(n: PNode; g: ModuleGraph; idgen: IdGenerator): PNode =
|
||||
result = n
|
||||
else:
|
||||
result = copyTree(result)
|
||||
result.typ = dest
|
||||
result.typ() = dest
|
||||
else:
|
||||
result = n
|
||||
|
||||
@@ -2014,7 +2014,7 @@ proc nominalRoot*(t: PType): PType =
|
||||
## i.e. the type directly associated with the symbol where the root
|
||||
## nominal type of `t` was defined, skipping things like generic instances,
|
||||
## aliases, `var`/`sink`/`typedesc` modifiers
|
||||
##
|
||||
##
|
||||
## instead of returning the uninstantiated body of a generic type,
|
||||
## returns the type of the symbol instead (with tyGenericBody type)
|
||||
result = nil
|
||||
|
||||
@@ -1014,6 +1014,6 @@ proc computeCursors*(s: PSym; n: PNode; g: ModuleGraph) =
|
||||
if par.s[rid].con.kind == isRootOf and dangerousMutation(par.graphs[par.s[rid].con.graphIndex], par.s[i]):
|
||||
discard "cannot cursor into a graph that is mutated"
|
||||
else:
|
||||
v.sym.flagsImpl.incl sfCursor
|
||||
v.sym.flags.incl sfCursor
|
||||
when false:
|
||||
echo "this is now a cursor ", v.sym, " ", par.s[rid].flags, " ", g.config $ v.sym.info
|
||||
|
||||
@@ -202,7 +202,7 @@ proc copyValue(src: PNode): PNode =
|
||||
return src
|
||||
result = newNode(src.kind)
|
||||
result.info = src.info
|
||||
result.typ = src.typ
|
||||
result.typ() = src.typ
|
||||
result.flags = src.flags * PersistentNodeFlags
|
||||
result.comment = src.comment
|
||||
when defined(useNodeIds):
|
||||
@@ -480,9 +480,9 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
|
||||
else:
|
||||
asgnComplex(dest, src)
|
||||
|
||||
proc compile(c: PCtx, s: PSym): VmProcInfo =
|
||||
proc compile(c: PCtx, s: PSym): int =
|
||||
result = vmgen.genProc(c, s)
|
||||
when debugEchoCode: c.echoCode result.pc
|
||||
when debugEchoCode: c.echoCode result
|
||||
#c.echoCode
|
||||
|
||||
template handleJmpBack() {.dirty.} =
|
||||
@@ -859,9 +859,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
of opcLdObj:
|
||||
# a = b.c
|
||||
decodeBC(rkNode)
|
||||
if rb >= regs.len or regs[rb].kind == rkNone or
|
||||
if rb >= regs.len or regs[rb].kind == rkNone or
|
||||
(regs[rb].kind == rkNode and regs[rb].node == nil) or
|
||||
(regs[rb].kind == rkNodeAddr and regs[rb].nodeAddr[] == nil):
|
||||
(regs[rb].kind == rkNodeAddr and regs[rb].nodeAddr[] == nil):
|
||||
stackTrace(c, tos, pc, errNilAccess)
|
||||
else:
|
||||
let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[]
|
||||
@@ -1435,23 +1435,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
else:
|
||||
globalError(c.config, c.debug[pc], "VM not built with FFI support")
|
||||
elif prc.kind != skTemplate:
|
||||
let procInfo = compile(c, prc)
|
||||
let newPc = compile(c, prc)
|
||||
# tricky: a recursion is also a jump back, so we use the same
|
||||
# logic as for loops:
|
||||
if procInfo.pc < pc: handleJmpBack()
|
||||
if newPc < pc: handleJmpBack()
|
||||
#echo "new pc ", newPc, " calling: ", prc.name.s
|
||||
var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
|
||||
newSeq(newFrame.slots, procInfo.usedRegisters+ord(isClosure))
|
||||
# setup slot for proc result:
|
||||
let ret {.cursor.} = prc.typ.returnType
|
||||
# hot spot ahead!
|
||||
if ret != nil:
|
||||
if fitsRegister(ret):
|
||||
# same logic as opcLdNullReg here:
|
||||
ensureKind(newFrame.slots[0], rkInt)
|
||||
newFrame.slots[0].intVal = 0
|
||||
elif not isEmptyType(ret):
|
||||
putIntoReg(newFrame.slots[0], getNullValue(c, ret, prc.info, c.config))
|
||||
newSeq(newFrame.slots, prc.offset+ord(isClosure))
|
||||
if not isEmptyType(prc.typ.returnType):
|
||||
putIntoReg(newFrame.slots[0], getNullValue(c, prc.typ.returnType, prc.info, c.config))
|
||||
for i in 1..rc-1:
|
||||
newFrame.slots[i] = regs[rb+i]
|
||||
if isClosure:
|
||||
@@ -1467,7 +1459,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
tos = newFrame
|
||||
updateRegsAlias
|
||||
# -1 for the following 'inc pc'
|
||||
pc = procInfo.pc-1
|
||||
pc = newPc-1
|
||||
else:
|
||||
# for 'getAst' support we need to support template expansion here:
|
||||
let genSymOwner = if tos.next != nil and tos.next.prc != nil:
|
||||
@@ -1480,8 +1472,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let node = regs[rb+i].regToNode
|
||||
node.info = c.debug[pc]
|
||||
if prc.typ[i].kind notin {tyTyped, tyUntyped}:
|
||||
var producedClosure = false
|
||||
node.annotateType(prc.typ[i], c.config, producedClosure)
|
||||
node.annotateType(prc.typ[i], c.config)
|
||||
|
||||
macroCall.add(node)
|
||||
var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter, c.idgen)
|
||||
@@ -1557,10 +1548,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
# Set the `name` field of the exception
|
||||
var exceptionNameNode = newStrNode(nkStrLit, c.currentExceptionA.typ.sym.name.s)
|
||||
if c.currentExceptionA[2].kind == nkExprColonExpr:
|
||||
exceptionNameNode.typ = c.currentExceptionA[2][1].typ
|
||||
exceptionNameNode.typ() = c.currentExceptionA[2][1].typ
|
||||
c.currentExceptionA[2][1] = exceptionNameNode
|
||||
else:
|
||||
exceptionNameNode.typ = c.currentExceptionA[2].typ
|
||||
exceptionNameNode.typ() = c.currentExceptionA[2].typ
|
||||
c.currentExceptionA[2] = exceptionNameNode
|
||||
c.exceptionInstr = pc
|
||||
|
||||
@@ -1602,7 +1593,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let instr2 = c.code[pc]
|
||||
let count = regs[instr2.regA].intVal.int
|
||||
regs[ra].node = newNodeI(nkBracket, c.debug[pc])
|
||||
regs[ra].node.typ = typ
|
||||
regs[ra].node.typ() = typ
|
||||
newSeq(regs[ra].node.sons, count)
|
||||
for i in 0..<count:
|
||||
regs[ra].node[i] = getNullValue(c, typ.elementType, c.debug[pc], c.config)
|
||||
@@ -1723,12 +1714,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let max = (1.BiggestInt shl (rb-1))-1
|
||||
if regs[ra].intVal < min or regs[ra].intVal > max:
|
||||
stackTrace(c, tos, pc, "unhandled exception: value out of range")
|
||||
of opcNarrowR:
|
||||
decodeBC(rkInt)
|
||||
let min = regs[rb].intVal
|
||||
let max = regs[rc].intVal
|
||||
if regs[ra].intVal < min or regs[ra].intVal > max:
|
||||
stackTrace(c, tos, pc, "unhandled exception: value out of range")
|
||||
of opcNarrowU:
|
||||
decodeB(rkInt)
|
||||
regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
|
||||
@@ -1837,6 +1822,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
case a.kind
|
||||
of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
|
||||
of opcNSymbol:
|
||||
decodeB(rkNode)
|
||||
let a = regs[rb].node
|
||||
if a.kind == nkSym:
|
||||
regs[ra].node = copyNode(a)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
|
||||
of opcNIdent:
|
||||
decodeB(rkNode)
|
||||
let a = regs[rb].node
|
||||
if a.kind == nkIdent:
|
||||
regs[ra].node = copyNode(a)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "ident")
|
||||
of opcNodeId:
|
||||
decodeB(rkInt)
|
||||
when defined(useNodeIds):
|
||||
@@ -2018,7 +2017,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
else:
|
||||
internalAssert c.config, false
|
||||
regs[ra].node.info = n.info
|
||||
regs[ra].node.typ = n.typ
|
||||
regs[ra].node.typ() = n.typ
|
||||
of opcNCopyLineInfo:
|
||||
decodeB(rkNode)
|
||||
regs[ra].node.info = regs[rb].node.info
|
||||
@@ -2098,7 +2097,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
ensureKind(rkNode)
|
||||
regs[ra].node = temp
|
||||
regs[ra].node.info = c.debug[pc]
|
||||
regs[ra].node.typ = typ
|
||||
regs[ra].node.typ() = typ
|
||||
of opcConv:
|
||||
let rb = instr.regB
|
||||
inc pc
|
||||
@@ -2142,6 +2141,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
dest.floatVal = regs[rb].floatVal
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
|
||||
of opcNSetSymbol:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
if dest.kind == nkSym and regs[rb].node.kind == nkSym:
|
||||
dest.sym = regs[rb].node.sym
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
|
||||
of opcNSetIdent:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
|
||||
dest.ident = regs[rb].node.ident
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "ident")
|
||||
of opcNSetStrVal:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
@@ -2192,7 +2205,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
if k < 0 or k > ord(high(TSymKind)):
|
||||
internalError(c.config, c.debug[pc], "request to create symbol of invalid kind")
|
||||
var sym = newSym(k.TSymKind, getIdent(c.cache, name), c.idgen, c.module.owner, c.debug[pc])
|
||||
incl(sym.flagsImpl, sfGenSym)
|
||||
incl(sym.flags, sfGenSym)
|
||||
regs[ra].node = newSymNode(sym)
|
||||
regs[ra].node.flags.incl nfIsRef
|
||||
of opcNccValue:
|
||||
@@ -2329,7 +2342,8 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
let start = genProc(c, sym)
|
||||
|
||||
var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
|
||||
newSeq(tos.slots, start.usedRegisters)
|
||||
let maxSlots = sym.offset
|
||||
newSeq(tos.slots, maxSlots)
|
||||
|
||||
# setup parameters:
|
||||
if not isEmptyType(sym.typ.returnType) or sym.kind == skMacro:
|
||||
@@ -2338,7 +2352,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
for i in 0..<sym.typ.paramsLen:
|
||||
putIntoReg(tos.slots[i+1], args[i])
|
||||
|
||||
result = rawExecute(c, start.pc, tos).regToNode
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
else:
|
||||
result = nil
|
||||
localError(c.config, sym.info,
|
||||
@@ -2346,8 +2360,8 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
|
||||
proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.typ = newType(tyError, idgen, owner)
|
||||
result.typ.incl tfCheckedForDestructor
|
||||
result.typ() = newType(tyError, idgen, owner)
|
||||
result.typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc evalStmt*(c: PCtx, n: PNode) =
|
||||
let n = transformExpr(c.graph, c.idgen, c.module, n)
|
||||
@@ -2484,7 +2498,7 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg =
|
||||
var n = x
|
||||
if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n[1]
|
||||
n.flags.incl nfIsRef
|
||||
n.typ = x.typ
|
||||
n.typ() = x.typ
|
||||
result = TFullReg(kind: rkNode, node: n)
|
||||
|
||||
iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
|
||||
@@ -2527,7 +2541,8 @@ proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstC
|
||||
return errorNode(idgen, module, n)
|
||||
|
||||
var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
|
||||
newSeq(tos.slots, start.usedRegisters)
|
||||
let maxSlots = sym.offset
|
||||
newSeq(tos.slots, maxSlots)
|
||||
# setup arguments:
|
||||
var L = n.safeLen
|
||||
if L == 0: L = 1
|
||||
@@ -2554,7 +2569,7 @@ proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstC
|
||||
" generic parameter(s)")
|
||||
# temporary storage:
|
||||
#for i in L..<maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start.pc, tos).regToNode
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
if result.info.line < 0: result.info = n.info
|
||||
if cyclicTree(result): globalError(c.config, n.info, "macro produced a cyclic tree")
|
||||
dec(g.config.evalMacroCounter)
|
||||
|
||||
@@ -105,7 +105,7 @@ type
|
||||
opcIsNil, opcOf, opcIs,
|
||||
opcParseFloat, opcConv, opcCast,
|
||||
opcQuit, opcInvalidField,
|
||||
opcNarrowS, opcNarrowU, opcNarrowR
|
||||
opcNarrowS, opcNarrowU,
|
||||
opcSignExtend,
|
||||
|
||||
opcAddStrCh,
|
||||
@@ -119,13 +119,15 @@ type
|
||||
opcNSymKind,
|
||||
opcNIntVal,
|
||||
opcNFloatVal,
|
||||
opcNSymbol,
|
||||
opcNIdent,
|
||||
opcNGetType,
|
||||
opcNStrVal,
|
||||
opcNSigHash,
|
||||
opcNGetSize,
|
||||
|
||||
opcNSetIntVal,
|
||||
opcNSetFloatVal, opcNSetStrVal,
|
||||
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetStrVal,
|
||||
opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym,
|
||||
|
||||
opcNccValue, opcNccInc, opcNcsAdd, opcNcsIncl, opcNcsLen, opcNcsAt,
|
||||
@@ -241,11 +243,6 @@ type
|
||||
VmCallback* = proc (args: VmArgs) {.closure.}
|
||||
|
||||
PCtx* = ref TCtx
|
||||
|
||||
VmProcInfo* = object
|
||||
pc*: int32
|
||||
usedRegisters*: int32
|
||||
|
||||
TCtx* = object of TPassContext # code gen context
|
||||
code*: seq[TInstr]
|
||||
debug*: seq[TLineInfo] # line info for every instruction; kept separate
|
||||
@@ -274,7 +271,7 @@ type
|
||||
profiler*: Profiler
|
||||
templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst
|
||||
vmstateDiff*: seq[(PSym, PNode)] # we remember the "diff" to global state here (feature for IC)
|
||||
procToCodePos*: Table[int, VmProcInfo]
|
||||
procToCodePos*: Table[int, int]
|
||||
cannotEval*: bool
|
||||
locals*: IntSet
|
||||
|
||||
@@ -296,9 +293,6 @@ type
|
||||
|
||||
PEvalContext* = PCtx
|
||||
|
||||
const
|
||||
NoVmProcInfo* = VmProcInfo(pc: 0'i32, usedRegisters: -1'i32)
|
||||
|
||||
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator): PCtx =
|
||||
PCtx(code: @[], debug: @[],
|
||||
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user