much more efficient rod file generation
This commit is contained in:
parent
0914ba8980
commit
4de84024e5
18 changed files with 611 additions and 557 deletions
|
|
@ -10,7 +10,8 @@
|
||||||
# abstract syntax tree + symbol table
|
# abstract syntax tree + symbol table
|
||||||
|
|
||||||
import
|
import
|
||||||
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, intsets
|
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
|
||||||
|
intsets, idgen
|
||||||
|
|
||||||
const
|
const
|
||||||
ImportTablePos* = 0
|
ImportTablePos* = 0
|
||||||
|
|
@ -377,7 +378,6 @@ type
|
||||||
|
|
||||||
type
|
type
|
||||||
PNode* = ref TNode
|
PNode* = ref TNode
|
||||||
PNodePtr* = ptr PNode
|
|
||||||
TNodeSeq* = seq[PNode]
|
TNodeSeq* = seq[PNode]
|
||||||
PType* = ref TType
|
PType* = ref TType
|
||||||
PSym* = ref TSym
|
PSym* = ref TSym
|
||||||
|
|
@ -577,12 +577,6 @@ const
|
||||||
resultPos* = 5
|
resultPos* = 5
|
||||||
dispatcherPos* = 6
|
dispatcherPos* = 6
|
||||||
|
|
||||||
var gId*: int
|
|
||||||
|
|
||||||
proc getID*(): int {.inline.}
|
|
||||||
proc setID*(id: int) {.inline.}
|
|
||||||
proc IDsynchronizationPoint*(idRange: int)
|
|
||||||
|
|
||||||
# creator procs:
|
# creator procs:
|
||||||
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym
|
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym
|
||||||
proc NewType*(kind: TTypeKind, owner: PSym): PType
|
proc NewType*(kind: TTypeKind, owner: PSym): PType
|
||||||
|
|
@ -660,27 +654,6 @@ proc leValue*(a, b: PNode): bool
|
||||||
# a <= b? a, b are literals
|
# a <= b? a, b are literals
|
||||||
proc ValueToString*(a: PNode): string
|
proc ValueToString*(a: PNode): string
|
||||||
|
|
||||||
const
|
|
||||||
debugIds* = false
|
|
||||||
|
|
||||||
when debugIds:
|
|
||||||
var usedIds: TIntSet
|
|
||||||
|
|
||||||
proc registerID*(id: PIdObj) =
|
|
||||||
when debugIDs:
|
|
||||||
if (id.id == - 1) or ContainsOrIncl(usedIds, id.id):
|
|
||||||
InternalError("ID already used: " & $(id.id))
|
|
||||||
|
|
||||||
proc getID(): int =
|
|
||||||
result = gId
|
|
||||||
inc(gId)
|
|
||||||
|
|
||||||
proc setId(id: int) =
|
|
||||||
gId = max(gId, id + 1)
|
|
||||||
|
|
||||||
proc IDsynchronizationPoint(idRange: int) =
|
|
||||||
gId = (gId div IdRange + 1) * IdRange + 1
|
|
||||||
|
|
||||||
proc leValue(a, b: PNode): bool =
|
proc leValue(a, b: PNode): bool =
|
||||||
# a <= b?
|
# a <= b?
|
||||||
result = false
|
result = false
|
||||||
|
|
@ -1032,4 +1005,3 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
internalError(a.info, "getStrOrChar")
|
internalError(a.info, "getStrOrChar")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
when debugIDs: usedIds = InitIntSet()
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ proc genHexLiteral(v: PNode): PRope =
|
||||||
|
|
||||||
proc getStrLit(m: BModule, s: string): PRope =
|
proc getStrLit(m: BModule, s: string): PRope =
|
||||||
discard cgsym(m, "TGenericSeq")
|
discard cgsym(m, "TGenericSeq")
|
||||||
result = con("TMP", toRope(getID()))
|
result = con("TMP", toRope(backendId()))
|
||||||
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
|
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
|
||||||
[result, makeCString(s), ToRope(len(s))])
|
[result, makeCString(s), ToRope(len(s))])
|
||||||
|
|
||||||
|
|
@ -70,8 +70,8 @@ proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
|
||||||
result = toRope("NIM_NIL")
|
result = toRope("NIM_NIL")
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if skipTypes(ty, abstractVarRange).kind == tyString:
|
if skipTypes(ty, abstractVarRange).kind == tyString:
|
||||||
var id = NodeTableTestOrSet(p.module.dataCache, v, gid)
|
var id = NodeTableTestOrSet(p.module.dataCache, v, gBackendId)
|
||||||
if id == gid:
|
if id == gBackendId:
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
result = ropecg(p.module, "((#NimStringDesc*) &$1)",
|
result = ropecg(p.module, "((#NimStringDesc*) &$1)",
|
||||||
[getStrLit(p.module, v.strVal)])
|
[getStrLit(p.module, v.strVal)])
|
||||||
|
|
@ -123,11 +123,11 @@ proc genSetNode(p: BProc, n: PNode): PRope =
|
||||||
var size = int(getSize(n.typ))
|
var size = int(getSize(n.typ))
|
||||||
toBitSet(n, cs)
|
toBitSet(n, cs)
|
||||||
if size > 8:
|
if size > 8:
|
||||||
var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
|
var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||||
result = con("TMP", toRope(id))
|
result = con("TMP", toRope(id))
|
||||||
if id == gid:
|
if id == gBackendId:
|
||||||
# not found in cache:
|
# not found in cache:
|
||||||
inc(gid)
|
inc(gBackendId)
|
||||||
appf(p.module.s[cfsData], "static NIM_CONST $1 $2 = $3;$n",
|
appf(p.module.s[cfsData], "static NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, n.typ), result, genRawSetData(cs, size)])
|
[getTypeDesc(p.module, n.typ), result, genRawSetData(cs, size)])
|
||||||
else:
|
else:
|
||||||
|
|
@ -618,8 +618,8 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
v.r = ropef("$1.$2", [r, it.sons[2].sym.loc.r])
|
v.r = ropef("$1.$2", [r, it.sons[2].sym.loc.r])
|
||||||
genInExprAux(p, it, u, v, test)
|
genInExprAux(p, it, u, v, test)
|
||||||
id = NodeTableTestOrSet(p.module.dataCache,
|
id = NodeTableTestOrSet(p.module.dataCache,
|
||||||
newStrNode(nkStrLit, field.name.s), gid)
|
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||||
if id == gid: strLit = getStrLit(p.module, field.name.s)
|
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
|
||||||
else: strLit = con("TMP", toRope(id))
|
else: strLit = con("TMP", toRope(id))
|
||||||
if op.magic == mNot:
|
if op.magic == mNot:
|
||||||
appcg(p, cpsStmts,
|
appcg(p, cpsStmts,
|
||||||
|
|
@ -1581,11 +1581,11 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||||
if (nfAllConst in n.flags) and (d.k == locNone) and (sonsLen(n) > 0):
|
if (nfAllConst in n.flags) and (d.k == locNone) and (sonsLen(n) > 0):
|
||||||
var t = getUniqueType(n.typ)
|
var t = getUniqueType(n.typ)
|
||||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||||
var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
|
var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||||
fillLoc(d, locData, t, con("TMP", toRope(id)), OnHeap)
|
fillLoc(d, locData, t, con("TMP", toRope(id)), OnHeap)
|
||||||
if id == gid:
|
if id == gBackendId:
|
||||||
# expression not found in the cache:
|
# expression not found in the cache:
|
||||||
inc(gid)
|
inc(gBackendId)
|
||||||
appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
|
[getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -145,12 +145,10 @@ proc CacheGetType(tab: TIdTable, key: PType): PRope =
|
||||||
result = PRope(IdTableGet(tab, key))
|
result = PRope(IdTableGet(tab, key))
|
||||||
|
|
||||||
proc getTempName(): PRope =
|
proc getTempName(): PRope =
|
||||||
result = ropeff("TMP$1", "%TMP$1", [toRope(gId)])
|
result = ropeff("TMP$1", "%TMP$1", [toRope(backendId())])
|
||||||
inc(gId)
|
|
||||||
|
|
||||||
proc getGlobalTempName(): PRope =
|
proc getGlobalTempName(): PRope =
|
||||||
result = ropeff("TMP$1", "@TMP$1", [toRope(gId)])
|
result = ropeff("TMP$1", "@TMP$1", [toRope(backendId())])
|
||||||
inc(gId)
|
|
||||||
|
|
||||||
proc ccgIntroducedPtr(s: PSym): bool =
|
proc ccgIntroducedPtr(s: PSym): bool =
|
||||||
var pt = skipTypes(s.typ, abstractInst)
|
var pt = skipTypes(s.typ, abstractInst)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import
|
||||||
options, intsets,
|
options, intsets,
|
||||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||||
rodutils, renderer
|
rodutils, renderer, idgen
|
||||||
|
|
||||||
when options.hasTinyCBackend:
|
when options.hasTinyCBackend:
|
||||||
import tccgen
|
import tccgen
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Identifier handling
|
# Identifier handling
|
||||||
# An identifier is a shared non-modifiable string that can be compared by its
|
# An identifier is a shared immutable string that can be compared by its
|
||||||
# id. This module is essential for the compiler's performance.
|
# id. This module is essential for the compiler's performance.
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -25,35 +25,20 @@ type
|
||||||
next*: PIdent # for hash-table chaining
|
next*: PIdent # for hash-table chaining
|
||||||
h*: THash # hash value of s
|
h*: THash # hash value of s
|
||||||
|
|
||||||
|
|
||||||
proc getIdent*(identifier: string): PIdent
|
|
||||||
proc getIdent*(identifier: string, h: THash): PIdent
|
|
||||||
proc getIdent*(identifier: cstring, length: int, h: THash): PIdent
|
|
||||||
# special version for the scanner; the scanner's buffering scheme makes
|
|
||||||
# this horribly efficient. Most of the time no character copying is needed!
|
|
||||||
proc IdentEq*(id: PIdent, name: string): bool
|
|
||||||
# implementation
|
|
||||||
|
|
||||||
proc IdentEq(id: PIdent, name: string): bool =
|
|
||||||
result = id.id == getIdent(name).id
|
|
||||||
|
|
||||||
var buckets: array[0..4096 * 2 - 1, PIdent]
|
var buckets: array[0..4096 * 2 - 1, PIdent]
|
||||||
|
|
||||||
proc cmpIgnoreStyle(a, b: cstring, blen: int): int =
|
proc cmpIgnoreStyle(a, b: cstring, blen: int): int =
|
||||||
var
|
var i = 0
|
||||||
aa, bb: char
|
var j = 0
|
||||||
i, j: int
|
|
||||||
i = 0
|
|
||||||
j = 0
|
|
||||||
result = 1
|
result = 1
|
||||||
while j < blen:
|
while j < blen:
|
||||||
while a[i] == '_': inc(i)
|
while a[i] == '_': inc(i)
|
||||||
while b[j] == '_': inc(j)
|
while b[j] == '_': inc(j)
|
||||||
# tolower inlined:
|
# tolower inlined:
|
||||||
aa = a[i]
|
var aa = a[i]
|
||||||
bb = b[j]
|
var bb = b[j]
|
||||||
if (aa >= 'A') and (aa <= 'Z'): aa = chr(ord(aa) + (ord('a') - ord('A')))
|
if aa >= 'A' and aa <= 'Z': aa = chr(ord(aa) + (ord('a') - ord('A')))
|
||||||
if (bb >= 'A') and (bb <= 'Z'): bb = chr(ord(bb) + (ord('a') - ord('A')))
|
if bb >= 'A' and bb <= 'Z': bb = chr(ord(bb) + (ord('a') - ord('A')))
|
||||||
result = ord(aa) - ord(bb)
|
result = ord(aa) - ord(bb)
|
||||||
if (result != 0) or (aa == '\0'): break
|
if (result != 0) or (aa == '\0'): break
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
@ -62,15 +47,12 @@ proc cmpIgnoreStyle(a, b: cstring, blen: int): int =
|
||||||
if a[i] != '\0': result = 1
|
if a[i] != '\0': result = 1
|
||||||
|
|
||||||
proc cmpExact(a, b: cstring, blen: int): int =
|
proc cmpExact(a, b: cstring, blen: int): int =
|
||||||
var
|
var i = 0
|
||||||
aa, bb: char
|
var j = 0
|
||||||
i, j: int
|
|
||||||
i = 0
|
|
||||||
j = 0
|
|
||||||
result = 1
|
result = 1
|
||||||
while j < blen:
|
while j < blen:
|
||||||
aa = a[i]
|
var aa = a[i]
|
||||||
bb = b[j]
|
var bb = b[j]
|
||||||
result = ord(aa) - ord(bb)
|
result = ord(aa) - ord(bb)
|
||||||
if (result != 0) or (aa == '\0'): break
|
if (result != 0) or (aa == '\0'): break
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
@ -78,23 +60,13 @@ proc cmpExact(a, b: cstring, blen: int): int =
|
||||||
if result == 0:
|
if result == 0:
|
||||||
if a[i] != '\0': result = 1
|
if a[i] != '\0': result = 1
|
||||||
|
|
||||||
proc getIdent(identifier: string): PIdent =
|
var wordCounter = 1
|
||||||
result = getIdent(cstring(identifier), len(identifier),
|
|
||||||
hashIgnoreStyle(identifier))
|
|
||||||
|
|
||||||
proc getIdent(identifier: string, h: THash): PIdent =
|
proc getIdent*(identifier: cstring, length: int, h: THash): PIdent =
|
||||||
result = getIdent(cstring(identifier), len(identifier), h)
|
var idx = h and high(buckets)
|
||||||
|
|
||||||
var wordCounter: int = 1
|
|
||||||
|
|
||||||
proc getIdent(identifier: cstring, length: int, h: THash): PIdent =
|
|
||||||
var
|
|
||||||
idx, id: int
|
|
||||||
last: PIdent
|
|
||||||
idx = h and high(buckets)
|
|
||||||
result = buckets[idx]
|
result = buckets[idx]
|
||||||
last = nil
|
var last: PIdent = nil
|
||||||
id = 0
|
var id = 0
|
||||||
while result != nil:
|
while result != nil:
|
||||||
if cmpExact(cstring(result.s), identifier, length) == 0:
|
if cmpExact(cstring(result.s), identifier, length) == 0:
|
||||||
if last != nil:
|
if last != nil:
|
||||||
|
|
@ -104,16 +76,6 @@ proc getIdent(identifier: cstring, length: int, h: THash): PIdent =
|
||||||
buckets[idx] = result
|
buckets[idx] = result
|
||||||
return
|
return
|
||||||
elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0:
|
elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0:
|
||||||
#if (id <> 0) and (id <> result.id) then begin
|
|
||||||
# result := buckets[idx];
|
|
||||||
# writeln('current id ', id);
|
|
||||||
# for i := 0 to len-1 do write(identifier[i]);
|
|
||||||
# writeln;
|
|
||||||
# while result <> nil do begin
|
|
||||||
# writeln(result.s, ' ', result.id);
|
|
||||||
# result := result.next
|
|
||||||
# end
|
|
||||||
# end;
|
|
||||||
assert((id == 0) or (id == result.id))
|
assert((id == 0) or (id == result.id))
|
||||||
id = result.id
|
id = result.id
|
||||||
last = result
|
last = result
|
||||||
|
|
@ -121,12 +83,22 @@ proc getIdent(identifier: cstring, length: int, h: THash): PIdent =
|
||||||
new(result)
|
new(result)
|
||||||
result.h = h
|
result.h = h
|
||||||
result.s = newString(length)
|
result.s = newString(length)
|
||||||
for i in countup(0, length + 0 - 1): result.s[i] = identifier[i - 0]
|
for i in countup(0, length - 1): result.s[i] = identifier[i]
|
||||||
result.next = buckets[idx]
|
result.next = buckets[idx]
|
||||||
buckets[idx] = result
|
buckets[idx] = result
|
||||||
if id == 0:
|
if id == 0:
|
||||||
inc(wordCounter)
|
inc(wordCounter)
|
||||||
result.id = - wordCounter
|
result.id = -wordCounter
|
||||||
else:
|
else:
|
||||||
result.id = id # writeln('new word ', result.s);
|
result.id = id
|
||||||
|
|
||||||
|
proc getIdent*(identifier: string): PIdent =
|
||||||
|
result = getIdent(cstring(identifier), len(identifier),
|
||||||
|
hashIgnoreStyle(identifier))
|
||||||
|
|
||||||
|
proc getIdent*(identifier: string, h: THash): PIdent =
|
||||||
|
result = getIdent(cstring(identifier), len(identifier), h)
|
||||||
|
|
||||||
|
proc IdentEq*(id: PIdent, name: string): bool =
|
||||||
|
result = id.id == getIdent(name).id
|
||||||
|
|
||||||
|
|
|
||||||
57
compiler/idgen.nim
Normal file
57
compiler/idgen.nim
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The Nimrod Compiler
|
||||||
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## This module contains a simple persistent id generator.
|
||||||
|
|
||||||
|
import idents, strutils, os
|
||||||
|
|
||||||
|
var gFrontEndId, gBackendId*: int
|
||||||
|
|
||||||
|
const
|
||||||
|
debugIds* = false
|
||||||
|
|
||||||
|
when debugIds:
|
||||||
|
import intsets
|
||||||
|
|
||||||
|
var usedIds = InitIntSet()
|
||||||
|
|
||||||
|
proc registerID*(id: PIdObj) =
|
||||||
|
when debugIDs:
|
||||||
|
if (id.id == - 1) or ContainsOrIncl(usedIds, id.id):
|
||||||
|
InternalError("ID already used: " & $id.id)
|
||||||
|
|
||||||
|
proc getID*(): int {.inline.} =
|
||||||
|
result = gFrontEndId
|
||||||
|
inc(gFrontEndId)
|
||||||
|
|
||||||
|
proc backendId*(): int {.inline.} =
|
||||||
|
result = gBackendId
|
||||||
|
inc(gBackendId)
|
||||||
|
|
||||||
|
proc setId*(id: int) {.inline.} =
|
||||||
|
gFrontEndId = max(gFrontEndId, id + 1)
|
||||||
|
|
||||||
|
proc IDsynchronizationPoint*(idRange: int) =
|
||||||
|
gFrontEndId = (gFrontEndId div IdRange + 1) * IdRange + 1
|
||||||
|
|
||||||
|
proc saveMaxIds*(project: string) =
|
||||||
|
var f = open(project.addFileExt("gid"), fmWrite)
|
||||||
|
f.writeln($gFrontEndId)
|
||||||
|
f.writeln($gBackEndId)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
proc loadMaxIds*(project: string) =
|
||||||
|
var f: TFile
|
||||||
|
if open(f, project.addFileExt("gid"), fmRead):
|
||||||
|
var frontEndId = parseInt(f.readLine)
|
||||||
|
var backEndId = parseInt(f.readLine)
|
||||||
|
gFrontEndId = max(gFrontEndId, frontEndId)
|
||||||
|
gBackEndId = max(gBackEndId, backEndId)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ import
|
||||||
os, lists, condsyms, rodread, rodwrite, ropes, trees,
|
os, lists, condsyms, rodread, rodwrite, ropes, trees,
|
||||||
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
||||||
cgen, ecmasgen,
|
cgen, ecmasgen,
|
||||||
platform, nimconf, importer, passaux, depends, transf, evals, types
|
platform, nimconf, importer, passaux, depends, transf, evals, types, idgen
|
||||||
|
|
||||||
const
|
const
|
||||||
has_LLVM_Backend = false
|
has_LLVM_Backend = false
|
||||||
|
|
@ -24,24 +24,17 @@ when has_LLVM_Backend:
|
||||||
import llvmgen
|
import llvmgen
|
||||||
|
|
||||||
proc MainCommand*(cmd, filename: string)
|
proc MainCommand*(cmd, filename: string)
|
||||||
# implementation
|
|
||||||
# ------------------ module handling -----------------------------------------
|
# ------------------ module handling -----------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
TFileModuleRec{.final.} = object
|
TFileModuleRec = tuple[filename: string, module: PSym]
|
||||||
filename*: string
|
|
||||||
module*: PSym
|
|
||||||
|
|
||||||
TFileModuleMap = seq[TFileModuleRec]
|
TFileModuleMap = seq[TFileModuleRec]
|
||||||
|
|
||||||
var compMods: TFileModuleMap = @[]
|
var compMods: TFileModuleMap = @[] # all compiled modules
|
||||||
|
|
||||||
proc registerModule(filename: string, module: PSym) =
|
proc registerModule(filename: string, module: PSym) =
|
||||||
# all compiled modules
|
compMods.add((filename, module))
|
||||||
var length = len(compMods)
|
|
||||||
setlen(compMods, length + 1)
|
|
||||||
compMods[length].filename = filename
|
|
||||||
compMods[length].module = module
|
|
||||||
|
|
||||||
proc getModule(filename: string): PSym =
|
proc getModule(filename: string): PSym =
|
||||||
for i in countup(0, high(compMods)):
|
for i in countup(0, high(compMods)):
|
||||||
|
|
@ -65,23 +58,22 @@ proc newModule(filename: string): PSym =
|
||||||
RegisterModule(filename, result)
|
RegisterModule(filename, result)
|
||||||
StrTableAdd(result.tab, result) # a module knows itself
|
StrTableAdd(result.tab, result) # a module knows itself
|
||||||
|
|
||||||
proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym
|
proc CompileModule(filename: string, flags: TSymFlags): PSym
|
||||||
proc importModule(filename: string): PSym =
|
proc importModule(filename: string): PSym =
|
||||||
# this is called by the semantic checking phase
|
# this is called by the semantic checking phase
|
||||||
result = getModule(filename)
|
result = getModule(filename)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
# compile the module
|
# compile the module
|
||||||
result = compileModule(filename, false, false)
|
result = compileModule(filename, {})
|
||||||
elif sfSystemModule in result.flags:
|
elif sfSystemModule in result.flags:
|
||||||
LocalError(result.info, errAttemptToRedefine, result.Name.s)
|
LocalError(result.info, errAttemptToRedefine, result.Name.s)
|
||||||
|
|
||||||
proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym =
|
proc CompileModule(filename: string, flags: TSymFlags): PSym =
|
||||||
var rd: PRodReader = nil
|
var rd: PRodReader = nil
|
||||||
var f = addFileExt(filename, nimExt)
|
var f = addFileExt(filename, nimExt)
|
||||||
result = newModule(filename)
|
result = newModule(filename)
|
||||||
if isMainFile: incl(result.flags, sfMainModule)
|
result.flags = result.flags + flags
|
||||||
if isSystemFile: incl(result.flags, sfSystemModule)
|
if gCmd in {cmdCompileToC, cmdCompileToCpp}:
|
||||||
if (gCmd == cmdCompileToC) or (gCmd == cmdCompileToCpp):
|
|
||||||
rd = handleSymbolFile(result, f)
|
rd = handleSymbolFile(result, f)
|
||||||
if result.id < 0:
|
if result.id < 0:
|
||||||
InternalError("handleSymbolFile should have set the module\'s ID")
|
InternalError("handleSymbolFile should have set the module\'s ID")
|
||||||
|
|
@ -90,9 +82,9 @@ proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym =
|
||||||
processModule(result, f, nil, rd)
|
processModule(result, f, nil, rd)
|
||||||
|
|
||||||
proc CompileProject(filename: string) =
|
proc CompileProject(filename: string) =
|
||||||
discard CompileModule(JoinPath(options.libpath, addFileExt("system", nimExt)),
|
discard CompileModule(options.libpath / addFileExt("system", nimExt),
|
||||||
false, true)
|
{sfSystemModule})
|
||||||
discard CompileModule(addFileExt(filename, nimExt), true, false)
|
discard CompileModule(addFileExt(filename, nimExt), {sfMainModule})
|
||||||
|
|
||||||
proc semanticPasses() =
|
proc semanticPasses() =
|
||||||
registerPass(verbosePass())
|
registerPass(verbosePass())
|
||||||
|
|
@ -147,8 +139,8 @@ proc CommandInteractive() =
|
||||||
registerPass(verbosePass())
|
registerPass(verbosePass())
|
||||||
registerPass(sem.semPass())
|
registerPass(sem.semPass())
|
||||||
registerPass(evals.evalPass()) # load system module:
|
registerPass(evals.evalPass()) # load system module:
|
||||||
discard CompileModule(JoinPath(options.libpath, addFileExt("system", nimExt)),
|
discard CompileModule(options.libpath / addFileExt("system", nimExt),
|
||||||
false, true)
|
{sfSystemModule})
|
||||||
var m = newModule("stdin")
|
var m = newModule("stdin")
|
||||||
m.id = getID()
|
m.id = getID()
|
||||||
incl(m.flags, sfMainModule)
|
incl(m.flags, sfMainModule)
|
||||||
|
|
@ -232,7 +224,7 @@ proc MainCommand(cmd, filename: string) =
|
||||||
rawMessage(errInvalidCommandX, cmd)
|
rawMessage(errInvalidCommandX, cmd)
|
||||||
of "pretty":
|
of "pretty":
|
||||||
gCmd = cmdPretty
|
gCmd = cmdPretty
|
||||||
wantFile(filename) #CommandExportSymbols(filename);
|
wantFile(filename)
|
||||||
CommandPretty(filename)
|
CommandPretty(filename)
|
||||||
of "doc":
|
of "doc":
|
||||||
gCmd = cmdDoc
|
gCmd = cmdDoc
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ type
|
||||||
errNamedExprNotAllowed, errXExpectsOneTypeParam,
|
errNamedExprNotAllowed, errXExpectsOneTypeParam,
|
||||||
errArrayExpectsTwoTypeParams, errInvalidVisibilityX, errInitHereNotAllowed,
|
errArrayExpectsTwoTypeParams, errInvalidVisibilityX, errInitHereNotAllowed,
|
||||||
errXCannotBeAssignedTo, errIteratorNotAllowed, errXNeedsReturnType,
|
errXCannotBeAssignedTo, errIteratorNotAllowed, errXNeedsReturnType,
|
||||||
|
errNoReturnTypeDeclared,
|
||||||
errInvalidCommandX, errXOnlyAtModuleScope,
|
errInvalidCommandX, errXOnlyAtModuleScope,
|
||||||
errXNeedsParamObjectType,
|
errXNeedsParamObjectType,
|
||||||
errTemplateInstantiationTooNested, errInstantiationFrom,
|
errTemplateInstantiationTooNested, errInstantiationFrom,
|
||||||
|
|
@ -284,6 +285,7 @@ const
|
||||||
errXCannotBeAssignedTo: "\'$1\' cannot be assigned to",
|
errXCannotBeAssignedTo: "\'$1\' cannot be assigned to",
|
||||||
errIteratorNotAllowed: "iterators can only be defined at the module\'s top level",
|
errIteratorNotAllowed: "iterators can only be defined at the module\'s top level",
|
||||||
errXNeedsReturnType: "$1 needs a return type",
|
errXNeedsReturnType: "$1 needs a return type",
|
||||||
|
errNoReturnTypeDeclared: "no return type declared",
|
||||||
errInvalidCommandX: "invalid command: \'$1\'",
|
errInvalidCommandX: "invalid command: \'$1\'",
|
||||||
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level",
|
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level",
|
||||||
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
|
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## implements some little helper passes
|
## implements some little helper passes
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, ast, astalgo, passes, msgs, options
|
strutils, ast, astalgo, passes, msgs, options, idgen
|
||||||
|
|
||||||
proc verboseOpen(s: PSym, filename: string): PPassContext =
|
proc verboseOpen(s: PSym, filename: string): PPassContext =
|
||||||
#MessageOut('compiling ' + s.name.s);
|
#MessageOut('compiling ' + s.name.s);
|
||||||
|
|
@ -24,7 +24,7 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode =
|
||||||
# system.nim deactivates all hints, for verbosity:3 we want the processing
|
# system.nim deactivates all hints, for verbosity:3 we want the processing
|
||||||
# messages nonetheless, so we activate them again unconditionally:
|
# messages nonetheless, so we activate them again unconditionally:
|
||||||
incl(msgs.gNotes, hintProcessing)
|
incl(msgs.gNotes, hintProcessing)
|
||||||
Message(n.info, hintProcessing, $ast.gid)
|
Message(n.info, hintProcessing, $idgen.gBackendId)
|
||||||
|
|
||||||
proc verbosePass*(): TPass =
|
proc verbosePass*(): TPass =
|
||||||
initPass(result)
|
initPass(result)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
import
|
import
|
||||||
strutils, lists, options, ast, astalgo, llstream, msgs, platform, os,
|
strutils, lists, options, ast, astalgo, llstream, msgs, platform, os,
|
||||||
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
|
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
|
||||||
nimsets, syntaxes, times, rodread, semthreads
|
nimsets, syntaxes, times, rodread, semthreads, idgen
|
||||||
|
|
||||||
type
|
type
|
||||||
TPassContext* = object of TObject # the pass's context
|
TPassContext* = object of TObject # the pass's context
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
|
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
|
||||||
ropes, idents, crc
|
ropes, idents, crc, idgen, rodutils
|
||||||
|
|
||||||
type
|
type
|
||||||
TReasonForRecompile* = enum
|
TReasonForRecompile* = enum
|
||||||
|
|
@ -100,12 +100,12 @@ type
|
||||||
TIndex*{.final.} = object # an index with compression
|
TIndex*{.final.} = object # an index with compression
|
||||||
lastIdxKey*, lastIdxVal*: int
|
lastIdxKey*, lastIdxVal*: int
|
||||||
tab*: TIITable
|
tab*: TIITable
|
||||||
r*: PRope # writers use this
|
r*: string # writers use this
|
||||||
offset*: int # readers use this
|
offset*: int # readers use this
|
||||||
|
|
||||||
TRodReader* = object of TObject
|
TRodReader* = object of TObject
|
||||||
pos*: int # position; used for parsing
|
pos*: int # position; used for parsing
|
||||||
s*: string # the whole file in memory
|
s*: string # the whole file in memory; XXX mmap this!
|
||||||
options*: TOptions
|
options*: TOptions
|
||||||
reason*: TReasonForRecompile
|
reason*: TReasonForRecompile
|
||||||
modDeps*: TStringSeq
|
modDeps*: TStringSeq
|
||||||
|
|
@ -116,7 +116,7 @@ type
|
||||||
filename*: string
|
filename*: string
|
||||||
index*, imports*: TIndex
|
index*, imports*: TIndex
|
||||||
readerIndex*: int
|
readerIndex*: int
|
||||||
line*: int # only used for debugging, but is always in the code
|
line*: int # only used for debugging, but is always in the code
|
||||||
moduleID*: int
|
moduleID*: int
|
||||||
syms*: TIdTable # already processed symbols
|
syms*: TIdTable # already processed symbols
|
||||||
|
|
||||||
|
|
@ -132,8 +132,7 @@ proc handleSymbolFile*(module: PSym, filename: string): PRodReader
|
||||||
proc GetCRC*(filename: string): TCrc32
|
proc GetCRC*(filename: string): TCrc32
|
||||||
proc loadInitSection*(r: PRodReader): PNode
|
proc loadInitSection*(r: PRodReader): PNode
|
||||||
proc loadStub*(s: PSym)
|
proc loadStub*(s: PSym)
|
||||||
proc encodeInt*(x: BiggestInt): PRope
|
|
||||||
proc encode*(s: string): PRope
|
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
var gTypeTable: TIdTable
|
var gTypeTable: TIdTable
|
||||||
|
|
@ -141,52 +140,19 @@ var gTypeTable: TIdTable
|
||||||
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
|
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
|
||||||
# `info` is only used for debugging purposes
|
# `info` is only used for debugging purposes
|
||||||
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
|
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
|
||||||
proc decode(r: PRodReader): string
|
|
||||||
proc decodeInt(r: PRodReader): int
|
|
||||||
proc decodeBInt(r: PRodReader): biggestInt
|
|
||||||
|
|
||||||
proc encode(s: string): PRope =
|
|
||||||
var res = ""
|
|
||||||
for i in countup(0, len(s) - 1):
|
|
||||||
case s[i]
|
|
||||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(res, s[i])
|
|
||||||
else: add(res, '\\' & toHex(ord(s[i]), 2))
|
|
||||||
result = toRope(res)
|
|
||||||
|
|
||||||
proc encodeIntAux(str: var string, x: BiggestInt) =
|
|
||||||
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
var d: char
|
|
||||||
var v = x
|
|
||||||
var rem: biggestInt = v mod 190
|
|
||||||
if (rem < 0):
|
|
||||||
add(str, '-')
|
|
||||||
v = - (v div 190)
|
|
||||||
rem = - rem
|
|
||||||
else:
|
|
||||||
v = v div 190
|
|
||||||
var idx = int(rem)
|
|
||||||
if idx < 62: d = chars[idx + 0]
|
|
||||||
else: d = chr(idx - 62 + 128)
|
|
||||||
if (v != 0): encodeIntAux(str, v)
|
|
||||||
add(str, d)
|
|
||||||
|
|
||||||
proc encodeInt(x: BiggestInt): PRope =
|
|
||||||
var res = ""
|
|
||||||
encodeIntAux(res, x)
|
|
||||||
result = toRope(res)
|
|
||||||
|
|
||||||
proc decodeLineInfo(r: PRodReader, info: var TLineInfo) =
|
proc decodeLineInfo(r: PRodReader, info: var TLineInfo) =
|
||||||
if r.s[r.pos] == '?':
|
if r.s[r.pos] == '?':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
if r.s[r.pos] == ',': info.col = int16(- 1)
|
if r.s[r.pos] == ',': info.col = int16(- 1)
|
||||||
else: info.col = int16(decodeInt(r))
|
else: info.col = int16(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == ',':
|
if r.s[r.pos] == ',':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
if r.s[r.pos] == ',': info.line = int16(- 1)
|
if r.s[r.pos] == ',': info.line = int16(- 1)
|
||||||
else: info.line = int16(decodeInt(r))
|
else: info.line = int16(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == ',':
|
if r.s[r.pos] == ',':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
info = newLineInfo(r.files[decodeInt(r)], info.line, info.col)
|
info = newLineInfo(r.files[decodeVInt(r.s, r.pos)], info.line, info.col)
|
||||||
|
|
||||||
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -195,42 +161,42 @@ proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
||||||
if r.s[r.pos] == ')':
|
if r.s[r.pos] == ')':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
return # nil node
|
return # nil node
|
||||||
result = newNodeI(TNodeKind(decodeInt(r)), fInfo)
|
result = newNodeI(TNodeKind(decodeVInt(r.s, r.pos)), fInfo)
|
||||||
decodeLineInfo(r, result.info)
|
decodeLineInfo(r, result.info)
|
||||||
if r.s[r.pos] == '$':
|
if r.s[r.pos] == '$':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.flags = cast[TNodeFlags](int32(decodeInt(r)))
|
result.flags = cast[TNodeFlags](int32(decodeVInt(r.s, r.pos)))
|
||||||
if r.s[r.pos] == '^':
|
if r.s[r.pos] == '^':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var id = decodeInt(r)
|
var id = decodeVInt(r.s, r.pos)
|
||||||
result.typ = rrGetType(r, id, result.info)
|
result.typ = rrGetType(r, id, result.info)
|
||||||
case result.kind
|
case result.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkInt64Lit:
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.intVal = decodeBInt(r)
|
result.intVal = decodeVBiggestInt(r.s, r.pos)
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat64Lit:
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var fl = decode(r)
|
var fl = decodeStr(r.s, r.pos)
|
||||||
result.floatVal = parseFloat(fl)
|
result.floatVal = parseFloat(fl)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.strVal = decode(r)
|
result.strVal = decodeStr(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
result.strVal = "" # BUGFIX
|
result.strVal = "" # BUGFIX
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var fl = decode(r)
|
var fl = decodeStr(r.s, r.pos)
|
||||||
result.ident = getIdent(fl)
|
result.ident = getIdent(fl)
|
||||||
else:
|
else:
|
||||||
internalError(result.info, "decodeNode: nkIdent")
|
internalError(result.info, "decodeNode: nkIdent")
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var id = decodeInt(r)
|
var id = decodeVInt(r.s, r.pos)
|
||||||
result.sym = rrGetSym(r, id, result.info)
|
result.sym = rrGetSym(r, id, result.info)
|
||||||
else:
|
else:
|
||||||
internalError(result.info, "decodeNode: nkSym")
|
internalError(result.info, "decodeNode: nkSym")
|
||||||
|
|
@ -245,32 +211,32 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
|
||||||
if r.s[r.pos] == '<':
|
if r.s[r.pos] == '<':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
if r.s[r.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}:
|
if r.s[r.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}:
|
||||||
loc.k = TLocKind(decodeInt(r))
|
loc.k = TLocKind(decodeVInt(r.s, r.pos))
|
||||||
else:
|
else:
|
||||||
loc.k = low(loc.k)
|
loc.k = low(loc.k)
|
||||||
if r.s[r.pos] == '*':
|
if r.s[r.pos] == '*':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
loc.s = TStorageLoc(decodeInt(r))
|
loc.s = TStorageLoc(decodeVInt(r.s, r.pos))
|
||||||
else:
|
else:
|
||||||
loc.s = low(loc.s)
|
loc.s = low(loc.s)
|
||||||
if r.s[r.pos] == '$':
|
if r.s[r.pos] == '$':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
loc.flags = cast[TLocFlags](int32(decodeInt(r)))
|
loc.flags = cast[TLocFlags](int32(decodeVInt(r.s, r.pos)))
|
||||||
else:
|
else:
|
||||||
loc.flags = {}
|
loc.flags = {}
|
||||||
if r.s[r.pos] == '^':
|
if r.s[r.pos] == '^':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
loc.t = rrGetType(r, decodeInt(r), info)
|
loc.t = rrGetType(r, decodeVInt(r.s, r.pos), info)
|
||||||
else:
|
else:
|
||||||
loc.t = nil
|
loc.t = nil
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
loc.r = toRope(decode(r))
|
loc.r = toRope(decodeStr(r.s, r.pos))
|
||||||
else:
|
else:
|
||||||
loc.r = nil
|
loc.r = nil
|
||||||
if r.s[r.pos] == '?':
|
if r.s[r.pos] == '?':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
loc.a = decodeInt(r)
|
loc.a = decodeVInt(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
loc.a = 0
|
loc.a = 0
|
||||||
if r.s[r.pos] == '>': inc(r.pos)
|
if r.s[r.pos] == '>': inc(r.pos)
|
||||||
|
|
@ -284,10 +250,10 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
return # nil type
|
return # nil type
|
||||||
new(result)
|
new(result)
|
||||||
result.kind = TTypeKind(decodeInt(r))
|
result.kind = TTypeKind(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == '+':
|
if r.s[r.pos] == '+':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.id = decodeInt(r)
|
result.id = decodeVInt(r.s, r.pos)
|
||||||
setId(result.id)
|
setId(result.id)
|
||||||
if debugIds: registerID(result)
|
if debugIds: registerID(result)
|
||||||
else:
|
else:
|
||||||
|
|
@ -297,29 +263,29 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||||
if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo())
|
if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo())
|
||||||
if r.s[r.pos] == '$':
|
if r.s[r.pos] == '$':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.flags = cast[TTypeFlags](int32(decodeInt(r)))
|
result.flags = cast[TTypeFlags](int32(decodeVInt(r.s, r.pos)))
|
||||||
if r.s[r.pos] == '?':
|
if r.s[r.pos] == '?':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.callConv = TCallingConvention(decodeInt(r))
|
result.callConv = TCallingConvention(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == '*':
|
if r.s[r.pos] == '*':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.owner = rrGetSym(r, decodeInt(r), info)
|
result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), info)
|
||||||
if r.s[r.pos] == '&':
|
if r.s[r.pos] == '&':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.sym = rrGetSym(r, decodeInt(r), info)
|
result.sym = rrGetSym(r, decodeVInt(r.s, r.pos), info)
|
||||||
if r.s[r.pos] == '/':
|
if r.s[r.pos] == '/':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.size = decodeInt(r)
|
result.size = decodeVInt(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
result.size = - 1
|
result.size = - 1
|
||||||
if r.s[r.pos] == '=':
|
if r.s[r.pos] == '=':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.align = decodeInt(r)
|
result.align = decodeVInt(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
result.align = 2
|
result.align = 2
|
||||||
if r.s[r.pos] == '@':
|
if r.s[r.pos] == '@':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.containerID = decodeInt(r)
|
result.containerID = decodeVInt(r.s, r.pos)
|
||||||
decodeLoc(r, result.loc, info)
|
decodeLoc(r, result.loc, info)
|
||||||
while r.s[r.pos] == '^':
|
while r.s[r.pos] == '^':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
|
|
@ -329,7 +295,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||||
else: InternalError(info, "decodeType ^(" & r.s[r.pos])
|
else: InternalError(info, "decodeType ^(" & r.s[r.pos])
|
||||||
addSon(result, nil)
|
addSon(result, nil)
|
||||||
else:
|
else:
|
||||||
var d = decodeInt(r)
|
var d = decodeVInt(r.s, r.pos)
|
||||||
addSon(result, rrGetType(r, d, info))
|
addSon(result, rrGetType(r, d, info))
|
||||||
|
|
||||||
proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
|
proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
|
||||||
|
|
@ -337,10 +303,10 @@ proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
|
||||||
if r.s[r.pos] == '|':
|
if r.s[r.pos] == '|':
|
||||||
new(result)
|
new(result)
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.kind = TLibKind(decodeInt(r))
|
result.kind = TLibKind(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] != '|': InternalError("decodeLib: 1")
|
if r.s[r.pos] != '|': InternalError("decodeLib: 1")
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.name = toRope(decode(r))
|
result.name = toRope(decodeStr(r.s, r.pos))
|
||||||
if r.s[r.pos] != '|': InternalError("decodeLib: 2")
|
if r.s[r.pos] != '|': InternalError("decodeLib: 2")
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.path = decodeNode(r, info)
|
result.path = decodeNode(r, info)
|
||||||
|
|
@ -355,16 +321,16 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
if r.s[r.pos] == '}':
|
if r.s[r.pos] == '}':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
return # nil sym
|
return # nil sym
|
||||||
var k = TSymKind(decodeInt(r))
|
var k = TSymKind(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == '+':
|
if r.s[r.pos] == '+':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
id = decodeInt(r)
|
id = decodeVInt(r.s, r.pos)
|
||||||
setId(id)
|
setId(id)
|
||||||
else:
|
else:
|
||||||
InternalError(info, "decodeSym: no id")
|
InternalError(info, "decodeSym: no id")
|
||||||
if r.s[r.pos] == '&':
|
if r.s[r.pos] == '&':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
ident = getIdent(decode(r))
|
ident = getIdent(decodeStr(r.s, r.pos))
|
||||||
else:
|
else:
|
||||||
InternalError(info, "decodeSym: no ident")
|
InternalError(info, "decodeSym: no ident")
|
||||||
result = PSym(IdTableGet(r.syms, id))
|
result = PSym(IdTableGet(r.syms, id))
|
||||||
|
|
@ -379,100 +345,37 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
result.name = ident # read the rest of the symbol description:
|
result.name = ident # read the rest of the symbol description:
|
||||||
if r.s[r.pos] == '^':
|
if r.s[r.pos] == '^':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.typ = rrGetType(r, decodeInt(r), info)
|
result.typ = rrGetType(r, decodeVInt(r.s, r.pos), info)
|
||||||
decodeLineInfo(r, result.info)
|
decodeLineInfo(r, result.info)
|
||||||
if r.s[r.pos] == '*':
|
if r.s[r.pos] == '*':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.owner = rrGetSym(r, decodeInt(r), result.info)
|
result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), result.info)
|
||||||
if r.s[r.pos] == '$':
|
if r.s[r.pos] == '$':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.flags = cast[TSymFlags](int32(decodeInt(r)))
|
result.flags = cast[TSymFlags](int32(decodeVInt(r.s, r.pos)))
|
||||||
if r.s[r.pos] == '@':
|
if r.s[r.pos] == '@':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.magic = TMagic(decodeInt(r))
|
result.magic = TMagic(decodeVInt(r.s, r.pos))
|
||||||
if r.s[r.pos] == '(': result.ast = decodeNode(r, result.info)
|
if r.s[r.pos] == '(': result.ast = decodeNode(r, result.info)
|
||||||
if r.s[r.pos] == '!':
|
if r.s[r.pos] == '!':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.options = cast[TOptions](int32(decodeInt(r)))
|
result.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
|
||||||
else:
|
else:
|
||||||
result.options = r.options
|
result.options = r.options
|
||||||
if r.s[r.pos] == '%':
|
if r.s[r.pos] == '%':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.position = decodeInt(r)
|
result.position = decodeVInt(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
result.position = 0
|
result.position = 0
|
||||||
# BUGFIX: this may have been misused as reader index!
|
# BUGFIX: this may have been misused as reader index!
|
||||||
if r.s[r.pos] == '`':
|
if r.s[r.pos] == '`':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.offset = decodeInt(r)
|
result.offset = decodeVInt(r.s, r.pos)
|
||||||
else:
|
else:
|
||||||
result.offset = - 1
|
result.offset = - 1
|
||||||
decodeLoc(r, result.loc, result.info)
|
decodeLoc(r, result.loc, result.info)
|
||||||
result.annex = decodeLib(r, info)
|
result.annex = decodeLib(r, info)
|
||||||
|
|
||||||
proc decodeInt(r: PRodReader): int =
|
|
||||||
# base 190 numbers
|
|
||||||
var i = r.pos
|
|
||||||
var sign = - 1
|
|
||||||
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
|
||||||
if r.s[i] == '-':
|
|
||||||
inc(i)
|
|
||||||
sign = 1
|
|
||||||
result = 0
|
|
||||||
while true:
|
|
||||||
case r.s[i]
|
|
||||||
of '0'..'9': result = result * 190 - (ord(r.s[i]) - ord('0'))
|
|
||||||
of 'a'..'z': result = result * 190 - (ord(r.s[i]) - ord('a') + 10)
|
|
||||||
of 'A'..'Z': result = result * 190 - (ord(r.s[i]) - ord('A') + 36)
|
|
||||||
of '\x80'..'\xFF': result = result * 190 - (ord(r.s[i]) - 128 + 62)
|
|
||||||
else: break
|
|
||||||
inc(i)
|
|
||||||
result = result * sign
|
|
||||||
r.pos = i
|
|
||||||
|
|
||||||
proc decodeBInt(r: PRodReader): biggestInt =
|
|
||||||
var i = r.pos
|
|
||||||
var sign: biggestInt = - 1
|
|
||||||
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
|
||||||
if r.s[i] == '-':
|
|
||||||
inc(i)
|
|
||||||
sign = 1
|
|
||||||
result = 0
|
|
||||||
while true:
|
|
||||||
case r.s[i]
|
|
||||||
of '0'..'9': result = result * 190 - (ord(r.s[i]) - ord('0'))
|
|
||||||
of 'a'..'z': result = result * 190 - (ord(r.s[i]) - ord('a') + 10)
|
|
||||||
of 'A'..'Z': result = result * 190 - (ord(r.s[i]) - ord('A') + 36)
|
|
||||||
of '\x80'..'\xFF': result = result * 190 - (ord(r.s[i]) - 128 + 62)
|
|
||||||
else: break
|
|
||||||
inc(i)
|
|
||||||
result = result * sign
|
|
||||||
r.pos = i
|
|
||||||
|
|
||||||
proc hexChar(c: char, xi: var int) =
|
|
||||||
case c
|
|
||||||
of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
|
|
||||||
of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10)
|
|
||||||
of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10)
|
|
||||||
else: nil
|
|
||||||
|
|
||||||
proc decode(r: PRodReader): string =
|
|
||||||
var i = r.pos
|
|
||||||
result = ""
|
|
||||||
while true:
|
|
||||||
case r.s[i]
|
|
||||||
of '\\':
|
|
||||||
inc(i, 3)
|
|
||||||
var xi = 0
|
|
||||||
hexChar(r.s[i-2], xi)
|
|
||||||
hexChar(r.s[i-1], xi)
|
|
||||||
add(result, chr(xi))
|
|
||||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_':
|
|
||||||
add(result, r.s[i])
|
|
||||||
inc(i)
|
|
||||||
else: break
|
|
||||||
r.pos = i
|
|
||||||
|
|
||||||
proc skipSection(r: PRodReader) =
|
proc skipSection(r: PRodReader) =
|
||||||
if r.s[r.pos] == ':':
|
if r.s[r.pos] == ':':
|
||||||
while r.s[r.pos] > '\x0A': inc(r.pos)
|
while r.s[r.pos] > '\x0A': inc(r.pos)
|
||||||
|
|
@ -514,9 +417,9 @@ proc processInterf(r: PRodReader, module: PSym) =
|
||||||
if r.interfIdx == 0: InternalError("processInterf")
|
if r.interfIdx == 0: InternalError("processInterf")
|
||||||
r.pos = r.interfIdx
|
r.pos = r.interfIdx
|
||||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||||
var w = decode(r)
|
var w = decodeStr(r.s, r.pos)
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var key = decodeInt(r)
|
var key = decodeVInt(r.s, r.pos)
|
||||||
inc(r.pos) # #10
|
inc(r.pos) # #10
|
||||||
var s = newStub(r, w, key)
|
var s = newStub(r, w, key)
|
||||||
s.owner = module
|
s.owner = module
|
||||||
|
|
@ -527,9 +430,9 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
|
||||||
if r.compilerProcsIdx == 0: InternalError("processCompilerProcs")
|
if r.compilerProcsIdx == 0: InternalError("processCompilerProcs")
|
||||||
r.pos = r.compilerProcsIdx
|
r.pos = r.compilerProcsIdx
|
||||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||||
var w = decode(r)
|
var w = decodeStr(r.s, r.pos)
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
var key = decodeInt(r)
|
var key = decodeVInt(r.s, r.pos)
|
||||||
inc(r.pos) # #10
|
inc(r.pos) # #10
|
||||||
var s = PSym(IdTableGet(r.syms, key))
|
var s = PSym(IdTableGet(r.syms, key))
|
||||||
if s == nil:
|
if s == nil:
|
||||||
|
|
@ -543,11 +446,11 @@ proc processIndex(r: PRodReader, idx: var TIndex) =
|
||||||
inc(r.pos, 2) # skip "(\10"
|
inc(r.pos, 2) # skip "(\10"
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||||
tmp = decodeInt(r)
|
tmp = decodeVInt(r.s, r.pos)
|
||||||
if r.s[r.pos] == ' ':
|
if r.s[r.pos] == ' ':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
key = idx.lastIdxKey + tmp
|
key = idx.lastIdxKey + tmp
|
||||||
val = decodeInt(r) + idx.lastIdxVal
|
val = decodeVInt(r.s, r.pos) + idx.lastIdxVal
|
||||||
else:
|
else:
|
||||||
key = idx.lastIdxKey + 1
|
key = idx.lastIdxKey + 1
|
||||||
val = tmp + idx.lastIdxVal
|
val = tmp + idx.lastIdxVal
|
||||||
|
|
@ -571,20 +474,20 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
case section
|
case section
|
||||||
of "CRC":
|
of "CRC":
|
||||||
inc(r.pos) # skip ':'
|
inc(r.pos) # skip ':'
|
||||||
if int(crc) != decodeInt(r): r.reason = rrCrcChange
|
if int(crc) != decodeVInt(r.s, r.pos): r.reason = rrCrcChange
|
||||||
of "ID":
|
of "ID":
|
||||||
inc(r.pos) # skip ':'
|
inc(r.pos) # skip ':'
|
||||||
r.moduleID = decodeInt(r)
|
r.moduleID = decodeVInt(r.s, r.pos)
|
||||||
setID(r.moduleID)
|
setID(r.moduleID)
|
||||||
of "OPTIONS":
|
of "OPTIONS":
|
||||||
inc(r.pos) # skip ':'
|
inc(r.pos) # skip ':'
|
||||||
r.options = cast[TOptions](int32(decodeInt(r)))
|
r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
|
||||||
if options.gOptions != r.options: r.reason = rrOptions
|
if options.gOptions != r.options: r.reason = rrOptions
|
||||||
of "DEFINES":
|
of "DEFINES":
|
||||||
inc(r.pos) # skip ':'
|
inc(r.pos) # skip ':'
|
||||||
d = 0
|
d = 0
|
||||||
while r.s[r.pos] > '\x0A':
|
while r.s[r.pos] > '\x0A':
|
||||||
w = decode(r)
|
w = decodeStr(r.s, r.pos)
|
||||||
inc(d)
|
inc(d)
|
||||||
if not condsyms.isDefined(getIdent(w)):
|
if not condsyms.isDefined(getIdent(w)):
|
||||||
r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
|
r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
|
||||||
|
|
@ -596,7 +499,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
L = 0
|
L = 0
|
||||||
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||||
setlen(r.files, L + 1)
|
setlen(r.files, L + 1)
|
||||||
r.files[L] = decode(r)
|
r.files[L] = decodeStr(r.s, r.pos)
|
||||||
inc(r.pos) # skip #10
|
inc(r.pos) # skip #10
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
inc(L)
|
inc(L)
|
||||||
|
|
@ -605,9 +508,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
inc(r.pos, 2) # skip "(\10"
|
inc(r.pos, 2) # skip "(\10"
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||||
w = r.files[decodeInt(r)]
|
w = r.files[decodeVInt(r.s, r.pos)]
|
||||||
inc(r.pos) # skip ' '
|
inc(r.pos) # skip ' '
|
||||||
inclCrc = decodeInt(r)
|
inclCrc = decodeVInt(r.s, r.pos)
|
||||||
if r.reason == rrNone:
|
if r.reason == rrNone:
|
||||||
if not ExistsFile(w) or (inclCrc != int(crcFromFile(w))):
|
if not ExistsFile(w) or (inclCrc != int(crcFromFile(w))):
|
||||||
r.reason = rrInclDeps
|
r.reason = rrInclDeps
|
||||||
|
|
@ -620,7 +523,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
L = 0
|
L = 0
|
||||||
while r.s[r.pos] > '\x0A':
|
while r.s[r.pos] > '\x0A':
|
||||||
setlen(r.modDeps, L + 1)
|
setlen(r.modDeps, L + 1)
|
||||||
r.modDeps[L] = r.files[decodeInt(r)]
|
r.modDeps[L] = r.files[decodeVInt(r.s, r.pos)]
|
||||||
inc(L)
|
inc(L)
|
||||||
if r.s[r.pos] == ' ': inc(r.pos)
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
of "INTERF":
|
of "INTERF":
|
||||||
|
|
@ -723,8 +626,9 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||||
if d == invalidKey:
|
if d == invalidKey:
|
||||||
var moduleID = IiTableGet(r.imports.tab, id)
|
var moduleID = IiTableGet(r.imports.tab, id)
|
||||||
if moduleID < 0:
|
if moduleID < 0:
|
||||||
InternalError(info,
|
var x = ""
|
||||||
"missing from both indexes: +" & ropeToStr(encodeInt(id)))
|
encodeVInt(id, x)
|
||||||
|
InternalError(info, "missing from both indexes: +" & x)
|
||||||
# find the reader with the correct moduleID:
|
# find the reader with the correct moduleID:
|
||||||
for i in countup(0, high(gMods)):
|
for i in countup(0, high(gMods)):
|
||||||
var rd = gMods[i].rd
|
var rd = gMods[i].rd
|
||||||
|
|
@ -735,8 +639,9 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||||
result = decodeSymSafePos(rd, d, info)
|
result = decodeSymSafePos(rd, d, info)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
InternalError(info, "rrGetSym: no reader found: +" &
|
var x = ""
|
||||||
ropeToStr(encodeInt(id)))
|
encodeVInt(id, x)
|
||||||
|
InternalError(info, "rrGetSym: no reader found: +" & x)
|
||||||
else:
|
else:
|
||||||
#if IiTableGet(rd.index.tab, id) <> invalidKey then
|
#if IiTableGet(rd.index.tab, id) <> invalidKey then
|
||||||
# XXX expensive check!
|
# XXX expensive check!
|
||||||
|
|
@ -753,7 +658,7 @@ proc loadInitSection(r: PRodReader): PNode =
|
||||||
r.pos = r.initIdx
|
r.pos = r.initIdx
|
||||||
result = newNode(nkStmtList)
|
result = newNode(nkStmtList)
|
||||||
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||||
var d = decodeInt(r)
|
var d = decodeVInt(r.s, r.pos)
|
||||||
inc(r.pos) # #10
|
inc(r.pos) # #10
|
||||||
var p = r.pos
|
var p = r.pos
|
||||||
r.pos = d + r.dataIdx
|
r.pos = d + r.dataIdx
|
||||||
|
|
@ -767,7 +672,7 @@ proc loadConverters(r: PRodReader) =
|
||||||
InternalError("importConverters")
|
InternalError("importConverters")
|
||||||
r.pos = r.convertersIdx
|
r.pos = r.convertersIdx
|
||||||
while (r.s[r.pos] > '\x0A'):
|
while (r.s[r.pos] > '\x0A'):
|
||||||
var d = decodeInt(r)
|
var d = decodeVInt(r.s, r.pos)
|
||||||
discard rrGetSym(r, d, UnknownLineInfo())
|
discard rrGetSym(r, d, UnknownLineInfo())
|
||||||
if r.s[r.pos] == ' ': inc(r.pos)
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
|
|
||||||
|
|
@ -818,9 +723,11 @@ proc checkDep(filename: string): TReasonForRecompile =
|
||||||
gMods[idx].reason = result # now we know better
|
gMods[idx].reason = result # now we know better
|
||||||
|
|
||||||
proc handleSymbolFile(module: PSym, filename: string): PRodReader =
|
proc handleSymbolFile(module: PSym, filename: string): PRodReader =
|
||||||
if not (optSymbolFiles in gGlobalOptions):
|
if optSymbolFiles notin gGlobalOptions:
|
||||||
module.id = getID()
|
module.id = getID()
|
||||||
return nil
|
return nil
|
||||||
|
idgen.loadMaxIds(options.projectPath / options.projectName)
|
||||||
|
|
||||||
discard checkDep(filename)
|
discard checkDep(filename)
|
||||||
var idx = getModuleIdx(filename)
|
var idx = getModuleIdx(filename)
|
||||||
if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile")
|
if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile")
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## Utilities for the compiler. Aim is to reduce the coupling between
|
## Serialization utilities for the compiler.
|
||||||
## the compiler and the evolving stdlib.
|
import strutils
|
||||||
|
|
||||||
proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", nodecl, varargs.}
|
proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", nodecl, varargs.}
|
||||||
|
|
||||||
|
|
@ -25,3 +25,97 @@ proc ToStrMaxPrecision*(f: BiggestFloat): string =
|
||||||
c_sprintf(buf, "%#.16e", f)
|
c_sprintf(buf, "%#.16e", f)
|
||||||
result = $buf
|
result = $buf
|
||||||
|
|
||||||
|
proc encodeStr*(s: string, result: var string) =
|
||||||
|
for i in countup(0, len(s) - 1):
|
||||||
|
case s[i]
|
||||||
|
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
|
||||||
|
else: add(result, '\\' & toHex(ord(s[i]), 2))
|
||||||
|
|
||||||
|
proc hexChar(c: char, xi: var int) =
|
||||||
|
case c
|
||||||
|
of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
|
||||||
|
of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10)
|
||||||
|
of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10)
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
proc decodeStr*(s: cstring, pos: var int): string =
|
||||||
|
var i = pos
|
||||||
|
result = ""
|
||||||
|
while true:
|
||||||
|
case s[i]
|
||||||
|
of '\\':
|
||||||
|
inc(i, 3)
|
||||||
|
var xi = 0
|
||||||
|
hexChar(s[i-2], xi)
|
||||||
|
hexChar(s[i-1], xi)
|
||||||
|
add(result, chr(xi))
|
||||||
|
of 'a'..'z', 'A'..'Z', '0'..'9', '_':
|
||||||
|
add(result, s[i])
|
||||||
|
inc(i)
|
||||||
|
else: break
|
||||||
|
pos = i
|
||||||
|
|
||||||
|
const
|
||||||
|
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
template encodeIntImpl(self: expr) =
|
||||||
|
var d: char
|
||||||
|
var v = x
|
||||||
|
var rem = v mod 190
|
||||||
|
if rem < 0:
|
||||||
|
add(result, '-')
|
||||||
|
v = - (v div 190)
|
||||||
|
rem = - rem
|
||||||
|
else:
|
||||||
|
v = v div 190
|
||||||
|
var idx = int(rem)
|
||||||
|
if idx < 62: d = chars[idx]
|
||||||
|
else: d = chr(idx - 62 + 128)
|
||||||
|
if v != 0: self(v, result)
|
||||||
|
add(result, d)
|
||||||
|
|
||||||
|
proc encodeVBiggestInt*(x: BiggestInt, result: var string) =
|
||||||
|
## encode a biggest int as a variable length base 190 int.
|
||||||
|
encodeIntImpl(encodeVBiggestInt)
|
||||||
|
|
||||||
|
proc encodeVInt*(x: int, result: var string) =
|
||||||
|
## encode an int as a variable length base 190 int.
|
||||||
|
encodeIntImpl(encodeVInt)
|
||||||
|
|
||||||
|
template decodeIntImpl() =
|
||||||
|
var i = pos
|
||||||
|
var sign = - 1
|
||||||
|
assert(s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
||||||
|
if s[i] == '-':
|
||||||
|
inc(i)
|
||||||
|
sign = 1
|
||||||
|
result = 0
|
||||||
|
while true:
|
||||||
|
case s[i]
|
||||||
|
of '0'..'9': result = result * 190 - (ord(s[i]) - ord('0'))
|
||||||
|
of 'a'..'z': result = result * 190 - (ord(s[i]) - ord('a') + 10)
|
||||||
|
of 'A'..'Z': result = result * 190 - (ord(s[i]) - ord('A') + 36)
|
||||||
|
of '\x80'..'\xFF': result = result * 190 - (ord(s[i]) - 128 + 62)
|
||||||
|
else: break
|
||||||
|
inc(i)
|
||||||
|
result = result * sign
|
||||||
|
pos = i
|
||||||
|
|
||||||
|
proc decodeVInt*(s: cstring, pos: var int): int =
|
||||||
|
decodeIntImpl()
|
||||||
|
|
||||||
|
proc decodeVBiggestInt*(s: cstring, pos: var int): biggestInt =
|
||||||
|
decodeIntImpl()
|
||||||
|
|
||||||
|
iterator decodeVIntArray*(s: cstring): int =
|
||||||
|
var i = 0
|
||||||
|
while s[i] != '\0':
|
||||||
|
yield decodeVInt(s, i)
|
||||||
|
if s[i] == ' ': inc i
|
||||||
|
|
||||||
|
iterator decodeStrArray*(s: cstring): string =
|
||||||
|
var i = 0
|
||||||
|
while s[i] != '\0':
|
||||||
|
yield decodeStr(s, i)
|
||||||
|
if s[i] == ' ': inc i
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -13,29 +13,29 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
|
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
|
||||||
condsyms, ropes, idents, crc, rodread, passes, importer
|
condsyms, ropes, idents, crc, rodread, passes, importer, idgen, rodutils
|
||||||
|
|
||||||
proc rodwritePass*(): TPass
|
proc rodwritePass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
type
|
type
|
||||||
TRodWriter = object of TPassContext
|
TRodWriter = object of TPassContext
|
||||||
module*: PSym
|
module: PSym
|
||||||
crc*: TCrc32
|
crc: TCrc32
|
||||||
options*: TOptions
|
options: TOptions
|
||||||
defines*: PRope
|
defines: string
|
||||||
inclDeps*: PRope
|
inclDeps: string
|
||||||
modDeps*: PRope
|
modDeps: string
|
||||||
interf*: PRope
|
interf: string
|
||||||
compilerProcs*: PRope
|
compilerProcs: string
|
||||||
index*, imports*: TIndex
|
index, imports: TIndex
|
||||||
converters*: PRope
|
converters: string
|
||||||
init*: PRope
|
init: string
|
||||||
data*: PRope
|
data: string
|
||||||
filename*: string
|
filename: string
|
||||||
sstack*: TSymSeq # a stack of symbols to process
|
sstack: TSymSeq # a stack of symbols to process
|
||||||
tstack*: TTypeSeq # a stack of types to process
|
tstack: TTypeSeq # a stack of types to process
|
||||||
files*: TStringSeq
|
files: TStringSeq
|
||||||
|
|
||||||
PRodWriter = ref TRodWriter
|
PRodWriter = ref TRodWriter
|
||||||
|
|
||||||
|
|
@ -45,19 +45,17 @@ proc addInclDep(w: PRodWriter, dep: string)
|
||||||
proc addInterfaceSym(w: PRodWriter, s: PSym)
|
proc addInterfaceSym(w: PRodWriter, s: PSym)
|
||||||
proc addStmt(w: PRodWriter, n: PNode)
|
proc addStmt(w: PRodWriter, n: PNode)
|
||||||
proc writeRod(w: PRodWriter)
|
proc writeRod(w: PRodWriter)
|
||||||
proc encodeStr(w: PRodWriter, s: string): PRope =
|
|
||||||
result = encode(s)
|
|
||||||
|
|
||||||
proc processStacks(w: PRodWriter)
|
proc processStacks(w: PRodWriter)
|
||||||
|
|
||||||
proc getDefines(): PRope =
|
proc getDefines(): string =
|
||||||
var it: TTabIter
|
var it: TTabIter
|
||||||
var s = InitTabIter(it, gSymbols)
|
var s = InitTabIter(it, gSymbols)
|
||||||
result = nil
|
result = ""
|
||||||
while s != nil:
|
while s != nil:
|
||||||
if s.position == 1:
|
if s.position == 1:
|
||||||
if result != nil: app(result, " ")
|
if result.len != 0: add(result, " ")
|
||||||
app(result, s.name.s)
|
add(result, s.name.s)
|
||||||
s = nextIter(it, gSymbols)
|
s = nextIter(it, gSymbols)
|
||||||
|
|
||||||
proc fileIdx(w: PRodWriter, filename: string): int =
|
proc fileIdx(w: PRodWriter, filename: string): int =
|
||||||
|
|
@ -74,175 +72,246 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter =
|
||||||
result.tstack = @[]
|
result.tstack = @[]
|
||||||
InitIITable(result.index.tab)
|
InitIITable(result.index.tab)
|
||||||
InitIITable(result.imports.tab)
|
InitIITable(result.imports.tab)
|
||||||
|
result.index.r = ""
|
||||||
|
result.imports.r = ""
|
||||||
result.filename = modfilename
|
result.filename = modfilename
|
||||||
result.crc = crc
|
result.crc = crc
|
||||||
result.module = module
|
result.module = module
|
||||||
result.defines = getDefines()
|
result.defines = getDefines()
|
||||||
result.options = options.gOptions
|
result.options = options.gOptions
|
||||||
result.files = @[]
|
result.files = @[]
|
||||||
|
result.inclDeps = ""
|
||||||
|
result.modDeps = ""
|
||||||
|
result.interf = newStringOfCap(2_000)
|
||||||
|
result.compilerProcs = ""
|
||||||
|
result.converters = ""
|
||||||
|
result.init = ""
|
||||||
|
result.data = newStringOfCap(12_000)
|
||||||
|
|
||||||
proc addModDep(w: PRodWriter, dep: string) =
|
proc addModDep(w: PRodWriter, dep: string) =
|
||||||
if w.modDeps != nil: app(w.modDeps, " ")
|
if w.modDeps.len != 0: add(w.modDeps, ' ')
|
||||||
app(w.modDeps, encodeInt(fileIdx(w, dep)))
|
encodeVInt(fileIdx(w, dep), w.modDeps)
|
||||||
|
|
||||||
const
|
const
|
||||||
rodNL = "\x0A"
|
rodNL = "\x0A"
|
||||||
|
|
||||||
proc addInclDep(w: PRodWriter, dep: string) =
|
proc addInclDep(w: PRodWriter, dep: string) =
|
||||||
app(w.inclDeps, encodeInt(fileIdx(w, dep)))
|
encodeVInt(fileIdx(w, dep), w.inclDeps)
|
||||||
app(w.inclDeps, " ")
|
add(w.inclDeps, " ")
|
||||||
app(w.inclDeps, encodeInt(crcFromFile(dep)))
|
encodeVInt(crcFromFile(dep), w.inclDeps)
|
||||||
app(w.inclDeps, rodNL)
|
add(w.inclDeps, rodNL)
|
||||||
|
|
||||||
proc pushType(w: PRodWriter, t: PType) =
|
proc pushType(w: PRodWriter, t: PType) =
|
||||||
# check so that the stack does not grow too large:
|
# check so that the stack does not grow too large:
|
||||||
if IiTableGet(w.index.tab, t.id) == invalidKey:
|
if IiTableGet(w.index.tab, t.id) == invalidKey:
|
||||||
var L = len(w.tstack)
|
w.tstack.add(t)
|
||||||
setlen(w.tstack, L + 1)
|
|
||||||
w.tstack[L] = t
|
|
||||||
|
|
||||||
proc pushSym(w: PRodWriter, s: PSym) =
|
proc pushSym(w: PRodWriter, s: PSym) =
|
||||||
# check so that the stack does not grow too large:
|
# check so that the stack does not grow too large:
|
||||||
if IiTableGet(w.index.tab, s.id) == invalidKey:
|
if IiTableGet(w.index.tab, s.id) == invalidKey:
|
||||||
var L = len(w.sstack)
|
w.sstack.add(s)
|
||||||
setlen(w.sstack, L + 1)
|
|
||||||
w.sstack[L] = s
|
|
||||||
|
|
||||||
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode): PRope =
|
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||||
|
result: var string) =
|
||||||
if n == nil:
|
if n == nil:
|
||||||
# nil nodes have to be stored too:
|
# nil nodes have to be stored too:
|
||||||
return toRope("()")
|
result.add("()")
|
||||||
result = toRope("(")
|
return
|
||||||
app(result, encodeInt(ord(n.kind)))
|
result.add('(')
|
||||||
|
encodeVInt(ord(n.kind), result)
|
||||||
# we do not write comments for now
|
# we do not write comments for now
|
||||||
# Line information takes easily 20% or more of the filesize! Therefore we
|
# Line information takes easily 20% or more of the filesize! Therefore we
|
||||||
# omit line information if it is the same as the father's line information:
|
# omit line information if it is the same as the father's line information:
|
||||||
if finfo.fileIndex != n.info.fileIndex:
|
if finfo.fileIndex != n.info.fileIndex:
|
||||||
appf(result, "?$1,$2,$3", [encodeInt(n.info.col), encodeInt(n.info.line),
|
result.add('?')
|
||||||
encodeInt(fileIdx(w, toFilename(n.info)))])
|
encodeVInt(n.info.col, result)
|
||||||
|
result.add(',')
|
||||||
|
encodeVInt(n.info.line, result)
|
||||||
|
result.add(',')
|
||||||
|
encodeVInt(fileIdx(w, toFilename(n.info)), result)
|
||||||
elif finfo.line != n.info.line:
|
elif finfo.line != n.info.line:
|
||||||
appf(result, "?$1,$2", [encodeInt(n.info.col), encodeInt(n.info.line)])
|
result.add('?')
|
||||||
|
encodeVInt(n.info.col, result)
|
||||||
|
result.add(',')
|
||||||
|
encodeVInt(n.info.line, result)
|
||||||
elif finfo.col != n.info.col:
|
elif finfo.col != n.info.col:
|
||||||
appf(result, "?$1", [encodeInt(n.info.col)])
|
result.add('?')
|
||||||
|
encodeVInt(n.info.col, result)
|
||||||
# No need to output the file index, as this is the serialization of one
|
# No need to output the file index, as this is the serialization of one
|
||||||
# file.
|
# file.
|
||||||
var f = n.flags * PersistentNodeFlags
|
var f = n.flags * PersistentNodeFlags
|
||||||
if f != {}: appf(result, "$$$1", [encodeInt(cast[int32](f))])
|
if f != {}:
|
||||||
|
result.add('$')
|
||||||
|
encodeVInt(cast[int32](f), result)
|
||||||
if n.typ != nil:
|
if n.typ != nil:
|
||||||
appf(result, "^$1", [encodeInt(n.typ.id)])
|
result.add('^')
|
||||||
|
encodeVInt(n.typ.id, result)
|
||||||
pushType(w, n.typ)
|
pushType(w, n.typ)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkInt64Lit:
|
||||||
if n.intVal != 0: appf(result, "!$1", [encodeInt(n.intVal)])
|
if n.intVal != 0:
|
||||||
|
result.add('!')
|
||||||
|
encodeVBiggestInt(n.intVal, result)
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat64Lit:
|
||||||
if n.floatVal != 0.0: appf(result, "!$1", [encodeStr(w, $n.floatVal)])
|
if n.floatVal != 0.0:
|
||||||
|
result.add('!')
|
||||||
|
encodeStr($n.floatVal, result)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if n.strVal != "": appf(result, "!$1", [encodeStr(w, n.strVal)])
|
if n.strVal != "":
|
||||||
|
result.add('!')
|
||||||
|
encodeStr(n.strVal, result)
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
appf(result, "!$1", [encodeStr(w, n.ident.s)])
|
result.add('!')
|
||||||
|
encodeStr(n.ident.s, result)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
appf(result, "!$1", [encodeInt(n.sym.id)])
|
result.add('!')
|
||||||
|
encodeVInt(n.sym.id, result)
|
||||||
pushSym(w, n.sym)
|
pushSym(w, n.sym)
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
app(result, encodeNode(w, n.info, n.sons[i]))
|
encodeNode(w, n.info, n.sons[i], result)
|
||||||
app(result, ")")
|
add(result, ')')
|
||||||
|
|
||||||
proc encodeLoc(w: PRodWriter, loc: TLoc): PRope =
|
proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
|
||||||
result = nil
|
var oldLen = result.len
|
||||||
if loc.k != low(loc.k): app(result, encodeInt(ord(loc.k)))
|
result.add('<')
|
||||||
if loc.s != low(loc.s): appf(result, "*$1", [encodeInt(ord(loc.s))])
|
if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
|
||||||
if loc.flags != {}: appf(result, "$$$1", [encodeInt(cast[int32](loc.flags))])
|
if loc.s != low(loc.s):
|
||||||
|
add(result, '*')
|
||||||
|
encodeVInt(ord(loc.s), result)
|
||||||
|
if loc.flags != {}:
|
||||||
|
add(result, '$')
|
||||||
|
encodeVInt(cast[int32](loc.flags), result)
|
||||||
if loc.t != nil:
|
if loc.t != nil:
|
||||||
appf(result, "^$1", [encodeInt(loc.t.id)])
|
add(result, '^')
|
||||||
|
encodeVInt(cast[int32](loc.t.id), result)
|
||||||
pushType(w, loc.t)
|
pushType(w, loc.t)
|
||||||
if loc.r != nil: appf(result, "!$1", [encodeStr(w, ropeToStr(loc.r))])
|
if loc.r != nil:
|
||||||
if loc.a != 0: appf(result, "?$1", [encodeInt(loc.a)])
|
add(result, '!')
|
||||||
if result != nil: result = ropef("<$1>", [result])
|
encodeStr(ropeToStr(loc.r), result)
|
||||||
|
if loc.a != 0:
|
||||||
|
add(result, '?')
|
||||||
|
encodeVInt(loc.a, result)
|
||||||
|
if oldlen + 1 == result.len:
|
||||||
|
# no data was necessary, so remove the '<' again:
|
||||||
|
setLen(result, oldLen)
|
||||||
|
else:
|
||||||
|
add(result, '>')
|
||||||
|
|
||||||
proc encodeType(w: PRodWriter, t: PType): PRope =
|
proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
||||||
if t == nil:
|
if t == nil:
|
||||||
# nil nodes have to be stored too:
|
# nil nodes have to be stored too:
|
||||||
return toRope("[]")
|
result.add("[]")
|
||||||
result = nil
|
return
|
||||||
|
# we need no surrounding [] here because the type is in a line of its own
|
||||||
if t.kind == tyForward: InternalError("encodeType: tyForward")
|
if t.kind == tyForward: InternalError("encodeType: tyForward")
|
||||||
app(result, encodeInt(ord(t.kind)))
|
encodeVInt(ord(t.kind), result)
|
||||||
appf(result, "+$1", [encodeInt(t.id)])
|
add(result, '+')
|
||||||
if t.n != nil: app(result, encodeNode(w, UnknownLineInfo(), t.n))
|
encodeVInt(t.id, result)
|
||||||
if t.flags != {}: appf(result, "$$$1", [encodeInt(cast[int32](t.flags))])
|
if t.n != nil:
|
||||||
|
encodeNode(w, UnknownLineInfo(), t.n, result)
|
||||||
|
if t.flags != {}:
|
||||||
|
add(result, '$')
|
||||||
|
encodeVInt(cast[int32](t.flags), result)
|
||||||
if t.callConv != low(t.callConv):
|
if t.callConv != low(t.callConv):
|
||||||
appf(result, "?$1", [encodeInt(ord(t.callConv))])
|
add(result, '?')
|
||||||
|
encodeVInt(ord(t.callConv), result)
|
||||||
if t.owner != nil:
|
if t.owner != nil:
|
||||||
appf(result, "*$1", [encodeInt(t.owner.id)])
|
add(result, '*')
|
||||||
|
encodeVInt(t.owner.id, result)
|
||||||
pushSym(w, t.owner)
|
pushSym(w, t.owner)
|
||||||
if t.sym != nil:
|
if t.sym != nil:
|
||||||
appf(result, "&$1", [encodeInt(t.sym.id)])
|
add(result, '&')
|
||||||
|
encodeVInt(t.sym.id, result)
|
||||||
pushSym(w, t.sym)
|
pushSym(w, t.sym)
|
||||||
if t.size != - 1: appf(result, "/$1", [encodeInt(t.size)])
|
if t.size != - 1:
|
||||||
if t.align != 2: appf(result, "=$1", [encodeInt(t.align)])
|
add(result, '/')
|
||||||
if t.containerID != 0: appf(result, "@$1", [encodeInt(t.containerID)])
|
encodeVBiggestInt(t.size, result)
|
||||||
app(result, encodeLoc(w, t.loc))
|
if t.align != 2:
|
||||||
|
add(result, '=')
|
||||||
|
encodeVInt(t.align, result)
|
||||||
|
if t.containerID != 0:
|
||||||
|
add(result, '@')
|
||||||
|
encodeVInt(t.containerID, result)
|
||||||
|
encodeLoc(w, t.loc, result)
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
if t.sons[i] == nil:
|
if t.sons[i] == nil:
|
||||||
app(result, "^()")
|
add(result, "^()")
|
||||||
else:
|
else:
|
||||||
appf(result, "^$1", [encodeInt(t.sons[i].id)])
|
add(result, '^')
|
||||||
|
encodeVInt(t.sons[i].id, result)
|
||||||
pushType(w, t.sons[i])
|
pushType(w, t.sons[i])
|
||||||
|
|
||||||
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo): PRope =
|
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
|
||||||
result = nil
|
add(result, '|')
|
||||||
appf(result, "|$1", [encodeInt(ord(lib.kind))])
|
encodeVInt(ord(lib.kind), result)
|
||||||
appf(result, "|$1", [encodeStr(w, ropeToStr(lib.name))])
|
add(result, '|')
|
||||||
appf(result, "|$1", [encodeNode(w, info, lib.path)])
|
encodeStr(ropeToStr(lib.name), result)
|
||||||
|
add(result, '|')
|
||||||
|
encodeNode(w, info, lib.path, result)
|
||||||
|
|
||||||
proc encodeSym(w: PRodWriter, s: PSym): PRope =
|
proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
|
||||||
var
|
|
||||||
codeAst: PNode
|
|
||||||
col, line: PRope
|
|
||||||
codeAst = nil
|
|
||||||
if s == nil:
|
if s == nil:
|
||||||
# nil nodes have to be stored too:
|
# nil nodes have to be stored too:
|
||||||
return toRope("{}")
|
result.add("{}")
|
||||||
result = nil
|
return
|
||||||
app(result, encodeInt(ord(s.kind)))
|
# we need no surrounding {} here because the symbol is in a line of its own
|
||||||
appf(result, "+$1", [encodeInt(s.id)])
|
encodeVInt(ord(s.kind), result)
|
||||||
appf(result, "&$1", [encodeStr(w, s.name.s)])
|
result.add('+')
|
||||||
|
encodeVInt(s.id, result)
|
||||||
|
result.add('&')
|
||||||
|
encodeStr(s.name.s, result)
|
||||||
if s.typ != nil:
|
if s.typ != nil:
|
||||||
appf(result, "^$1", [encodeInt(s.typ.id)])
|
result.add('^')
|
||||||
|
encodeVInt(s.typ.id, result)
|
||||||
pushType(w, s.typ)
|
pushType(w, s.typ)
|
||||||
if s.info.col == int16(- 1): col = nil
|
result.add('?')
|
||||||
else: col = encodeInt(s.info.col)
|
if s.info.col != -1'i16: encodeVInt(s.info.col, result)
|
||||||
if s.info.line == int16(- 1): line = nil
|
result.add(',')
|
||||||
else: line = encodeInt(s.info.line)
|
if s.info.line != -1'i16: encodeVInt(s.info.line, result)
|
||||||
appf(result, "?$1,$2,$3",
|
result.add(',')
|
||||||
[col, line, encodeInt(fileIdx(w, toFilename(s.info)))])
|
encodeVInt(fileIdx(w, toFilename(s.info)), result)
|
||||||
if s.owner != nil:
|
if s.owner != nil:
|
||||||
appf(result, "*$1", [encodeInt(s.owner.id)])
|
result.add('*')
|
||||||
|
encodeVInt(s.owner.id, result)
|
||||||
pushSym(w, s.owner)
|
pushSym(w, s.owner)
|
||||||
if s.flags != {}: appf(result, "$$$1", [encodeInt(cast[int32](s.flags))])
|
if s.flags != {}:
|
||||||
if s.magic != mNone: appf(result, "@$1", [encodeInt(ord(s.magic))])
|
result.add('$')
|
||||||
if (s.ast != nil):
|
encodeVInt(cast[int32](s.flags), result)
|
||||||
|
if s.magic != mNone:
|
||||||
|
result.add('@')
|
||||||
|
encodeVInt(ord(s.magic), result)
|
||||||
|
if s.ast != nil:
|
||||||
|
var codeAst: PNode = nil
|
||||||
if not astNeeded(s):
|
if not astNeeded(s):
|
||||||
codeAst = s.ast.sons[codePos]
|
codeAst = s.ast.sons[codePos]
|
||||||
|
# ugly hack to not store the AST:
|
||||||
s.ast.sons[codePos] = nil
|
s.ast.sons[codePos] = nil
|
||||||
app(result, encodeNode(w, s.info, s.ast))
|
encodeNode(w, s.info, s.ast, result)
|
||||||
if codeAst != nil:
|
if codeAst != nil:
|
||||||
|
# resore the AST:
|
||||||
s.ast.sons[codePos] = codeAst
|
s.ast.sons[codePos] = codeAst
|
||||||
if s.options != w.options:
|
if s.options != w.options:
|
||||||
appf(result, "!$1", [encodeInt(cast[int32](s.options))])
|
result.add('!')
|
||||||
if s.position != 0: appf(result, "%$1", [encodeInt(s.position)])
|
encodeVInt(cast[int32](s.options), result)
|
||||||
if s.offset != - 1: appf(result, "`$1", [encodeInt(s.offset)])
|
if s.position != 0:
|
||||||
app(result, encodeLoc(w, s.loc))
|
result.add('%')
|
||||||
if s.annex != nil: app(result, encodeLib(w, s.annex, s.info))
|
encodeVInt(s.position, result)
|
||||||
|
if s.offset != - 1:
|
||||||
|
result.add('`')
|
||||||
|
encodeVInt(s.offset, result)
|
||||||
|
encodeLoc(w, s.loc, result)
|
||||||
|
if s.annex != nil: encodeLib(w, s.annex, s.info, result)
|
||||||
|
|
||||||
proc addToIndex(w: var TIndex, key, val: int) =
|
proc addToIndex(w: var TIndex, key, val: int) =
|
||||||
if key - w.lastIdxKey == 1:
|
if key - w.lastIdxKey == 1:
|
||||||
# we do not store a key-diff of 1 to safe space
|
# we do not store a key-diff of 1 to safe space
|
||||||
app(w.r, encodeInt(val - w.lastIdxVal))
|
encodeVInt(val - w.lastIdxVal, w.r)
|
||||||
app(w.r, rodNL)
|
|
||||||
else:
|
else:
|
||||||
appf(w.r, "$1 $2" & rodNL,
|
encodeVInt(key - w.lastIdxKey, w.r)
|
||||||
[encodeInt(key - w.lastIdxKey), encodeInt(val - w.lastIdxVal)])
|
add(w.r, ' ')
|
||||||
|
encodeVInt(val - w.lastIdxVal, w.r)
|
||||||
|
add(w.r, rodNL)
|
||||||
w.lastIdxKey = key
|
w.lastIdxKey = key
|
||||||
w.lastIdxVal = val
|
w.lastIdxVal = val
|
||||||
IiTablePut(w.tab, key, val)
|
IiTablePut(w.tab, key, val)
|
||||||
|
|
@ -250,29 +319,32 @@ proc addToIndex(w: var TIndex, key, val: int) =
|
||||||
var debugWritten: TIntSet
|
var debugWritten: TIntSet
|
||||||
|
|
||||||
proc symStack(w: PRodWriter) =
|
proc symStack(w: PRodWriter) =
|
||||||
var
|
var i = 0
|
||||||
i, L: int
|
|
||||||
s, m: PSym
|
|
||||||
i = 0
|
|
||||||
while i < len(w.sstack):
|
while i < len(w.sstack):
|
||||||
s = w.sstack[i]
|
var s = w.sstack[i]
|
||||||
if IiTableGet(w.index.tab, s.id) == invalidKey:
|
if IiTableGet(w.index.tab, s.id) == invalidKey:
|
||||||
m = getModule(s)
|
var m = getModule(s)
|
||||||
if m == nil: InternalError("symStack: module nil: " & s.name.s)
|
if m == nil: InternalError("symStack: module nil: " & s.name.s)
|
||||||
if (m.id == w.module.id) or (sfFromGeneric in s.flags):
|
if (m.id == w.module.id) or (sfFromGeneric in s.flags):
|
||||||
# put definition in here
|
# put definition in here
|
||||||
L = ropeLen(w.data)
|
var L = w.data.len
|
||||||
addToIndex(w.index, s.id, L) #intSetIncl(debugWritten, s.id);
|
addToIndex(w.index, s.id, L)
|
||||||
app(w.data, encodeSym(w, s))
|
#intSetIncl(debugWritten, s.id)
|
||||||
app(w.data, rodNL)
|
encodeSym(w, s, w.data)
|
||||||
|
add(w.data, rodNL)
|
||||||
if sfExported in s.flags:
|
if sfExported in s.flags:
|
||||||
appf(w.interf, "$1 $2" & rodNL, [encode(s.name.s), encodeInt(s.id)])
|
encodeStr(s.name.s, w.interf)
|
||||||
|
add(w.interf, ' ')
|
||||||
|
encodeVInt(s.id, w.interf)
|
||||||
|
add(w.interf, rodNL)
|
||||||
if sfCompilerProc in s.flags:
|
if sfCompilerProc in s.flags:
|
||||||
appf(w.compilerProcs, "$1 $2" & rodNL,
|
encodeStr(s.name.s, w.compilerProcs)
|
||||||
[encode(s.name.s), encodeInt(s.id)])
|
add(w.compilerProcs, ' ')
|
||||||
|
encodeVInt(s.id, w.compilerProcs)
|
||||||
|
add(w.compilerProcs, rodNL)
|
||||||
if s.kind == skConverter:
|
if s.kind == skConverter:
|
||||||
if w.converters != nil: app(w.converters, " ")
|
if w.converters.len != 0: add(w.converters, ' ')
|
||||||
app(w.converters, encodeInt(s.id))
|
encodeVInt(s.id, w.converters)
|
||||||
elif IiTableGet(w.imports.tab, s.id) == invalidKey:
|
elif IiTableGet(w.imports.tab, s.id) == invalidKey:
|
||||||
addToIndex(w.imports, s.id, m.id) #if not Contains(debugWritten, s.id):
|
addToIndex(w.imports, s.id, m.id) #if not Contains(debugWritten, s.id):
|
||||||
# MessageOut(w.filename);
|
# MessageOut(w.filename);
|
||||||
|
|
@ -287,10 +359,10 @@ proc typeStack(w: PRodWriter) =
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < len(w.tstack):
|
while i < len(w.tstack):
|
||||||
if IiTableGet(w.index.tab, w.tstack[i].id) == invalidKey:
|
if IiTableGet(w.index.tab, w.tstack[i].id) == invalidKey:
|
||||||
var L = ropeLen(w.data)
|
var L = w.data.len
|
||||||
addToIndex(w.index, w.tstack[i].id, L)
|
addToIndex(w.index, w.tstack[i].id, L)
|
||||||
app(w.data, encodeType(w, w.tstack[i]))
|
encodeType(w, w.tstack[i], w.data)
|
||||||
app(w.data, rodNL)
|
add(w.data, rodNL)
|
||||||
inc(i)
|
inc(i)
|
||||||
setlen(w.tstack, 0)
|
setlen(w.tstack, 0)
|
||||||
|
|
||||||
|
|
@ -309,66 +381,88 @@ proc addInterfaceSym(w: PRodWriter, s: PSym) =
|
||||||
rawAddInterfaceSym(w, s)
|
rawAddInterfaceSym(w, s)
|
||||||
|
|
||||||
proc addStmt(w: PRodWriter, n: PNode) =
|
proc addStmt(w: PRodWriter, n: PNode) =
|
||||||
app(w.init, encodeInt(ropeLen(w.data)))
|
encodeVInt(w.data.len, w.init)
|
||||||
app(w.init, rodNL)
|
add(w.init, rodNL)
|
||||||
app(w.data, encodeNode(w, UnknownLineInfo(), n))
|
encodeNode(w, UnknownLineInfo(), n, w.data)
|
||||||
app(w.data, rodNL)
|
add(w.data, rodNL)
|
||||||
processStacks(w)
|
processStacks(w)
|
||||||
|
|
||||||
proc writeRod(w: PRodWriter) =
|
proc writeRod(w: PRodWriter) =
|
||||||
processStacks(w) # write header:
|
processStacks(w)
|
||||||
var content = toRope("NIM:")
|
var f: TFile
|
||||||
app(content, toRope(FileVersion))
|
if not open(f, completeGeneratedFilePath(changeFileExt(w.filename, "rod")),
|
||||||
app(content, rodNL)
|
fmWrite):
|
||||||
app(content, toRope("ID:"))
|
return
|
||||||
app(content, encodeInt(w.module.id))
|
# write header:
|
||||||
app(content, rodNL)
|
f.write("NIM:")
|
||||||
app(content, toRope("CRC:"))
|
f.write(FileVersion)
|
||||||
app(content, encodeInt(w.crc))
|
f.write(rodNL)
|
||||||
app(content, rodNL)
|
var id = "ID:"
|
||||||
app(content, toRope("OPTIONS:"))
|
encodeVInt(w.module.id, id)
|
||||||
app(content, encodeInt(cast[int32](w.options)))
|
f.write(id)
|
||||||
app(content, rodNL)
|
f.write(rodNL)
|
||||||
app(content, toRope("DEFINES:"))
|
|
||||||
app(content, w.defines)
|
var crc = "CRC:"
|
||||||
app(content, rodNL)
|
encodeVInt(w.crc, crc)
|
||||||
app(content, toRope("FILES(" & rodNL))
|
f.write(crc)
|
||||||
|
f.write(rodNL)
|
||||||
|
|
||||||
|
var options = "OPTIONS:"
|
||||||
|
encodeVInt(cast[int32](w.options), options)
|
||||||
|
f.write(options)
|
||||||
|
f.write(rodNL)
|
||||||
|
|
||||||
|
f.write("DEFINES:")
|
||||||
|
f.write(w.defines)
|
||||||
|
f.write(rodNL)
|
||||||
|
|
||||||
|
var files = "FILES(" & rodNL
|
||||||
for i in countup(0, high(w.files)):
|
for i in countup(0, high(w.files)):
|
||||||
app(content, encode(w.files[i]))
|
encodeStr(w.files[i], files)
|
||||||
app(content, rodNL)
|
files.add(rodNL)
|
||||||
app(content, toRope(')' & rodNL))
|
f.write(files)
|
||||||
app(content, toRope("INCLUDES(" & rodNL))
|
f.write(')' & rodNL)
|
||||||
app(content, w.inclDeps)
|
|
||||||
app(content, toRope(')' & rodNL))
|
f.write("INCLUDES(" & rodNL)
|
||||||
app(content, toRope("DEPS:"))
|
f.write(w.inclDeps)
|
||||||
app(content, w.modDeps)
|
f.write(')' & rodNL)
|
||||||
app(content, rodNL)
|
|
||||||
app(content, toRope("INTERF(" & rodNL))
|
f.write("DEPS:")
|
||||||
app(content, w.interf)
|
f.write(w.modDeps)
|
||||||
app(content, toRope(')' & rodNL))
|
f.write(rodNL)
|
||||||
app(content, toRope("COMPILERPROCS(" & rodNL))
|
|
||||||
app(content, w.compilerProcs)
|
f.write("INTERF(" & rodNL)
|
||||||
app(content, toRope(')' & rodNL))
|
f.write(w.interf)
|
||||||
app(content, toRope("INDEX(" & rodNL))
|
f.write(')' & rodNL)
|
||||||
app(content, w.index.r)
|
|
||||||
app(content, toRope(')' & rodNL))
|
f.write("COMPILERPROCS(" & rodNL)
|
||||||
app(content, toRope("IMPORTS(" & rodNL))
|
f.write(w.compilerProcs)
|
||||||
app(content, w.imports.r)
|
f.write(')' & rodNL)
|
||||||
app(content, toRope(')' & rodNL))
|
|
||||||
app(content, toRope("CONVERTERS:"))
|
f.write("INDEX(" & rodNL)
|
||||||
app(content, w.converters)
|
f.write(w.index.r)
|
||||||
app(content, toRope(rodNL))
|
f.write(')' & rodNL)
|
||||||
app(content, toRope("INIT(" & rodNL))
|
|
||||||
app(content, w.init)
|
f.write("IMPORTS(" & rodNL)
|
||||||
app(content, toRope(')' & rodNL))
|
f.write(w.imports.r)
|
||||||
app(content, toRope("DATA(" & rodNL))
|
f.write(')' & rodNL)
|
||||||
app(content, w.data)
|
|
||||||
app(content, toRope(')' & rodNL))
|
f.write("CONVERTERS:")
|
||||||
#MessageOut('interf ' + ToString(ropeLen(w.interf)));
|
f.write(w.converters)
|
||||||
#MessageOut('index ' + ToString(ropeLen(w.indexRope)));
|
f.write(rodNL)
|
||||||
#MessageOut('init ' + ToString(ropeLen(w.init)));
|
|
||||||
#MessageOut('data ' + ToString(ropeLen(w.data)));
|
f.write("INIT(" & rodNL)
|
||||||
writeRope(content, completeGeneratedFilePath(changeFileExt(w.filename, "rod")))
|
f.write(w.init)
|
||||||
|
f.write(')' & rodNL)
|
||||||
|
|
||||||
|
f.write("DATA(" & rodNL)
|
||||||
|
f.write(w.data)
|
||||||
|
f.write(')' & rodNL)
|
||||||
|
f.close()
|
||||||
|
#MessageOut('interf ' + ToString(ropeLen(w.interf)))
|
||||||
|
#MessageOut('index ' + ToString(ropeLen(w.indexRope)))
|
||||||
|
#MessageOut('init ' + ToString(ropeLen(w.init)))
|
||||||
|
#MessageOut('data ' + ToString(ropeLen(w.data)))
|
||||||
|
|
||||||
proc process(c: PPassContext, n: PNode): PNode =
|
proc process(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -438,6 +532,7 @@ proc myClose(c: PPassContext, n: PNode): PNode =
|
||||||
var w = PRodWriter(c)
|
var w = PRodWriter(c)
|
||||||
writeRod(w)
|
writeRod(w)
|
||||||
result = n
|
result = n
|
||||||
|
idgen.saveMaxIds(options.projectPath / options.projectName)
|
||||||
|
|
||||||
proc rodwritePass(): TPass =
|
proc rodwritePass(): TPass =
|
||||||
initPass(result)
|
initPass(result)
|
||||||
|
|
@ -446,4 +541,4 @@ proc rodwritePass(): TPass =
|
||||||
result.close = myClose
|
result.close = myClose
|
||||||
result.process = process
|
result.process = process
|
||||||
|
|
||||||
debugWritten= initIntSet()
|
debugWritten = initIntSet()
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import
|
||||||
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
|
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
|
||||||
magicsys, parser, nversion, semdata, nimsets, semfold, importer,
|
magicsys, parser, nversion, semdata, nimsets, semfold, importer,
|
||||||
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
|
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
|
||||||
semthreads, intsets, transf, evals
|
semthreads, intsets, transf, evals, idgen
|
||||||
|
|
||||||
proc semPass*(): TPass
|
proc semPass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ proc SemReturn(c: PContext, n: PNode): PNode =
|
||||||
globalError(n.info, errXNotAllowedHere, "\'return\'")
|
globalError(n.info, errXNotAllowedHere, "\'return\'")
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
# transform ``return expr`` to ``result = expr; return``
|
# transform ``return expr`` to ``result = expr; return``
|
||||||
if c.p.resultSym == nil: InternalError(n.info, "semReturn")
|
if c.p.resultSym == nil: globalError(n.info, errNoReturnTypeDeclared)
|
||||||
var a = newNodeI(nkAsgn, n.sons[0].info)
|
var a = newNodeI(nkAsgn, n.sons[0].info)
|
||||||
addSon(a, newSymNode(c.p.resultSym))
|
addSon(a, newSymNode(c.p.resultSym))
|
||||||
addSon(a, n.sons[0])
|
addSon(a, n.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Implements a table from trees to trees. Does structural equavilent checking.
|
# Implements a table from trees to trees. Does structural equivalence checking.
|
||||||
|
|
||||||
import
|
import
|
||||||
hashes, ast, astalgo, types
|
hashes, ast, astalgo, types
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
|
||||||
## of the first row. Returns "" if the dataset contains no rows.
|
## of the first row. Returns "" if the dataset contains no rows.
|
||||||
var stmt = setupQuery(db, query, args)
|
var stmt = setupQuery(db, query, args)
|
||||||
if step(stmt) == SQLITE_ROW:
|
if step(stmt) == SQLITE_ROW:
|
||||||
result = newString(column_bytes(stmt, 0))
|
result = newStringOfCap(column_bytes(stmt, 0))
|
||||||
setLen(result, 0)
|
|
||||||
add(result, column_text(stmt, 0))
|
add(result, column_text(stmt, 0))
|
||||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
36
todo.txt
36
todo.txt
|
|
@ -9,6 +9,7 @@ Version 0.8.14
|
||||||
- optional indentation for 'case' statement
|
- optional indentation for 'case' statement
|
||||||
- document & test splicing; don't forget to test negative indexes
|
- document & test splicing; don't forget to test negative indexes
|
||||||
- thread local vs. global raiseHook()
|
- thread local vs. global raiseHook()
|
||||||
|
- incremental compilation (!)
|
||||||
|
|
||||||
|
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
|
|
@ -105,41 +106,6 @@ Low priority
|
||||||
- timeout for locks
|
- timeout for locks
|
||||||
|
|
||||||
|
|
||||||
Super operators
|
|
||||||
===============
|
|
||||||
|
|
||||||
macro (pattern) [T](arg: array[T]) =
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Patterns
|
|
||||||
--------
|
|
||||||
|
|
||||||
Patterns are PEGs over the Nimrod AST. Patterns consist of:
|
|
||||||
|
|
||||||
type
|
|
||||||
TPatternKind = enum
|
|
||||||
pkAny, ## any node (.)
|
|
||||||
pkNodeClass, ## set of node kinds
|
|
||||||
pkTerminal, ## 'xyz'
|
|
||||||
pkNonTerminal, ## a
|
|
||||||
pkSequence, ## a b c
|
|
||||||
pkOrderedChoice, ## a / b / c
|
|
||||||
pkGreedyRep, ## a*
|
|
||||||
## a+ --> (a a*)
|
|
||||||
pkOption, ## a?
|
|
||||||
pkAndPredicate, ## &a
|
|
||||||
pkNotPredicate, ## !a
|
|
||||||
pkCapture, ## {a}
|
|
||||||
pkBackRef, ## $i
|
|
||||||
pkSearch, ## @a
|
|
||||||
pkCapturedSearch, ## {@} a
|
|
||||||
pkRule, ## a <- b
|
|
||||||
pkGrammar, ## list of rules
|
|
||||||
|
|
||||||
Choice operator requires capture.
|
|
||||||
|
|
||||||
|
|
||||||
Version 2
|
Version 2
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue