compiler: Trim .nim files trailing whitespace
via OSX: find . -name '*.nim' -exec sed -i '' -E 's/[[:space:]]+$//' {} +
This commit is contained in:
parent
37fe21b64a
commit
d681812465
32 changed files with 570 additions and 570 deletions
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, types, trees, intsets, msgs
|
ast, astalgo, types, trees, intsets, msgs
|
||||||
|
|
||||||
type
|
type
|
||||||
TAnalysisResult* = enum
|
TAnalysisResult* = enum
|
||||||
arNo, arMaybe, arYes
|
arNo, arMaybe, arYes
|
||||||
|
|
@ -21,42 +21,42 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult
|
||||||
proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
|
proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
|
||||||
result = arNo
|
result = arNo
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result = isPartOfAux(n.sons[i], b, marker)
|
result = isPartOfAux(n.sons[i], b, marker)
|
||||||
if result == arYes: return
|
if result == arYes: return
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
assert(n.sons[0].kind == nkSym)
|
assert(n.sons[0].kind == nkSym)
|
||||||
result = isPartOfAux(n.sons[0], b, marker)
|
result = isPartOfAux(n.sons[0], b, marker)
|
||||||
if result == arYes: return
|
if result == arYes: return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
|
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
|
||||||
if result == arYes: return
|
if result == arYes: return
|
||||||
else: internalError("isPartOfAux(record case branch)")
|
else: internalError("isPartOfAux(record case branch)")
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result = isPartOfAux(n.sym.typ, b, marker)
|
result = isPartOfAux(n.sym.typ, b, marker)
|
||||||
else: internalError(n.info, "isPartOfAux()")
|
else: internalError(n.info, "isPartOfAux()")
|
||||||
|
|
||||||
proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
|
proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
|
||||||
result = arNo
|
result = arNo
|
||||||
if a == nil or b == nil: return
|
if a == nil or b == nil: return
|
||||||
if containsOrIncl(marker, a.id): return
|
if containsOrIncl(marker, a.id): return
|
||||||
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
|
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = isPartOfAux(a.sons[0], b, marker)
|
result = isPartOfAux(a.sons[0], b, marker)
|
||||||
if result == arNo: result = isPartOfAux(a.n, b, marker)
|
if result == arNo: result = isPartOfAux(a.n, b, marker)
|
||||||
of tyGenericInst, tyDistinct:
|
of tyGenericInst, tyDistinct:
|
||||||
result = isPartOfAux(lastSon(a), b, marker)
|
result = isPartOfAux(lastSon(a), b, marker)
|
||||||
of tyArray, tyArrayConstr, tySet, tyTuple:
|
of tyArray, tyArrayConstr, tySet, tyTuple:
|
||||||
for i in countup(0, sonsLen(a) - 1):
|
for i in countup(0, sonsLen(a) - 1):
|
||||||
result = isPartOfAux(a.sons[i], b, marker)
|
result = isPartOfAux(a.sons[i], b, marker)
|
||||||
if result == arYes: return
|
if result == arYes: return
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc isPartOf(a, b: PType): TAnalysisResult =
|
proc isPartOf(a, b: PType): TAnalysisResult =
|
||||||
## checks iff 'a' can be part of 'b'. Iterates over VALUE types!
|
## checks iff 'a' can be part of 'b'. Iterates over VALUE types!
|
||||||
var marker = initIntSet()
|
var marker = initIntSet()
|
||||||
# watch out: parameters reversed because I'm too lazy to change the code...
|
# watch out: parameters reversed because I'm too lazy to change the code...
|
||||||
|
|
@ -70,14 +70,14 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
## type. Since however type analysis is more expensive, we perform it only
|
## type. Since however type analysis is more expensive, we perform it only
|
||||||
## if necessary.
|
## if necessary.
|
||||||
##
|
##
|
||||||
## cases:
|
## cases:
|
||||||
##
|
##
|
||||||
## YES-cases:
|
## YES-cases:
|
||||||
## x <| x # for general trees
|
## x <| x # for general trees
|
||||||
## x[] <| x
|
## x[] <| x
|
||||||
## x[i] <| x
|
## x[i] <| x
|
||||||
## x.f <| x
|
## x.f <| x
|
||||||
##
|
##
|
||||||
## NO-cases:
|
## NO-cases:
|
||||||
## x !<| y # depending on type and symbol kind
|
## x !<| y # depending on type and symbol kind
|
||||||
## x[constA] !<| x[constB]
|
## x[constA] !<| x[constB]
|
||||||
|
|
@ -88,16 +88,16 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
##
|
##
|
||||||
## x[] ?<| y[] iff compatible type
|
## x[] ?<| y[] iff compatible type
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
## x[] ?<| y depending on type
|
## x[] ?<| y depending on type
|
||||||
##
|
##
|
||||||
if a.kind == b.kind:
|
if a.kind == b.kind:
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
const varKinds = {skVar, skTemp, skProc}
|
const varKinds = {skVar, skTemp, skProc}
|
||||||
# same symbol: aliasing:
|
# same symbol: aliasing:
|
||||||
if a.sym.id == b.sym.id: result = arYes
|
if a.sym.id == b.sym.id: result = arYes
|
||||||
elif a.sym.kind in varKinds or b.sym.kind in varKinds:
|
elif a.sym.kind in varKinds or b.sym.kind in varKinds:
|
||||||
# actually, a param could alias a var but we know that cannot happen
|
# actually, a param could alias a var but we know that cannot happen
|
||||||
# here. XXX make this more generic
|
# here. XXX make this more generic
|
||||||
result = arNo
|
result = arNo
|
||||||
|
|
@ -110,11 +110,11 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
if len(a) >= 2 and len(b) >= 2:
|
if len(a) >= 2 and len(b) >= 2:
|
||||||
# array accesses:
|
# array accesses:
|
||||||
if result == arYes and isDeepConstExpr(a[1]) and isDeepConstExpr(b[1]):
|
if result == arYes and isDeepConstExpr(a[1]) and isDeepConstExpr(b[1]):
|
||||||
# we know it's the same array and we have 2 constant indexes;
|
# we know it's the same array and we have 2 constant indexes;
|
||||||
# if they are
|
# if they are
|
||||||
var x = if a[1].kind == nkHiddenStdConv: a[1][1] else: a[1]
|
var x = if a[1].kind == nkHiddenStdConv: a[1][1] else: a[1]
|
||||||
var y = if b[1].kind == nkHiddenStdConv: b[1][1] else: b[1]
|
var y = if b[1].kind == nkHiddenStdConv: b[1][1] else: b[1]
|
||||||
|
|
||||||
if sameValue(x, y): result = arYes
|
if sameValue(x, y): result = arYes
|
||||||
else: result = arNo
|
else: result = arNo
|
||||||
# else: maybe and no are accurate
|
# else: maybe and no are accurate
|
||||||
|
|
@ -122,7 +122,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
# pointer derefs:
|
# pointer derefs:
|
||||||
if result != arYes:
|
if result != arYes:
|
||||||
if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
|
if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
|
||||||
|
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
result = isPartOf(a[0], b[0])
|
result = isPartOf(a[0], b[0])
|
||||||
if result != arNo:
|
if result != arNo:
|
||||||
|
|
@ -135,7 +135,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
# weaken because of indirection:
|
# weaken because of indirection:
|
||||||
if result != arYes:
|
if result != arYes:
|
||||||
if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
|
if isPartOf(a.typ, b.typ) != arNo: result = arMaybe
|
||||||
|
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||||
result = isPartOf(a[1], b[1])
|
result = isPartOf(a[1], b[1])
|
||||||
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||||
|
|
@ -144,7 +144,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
# Calls return a new location, so a default of ``arNo`` is fine.
|
# Calls return a new location, so a default of ``arNo`` is fine.
|
||||||
else:
|
else:
|
||||||
# go down recursively; this is quite demanding:
|
# go down recursively; this is quite demanding:
|
||||||
const
|
const
|
||||||
Ix0Kinds = {nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
|
Ix0Kinds = {nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
|
||||||
nkCheckedFieldExpr}
|
nkCheckedFieldExpr}
|
||||||
Ix1Kinds = {nkHiddenStdConv, nkHiddenSubConv, nkConv}
|
Ix1Kinds = {nkHiddenStdConv, nkHiddenSubConv, nkConv}
|
||||||
|
|
@ -153,17 +153,17 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
of Ix0Kinds:
|
of Ix0Kinds:
|
||||||
# a* !<| b.f iff a* !<| b
|
# a* !<| b.f iff a* !<| b
|
||||||
result = isPartOf(a, b[0])
|
result = isPartOf(a, b[0])
|
||||||
|
|
||||||
of DerefKinds:
|
of DerefKinds:
|
||||||
# a* !<| b[] iff
|
# a* !<| b[] iff
|
||||||
if isPartOf(a.typ, b.typ) != arNo:
|
if isPartOf(a.typ, b.typ) != arNo:
|
||||||
result = isPartOf(a, b[0])
|
result = isPartOf(a, b[0])
|
||||||
if result == arNo: result = arMaybe
|
if result == arNo: result = arMaybe
|
||||||
|
|
||||||
of Ix1Kinds:
|
of Ix1Kinds:
|
||||||
# a* !<| T(b) iff a* !<| b
|
# a* !<| T(b) iff a* !<| b
|
||||||
result = isPartOf(a, b[1])
|
result = isPartOf(a, b[1])
|
||||||
|
|
||||||
of nkSym:
|
of nkSym:
|
||||||
# b is an atom, so we have to check a:
|
# b is an atom, so we have to check a:
|
||||||
case a.kind
|
case a.kind
|
||||||
|
|
@ -172,7 +172,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||||
result = isPartOf(a[0], b)
|
result = isPartOf(a[0], b)
|
||||||
of Ix1Kinds:
|
of Ix1Kinds:
|
||||||
result = isPartOf(a[1], b)
|
result = isPartOf(a[1], b)
|
||||||
|
|
||||||
of DerefKinds:
|
of DerefKinds:
|
||||||
if isPartOf(a.typ, b.typ) != arNo:
|
if isPartOf(a.typ, b.typ) != arNo:
|
||||||
result = isPartOf(a[0], b)
|
result = isPartOf(a[0], b)
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
# this unit handles Nim sets; it implements bit sets
|
# this unit handles Nim sets; it implements bit sets
|
||||||
# the code here should be reused in the Nim standard library
|
# the code here should be reused in the Nim standard library
|
||||||
|
|
||||||
type
|
type
|
||||||
TBitSet* = seq[int8] # we use byte here to avoid issues with
|
TBitSet* = seq[int8] # we use byte here to avoid issues with
|
||||||
# cross-compiling; uint would be more efficient
|
# cross-compiling; uint would be more efficient
|
||||||
# however
|
# however
|
||||||
|
|
||||||
const
|
const
|
||||||
ElemSize* = sizeof(int8) * 8
|
ElemSize* = sizeof(int8) * 8
|
||||||
|
|
||||||
proc bitSetInit*(b: var TBitSet, length: int)
|
proc bitSetInit*(b: var TBitSet, length: int)
|
||||||
|
|
@ -30,42 +30,42 @@ proc bitSetEquals*(x, y: TBitSet): bool
|
||||||
proc bitSetContains*(x, y: TBitSet): bool
|
proc bitSetContains*(x, y: TBitSet): bool
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
|
proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
|
||||||
result = (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) !=
|
result = (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) !=
|
||||||
toU8(0)
|
toU8(0)
|
||||||
|
|
||||||
proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
|
proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
|
||||||
assert(elem >= 0)
|
assert(elem >= 0)
|
||||||
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] or
|
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] or
|
||||||
toU8(int(1 shl (elem mod ElemSize)))
|
toU8(int(1 shl (elem mod ElemSize)))
|
||||||
|
|
||||||
proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
|
proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
|
||||||
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] and
|
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] and
|
||||||
not toU8(int(1 shl (elem mod ElemSize)))
|
not toU8(int(1 shl (elem mod ElemSize)))
|
||||||
|
|
||||||
proc bitSetInit(b: var TBitSet, length: int) =
|
proc bitSetInit(b: var TBitSet, length: int) =
|
||||||
newSeq(b, length)
|
newSeq(b, length)
|
||||||
|
|
||||||
proc bitSetUnion(x: var TBitSet, y: TBitSet) =
|
proc bitSetUnion(x: var TBitSet, y: TBitSet) =
|
||||||
for i in countup(0, high(x)): x[i] = x[i] or y[i]
|
for i in countup(0, high(x)): x[i] = x[i] or y[i]
|
||||||
|
|
||||||
proc bitSetDiff(x: var TBitSet, y: TBitSet) =
|
proc bitSetDiff(x: var TBitSet, y: TBitSet) =
|
||||||
for i in countup(0, high(x)): x[i] = x[i] and not y[i]
|
for i in countup(0, high(x)): x[i] = x[i] and not y[i]
|
||||||
|
|
||||||
proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
|
proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
|
||||||
for i in countup(0, high(x)): x[i] = x[i] xor y[i]
|
for i in countup(0, high(x)): x[i] = x[i] xor y[i]
|
||||||
|
|
||||||
proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
|
proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
|
||||||
for i in countup(0, high(x)): x[i] = x[i] and y[i]
|
for i in countup(0, high(x)): x[i] = x[i] and y[i]
|
||||||
|
|
||||||
proc bitSetEquals(x, y: TBitSet): bool =
|
proc bitSetEquals(x, y: TBitSet): bool =
|
||||||
for i in countup(0, high(x)):
|
for i in countup(0, high(x)):
|
||||||
if x[i] != y[i]:
|
if x[i] != y[i]:
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc bitSetContains(x, y: TBitSet): bool =
|
proc bitSetContains(x, y: TBitSet): bool =
|
||||||
for i in countup(0, high(x)):
|
for i in countup(0, high(x)):
|
||||||
if (x[i] and not y[i]) != int8(0):
|
if (x[i] and not y[i]) != int8(0):
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -30,39 +30,39 @@ type
|
||||||
#
|
#
|
||||||
# This is a good compromise between correctness and brevity. ;-)
|
# This is a good compromise between correctness and brevity. ;-)
|
||||||
|
|
||||||
const
|
const
|
||||||
cb64 = [
|
cb64 = [
|
||||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||||
"O", "P", "Q", "R", "S", "T" "U", "V", "W", "X", "Y", "Z",
|
"O", "P", "Q", "R", "S", "T" "U", "V", "W", "X", "Y", "Z",
|
||||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
||||||
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
"_A", "_B"]
|
"_A", "_B"]
|
||||||
|
|
||||||
proc toBase64a(s: cstring, len: int): string =
|
proc toBase64a(s: cstring, len: int): string =
|
||||||
## encodes `s` into base64 representation. After `lineLen` characters, a
|
## encodes `s` into base64 representation. After `lineLen` characters, a
|
||||||
## `newline` is added.
|
## `newline` is added.
|
||||||
result = newStringOfCap(((len + 2) div 3) * 4)
|
result = newStringOfCap(((len + 2) div 3) * 4)
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < s.len - 2:
|
while i < s.len - 2:
|
||||||
let a = ord(s[i])
|
let a = ord(s[i])
|
||||||
let b = ord(s[i+1])
|
let b = ord(s[i+1])
|
||||||
let c = ord(s[i+2])
|
let c = ord(s[i+2])
|
||||||
result.add cb64[a shr 2]
|
result.add cb64[a shr 2]
|
||||||
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
||||||
result.add cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)]
|
result.add cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)]
|
||||||
result.add cb64[c and 0x3F]
|
result.add cb64[c and 0x3F]
|
||||||
inc(i, 3)
|
inc(i, 3)
|
||||||
if i < s.len-1:
|
if i < s.len-1:
|
||||||
let a = ord(s[i])
|
let a = ord(s[i])
|
||||||
let b = ord(s[i+1])
|
let b = ord(s[i+1])
|
||||||
result.add cb64[a shr 2]
|
result.add cb64[a shr 2]
|
||||||
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
||||||
result.add cb64[((b and 0x0F) shl 2)]
|
result.add cb64[((b and 0x0F) shl 2)]
|
||||||
elif i < s.len:
|
elif i < s.len:
|
||||||
let a = ord(s[i])
|
let a = ord(s[i])
|
||||||
result.add cb64[a shr 2]
|
result.add cb64[a shr 2]
|
||||||
result.add cb64[(a and 3) shl 4]
|
result.add cb64[(a and 3) shl 4]
|
||||||
|
|
||||||
proc toBase64a(u: TUid): string = toBase64a(cast[cstring](u), sizeof(u))
|
proc toBase64a(u: TUid): string = toBase64a(cast[cstring](u), sizeof(u))
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ proc hashSym(c: var MD5Context, s: PSym) =
|
||||||
c &= ":anon"
|
c &= ":anon"
|
||||||
else:
|
else:
|
||||||
var it = s.owner
|
var it = s.owner
|
||||||
while it != nil:
|
while it != nil:
|
||||||
hashSym(c, it)
|
hashSym(c, it)
|
||||||
c &= "."
|
c &= "."
|
||||||
it = s.owner
|
it = s.owner
|
||||||
|
|
@ -106,18 +106,18 @@ proc hashTree(c: var MD5Context, n: PNode) =
|
||||||
|
|
||||||
proc hashType(c: var MD5Context, t: PType) =
|
proc hashType(c: var MD5Context, t: PType) =
|
||||||
# modelled after 'typeToString'
|
# modelled after 'typeToString'
|
||||||
if t == nil:
|
if t == nil:
|
||||||
c &= "\254"
|
c &= "\254"
|
||||||
return
|
return
|
||||||
|
|
||||||
var k = t.kind
|
var k = t.kind
|
||||||
md5Update(c, cast[cstring](addr(k)), 1)
|
md5Update(c, cast[cstring](addr(k)), 1)
|
||||||
|
|
||||||
if t.sym != nil and sfAnon notin t.sym.flags:
|
if t.sym != nil and sfAnon notin t.sym.flags:
|
||||||
# t.n for literals, but not for e.g. objects!
|
# t.n for literals, but not for e.g. objects!
|
||||||
if t.kind in {tyFloat, tyInt}: c.hashNode(t.n)
|
if t.kind in {tyFloat, tyInt}: c.hashNode(t.n)
|
||||||
c.hashSym(t.sym)
|
c.hashSym(t.sym)
|
||||||
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericBody, tyGenericInst, tyGenericInvocation:
|
of tyGenericBody, tyGenericInst, tyGenericInvocation:
|
||||||
for i in countup(0, sonsLen(t) -1 -ord(t.kind != tyGenericInvocation)):
|
for i in countup(0, sonsLen(t) -1 -ord(t.kind != tyGenericInvocation)):
|
||||||
|
|
@ -135,10 +135,10 @@ proc hashType(c: var MD5Context, t: PType) =
|
||||||
of tyArrayConstr:
|
of tyArrayConstr:
|
||||||
c.hashTree(t.sons[0].n)
|
c.hashTree(t.sons[0].n)
|
||||||
c.hashType(t.sons[1])
|
c.hashType(t.sons[1])
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if t.n != nil:
|
if t.n != nil:
|
||||||
assert(sonsLen(t.n) == sonsLen(t))
|
assert(sonsLen(t.n) == sonsLen(t))
|
||||||
for i in countup(0, sonsLen(t.n) - 1):
|
for i in countup(0, sonsLen(t.n) - 1):
|
||||||
assert(t.n.sons[i].kind == nkSym)
|
assert(t.n.sons[i].kind == nkSym)
|
||||||
c &= t.n.sons[i].sym.name.s
|
c &= t.n.sons[i].sym.name.s
|
||||||
c &= ":"
|
c &= ":"
|
||||||
|
|
@ -184,18 +184,18 @@ proc pushSym(w: PRodWriter, s: PSym) =
|
||||||
if iiTableGet(w.index.tab, s.id) == InvalidKey:
|
if iiTableGet(w.index.tab, s.id) == InvalidKey:
|
||||||
w.sstack.add(s)
|
w.sstack.add(s)
|
||||||
|
|
||||||
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||||
result: var string) =
|
result: var string) =
|
||||||
if n == nil:
|
if n == nil:
|
||||||
# nil nodes have to be stored too:
|
# nil nodes have to be stored too:
|
||||||
result.add("()")
|
result.add("()")
|
||||||
return
|
return
|
||||||
result.add('(')
|
result.add('(')
|
||||||
encodeVInt(ord(n.kind), result)
|
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:
|
||||||
result.add('?')
|
result.add('?')
|
||||||
encodeVInt(n.info.col, result)
|
encodeVInt(n.info.col, result)
|
||||||
result.add(',')
|
result.add(',')
|
||||||
|
|
@ -211,7 +211,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||||
result.add('?')
|
result.add('?')
|
||||||
encodeVInt(n.info.col, result)
|
encodeVInt(n.info.col, result)
|
||||||
var f = n.flags * PersistentNodeFlags
|
var f = n.flags * PersistentNodeFlags
|
||||||
if f != {}:
|
if f != {}:
|
||||||
result.add('$')
|
result.add('$')
|
||||||
encodeVInt(cast[int32](f), result)
|
encodeVInt(cast[int32](f), result)
|
||||||
if n.typ != nil:
|
if n.typ != nil:
|
||||||
|
|
@ -219,16 +219,16 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||||
encodeVInt(n.typ.id, result)
|
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:
|
if n.intVal != 0:
|
||||||
result.add('!')
|
result.add('!')
|
||||||
encodeVBiggestInt(n.intVal, result)
|
encodeVBiggestInt(n.intVal, result)
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat64Lit:
|
||||||
if n.floatVal != 0.0:
|
if n.floatVal != 0.0:
|
||||||
result.add('!')
|
result.add('!')
|
||||||
encodeStr($n.floatVal, result)
|
encodeStr($n.floatVal, result)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if n.strVal != "":
|
if n.strVal != "":
|
||||||
result.add('!')
|
result.add('!')
|
||||||
encodeStr(n.strVal, result)
|
encodeStr(n.strVal, result)
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
|
|
@ -239,7 +239,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||||
encodeVInt(n.sym.id, result)
|
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):
|
||||||
encodeNode(w, n.info, n.sons[i], result)
|
encodeNode(w, n.info, n.sons[i], result)
|
||||||
add(result, ')')
|
add(result, ')')
|
||||||
|
|
||||||
|
|
@ -268,9 +268,9 @@ proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
|
||||||
setLen(result, oldLen)
|
setLen(result, oldLen)
|
||||||
else:
|
else:
|
||||||
add(result, '>')
|
add(result, '>')
|
||||||
|
|
||||||
proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
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:
|
||||||
result.add("[]")
|
result.add("[]")
|
||||||
return
|
return
|
||||||
|
|
@ -282,38 +282,38 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
||||||
encodeVInt(ord(t.kind), result)
|
encodeVInt(ord(t.kind), result)
|
||||||
add(result, '+')
|
add(result, '+')
|
||||||
encodeVInt(t.id, result)
|
encodeVInt(t.id, result)
|
||||||
if t.n != nil:
|
if t.n != nil:
|
||||||
encodeNode(w, unknownLineInfo(), t.n, result)
|
encodeNode(w, unknownLineInfo(), t.n, result)
|
||||||
if t.flags != {}:
|
if t.flags != {}:
|
||||||
add(result, '$')
|
add(result, '$')
|
||||||
encodeVInt(cast[int32](t.flags), result)
|
encodeVInt(cast[int32](t.flags), result)
|
||||||
if t.callConv != low(t.callConv):
|
if t.callConv != low(t.callConv):
|
||||||
add(result, '?')
|
add(result, '?')
|
||||||
encodeVInt(ord(t.callConv), result)
|
encodeVInt(ord(t.callConv), result)
|
||||||
if t.owner != nil:
|
if t.owner != nil:
|
||||||
add(result, '*')
|
add(result, '*')
|
||||||
encodeVInt(t.owner.id, result)
|
encodeVInt(t.owner.id, result)
|
||||||
pushSym(w, t.owner)
|
pushSym(w, t.owner)
|
||||||
if t.sym != nil:
|
if t.sym != nil:
|
||||||
add(result, '&')
|
add(result, '&')
|
||||||
encodeVInt(t.sym.id, result)
|
encodeVInt(t.sym.id, result)
|
||||||
pushSym(w, t.sym)
|
pushSym(w, t.sym)
|
||||||
if t.size != - 1:
|
if t.size != - 1:
|
||||||
add(result, '/')
|
add(result, '/')
|
||||||
encodeVBiggestInt(t.size, result)
|
encodeVBiggestInt(t.size, result)
|
||||||
if t.align != 2:
|
if t.align != 2:
|
||||||
add(result, '=')
|
add(result, '=')
|
||||||
encodeVInt(t.align, result)
|
encodeVInt(t.align, result)
|
||||||
encodeLoc(w, t.loc, 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:
|
||||||
add(result, "^()")
|
add(result, "^()")
|
||||||
else:
|
else:
|
||||||
add(result, '^')
|
add(result, '^')
|
||||||
encodeVInt(t.sons[i].id, 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, result: var string) =
|
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
|
||||||
add(result, '|')
|
add(result, '|')
|
||||||
encodeVInt(ord(lib.kind), result)
|
encodeVInt(ord(lib.kind), result)
|
||||||
add(result, '|')
|
add(result, '|')
|
||||||
|
|
@ -352,10 +352,10 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
|
||||||
if s.magic != mNone:
|
if s.magic != mNone:
|
||||||
result.add('@')
|
result.add('@')
|
||||||
encodeVInt(ord(s.magic), result)
|
encodeVInt(ord(s.magic), result)
|
||||||
if s.options != w.options:
|
if s.options != w.options:
|
||||||
result.add('!')
|
result.add('!')
|
||||||
encodeVInt(cast[int32](s.options), result)
|
encodeVInt(cast[int32](s.options), result)
|
||||||
if s.position != 0:
|
if s.position != 0:
|
||||||
result.add('%')
|
result.add('%')
|
||||||
encodeVInt(s.position, result)
|
encodeVInt(s.position, result)
|
||||||
if s.offset != - 1:
|
if s.offset != - 1:
|
||||||
|
|
@ -383,7 +383,7 @@ proc createDb() =
|
||||||
fullpath varchar(256) not null,
|
fullpath varchar(256) not null,
|
||||||
interfHash varchar(256) not null,
|
interfHash varchar(256) not null,
|
||||||
fullHash varchar(256) not null,
|
fullHash varchar(256) not null,
|
||||||
|
|
||||||
created timestamp not null default (DATETIME('now')),
|
created timestamp not null default (DATETIME('now')),
|
||||||
);""")
|
);""")
|
||||||
|
|
||||||
|
|
@ -397,7 +397,7 @@ proc createDb() =
|
||||||
|
|
||||||
foreign key (module) references module(id)
|
foreign key (module) references module(id)
|
||||||
);""")
|
);""")
|
||||||
|
|
||||||
db.exec(sql"""
|
db.exec(sql"""
|
||||||
create table if not exists Type(
|
create table if not exists Type(
|
||||||
id integer primary key,
|
id integer primary key,
|
||||||
|
|
|
||||||
|
|
@ -9,33 +9,33 @@
|
||||||
|
|
||||||
## This module implements code generation for multi methods.
|
## This module implements code generation for multi methods.
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
|
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
|
||||||
sempass2, strutils
|
sempass2, strutils
|
||||||
|
|
||||||
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||||
var dest = skipTypes(d, abstractPtrs)
|
var dest = skipTypes(d, abstractPtrs)
|
||||||
var source = skipTypes(n.typ, abstractPtrs)
|
var source = skipTypes(n.typ, abstractPtrs)
|
||||||
if (source.kind == tyObject) and (dest.kind == tyObject):
|
if (source.kind == tyObject) and (dest.kind == tyObject):
|
||||||
var diff = inheritanceDiff(dest, source)
|
var diff = inheritanceDiff(dest, source)
|
||||||
if diff == high(int): internalError(n.info, "cgmeth.genConv")
|
if diff == high(int): internalError(n.info, "cgmeth.genConv")
|
||||||
if diff < 0:
|
if diff < 0:
|
||||||
result = newNodeIT(nkObjUpConv, n.info, d)
|
result = newNodeIT(nkObjUpConv, n.info, d)
|
||||||
addSon(result, n)
|
addSon(result, n)
|
||||||
if downcast: internalError(n.info, "cgmeth.genConv: no upcast allowed")
|
if downcast: internalError(n.info, "cgmeth.genConv: no upcast allowed")
|
||||||
elif diff > 0:
|
elif diff > 0:
|
||||||
result = newNodeIT(nkObjDownConv, n.info, d)
|
result = newNodeIT(nkObjDownConv, n.info, d)
|
||||||
addSon(result, n)
|
addSon(result, n)
|
||||||
if not downcast:
|
if not downcast:
|
||||||
internalError(n.info, "cgmeth.genConv: no downcast allowed")
|
internalError(n.info, "cgmeth.genConv: no downcast allowed")
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc methodCall*(n: PNode): PNode =
|
proc methodCall*(n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
# replace ordinary method by dispatcher method:
|
# replace ordinary method by dispatcher method:
|
||||||
var disp = lastSon(result.sons[0].sym.ast).sym
|
var disp = lastSon(result.sons[0].sym.ast).sym
|
||||||
assert sfDispatcher in disp.flags
|
assert sfDispatcher in disp.flags
|
||||||
result.sons[0].sym = disp
|
result.sons[0].sym = disp
|
||||||
|
|
@ -47,23 +47,23 @@ proc methodCall*(n: PNode): PNode =
|
||||||
var
|
var
|
||||||
gMethods: seq[tuple[methods: TSymSeq, dispatcher: PSym]] = @[]
|
gMethods: seq[tuple[methods: TSymSeq, dispatcher: PSym]] = @[]
|
||||||
|
|
||||||
proc sameMethodBucket(a, b: PSym): bool =
|
proc sameMethodBucket(a, b: PSym): bool =
|
||||||
result = false
|
result = false
|
||||||
if a.name.id != b.name.id: return
|
if a.name.id != b.name.id: return
|
||||||
if sonsLen(a.typ) != sonsLen(b.typ):
|
if sonsLen(a.typ) != sonsLen(b.typ):
|
||||||
return # check for return type:
|
return # check for return type:
|
||||||
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]): return
|
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]): return
|
||||||
for i in countup(1, sonsLen(a.typ) - 1):
|
for i in countup(1, sonsLen(a.typ) - 1):
|
||||||
var aa = a.typ.sons[i]
|
var aa = a.typ.sons[i]
|
||||||
var bb = b.typ.sons[i]
|
var bb = b.typ.sons[i]
|
||||||
while true:
|
while true:
|
||||||
aa = skipTypes(aa, {tyGenericInst})
|
aa = skipTypes(aa, {tyGenericInst})
|
||||||
bb = skipTypes(bb, {tyGenericInst})
|
bb = skipTypes(bb, {tyGenericInst})
|
||||||
if (aa.kind == bb.kind) and (aa.kind in {tyVar, tyPtr, tyRef}):
|
if (aa.kind == bb.kind) and (aa.kind in {tyVar, tyPtr, tyRef}):
|
||||||
aa = aa.lastSon
|
aa = aa.lastSon
|
||||||
bb = bb.lastSon
|
bb = bb.lastSon
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
if sameType(aa, bb) or
|
if sameType(aa, bb) or
|
||||||
(aa.kind == tyObject) and (bb.kind == tyObject) and
|
(aa.kind == tyObject) and (bb.kind == tyObject) and
|
||||||
(inheritanceDiff(bb, aa) < 0):
|
(inheritanceDiff(bb, aa) < 0):
|
||||||
|
|
@ -140,7 +140,7 @@ proc methodDef*(s: PSym, fromCache: bool) =
|
||||||
attachDispatcher(s, lastSon(disp.ast))
|
attachDispatcher(s, lastSon(disp.ast))
|
||||||
fixupDispatcher(s, disp)
|
fixupDispatcher(s, disp)
|
||||||
when useEffectSystem: checkMethodEffects(disp, s)
|
when useEffectSystem: checkMethodEffects(disp, s)
|
||||||
return
|
return
|
||||||
# create a new dispatcher:
|
# create a new dispatcher:
|
||||||
add(gMethods, (methods: @[s], dispatcher: createDispatcher(s)))
|
add(gMethods, (methods: @[s], dispatcher: createDispatcher(s)))
|
||||||
if fromCache:
|
if fromCache:
|
||||||
|
|
@ -154,35 +154,35 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||||
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
|
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
|
||||||
if not sameType(t2, t):
|
if not sameType(t2, t):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
|
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
|
||||||
for col in countup(1, sonsLen(a.typ) - 1):
|
for col in countup(1, sonsLen(a.typ) - 1):
|
||||||
if contains(relevantCols, col):
|
if contains(relevantCols, col):
|
||||||
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
||||||
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
||||||
var d = inheritanceDiff(aa, bb)
|
var d = inheritanceDiff(aa, bb)
|
||||||
if (d != high(int)):
|
if (d != high(int)):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
proc sortBucket(a: var TSymSeq, relevantCols: IntSet) =
|
proc sortBucket(a: var TSymSeq, relevantCols: IntSet) =
|
||||||
# we use shellsort here; fast and simple
|
# we use shellsort here; fast and simple
|
||||||
var n = len(a)
|
var n = len(a)
|
||||||
var h = 1
|
var h = 1
|
||||||
while true:
|
while true:
|
||||||
h = 3 * h + 1
|
h = 3 * h + 1
|
||||||
if h > n: break
|
if h > n: break
|
||||||
while true:
|
while true:
|
||||||
h = h div 3
|
h = h div 3
|
||||||
for i in countup(h, n - 1):
|
for i in countup(h, n - 1):
|
||||||
var v = a[i]
|
var v = a[i]
|
||||||
var j = i
|
var j = i
|
||||||
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
|
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
|
||||||
a[j] = a[j - h]
|
a[j] = a[j - h]
|
||||||
j = j - h
|
j = j - h
|
||||||
if j < h: break
|
if j < h: break
|
||||||
a[j] = v
|
a[j] = v
|
||||||
if h == 1: break
|
if h == 1: break
|
||||||
|
|
||||||
proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
|
proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
|
||||||
var base = lastSon(methods[0].ast).sym
|
var base = lastSon(methods[0].ast).sym
|
||||||
result = base
|
result = base
|
||||||
|
|
@ -199,7 +199,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
|
||||||
addSon(isn, newSymNode(iss))
|
addSon(isn, newSymNode(iss))
|
||||||
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
||||||
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
|
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
|
||||||
if cond != nil:
|
if cond != nil:
|
||||||
var a = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
var a = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
||||||
addSon(a, newSymNode(ands))
|
addSon(a, newSymNode(ands))
|
||||||
addSon(a, cond)
|
addSon(a, cond)
|
||||||
|
|
@ -209,8 +209,8 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
|
||||||
cond = isn
|
cond = isn
|
||||||
var call = newNodeI(nkCall, base.info)
|
var call = newNodeI(nkCall, base.info)
|
||||||
addSon(call, newSymNode(curr))
|
addSon(call, newSymNode(curr))
|
||||||
for col in countup(1, paramLen - 1):
|
for col in countup(1, paramLen - 1):
|
||||||
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
|
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
|
||||||
curr.typ.sons[col], false))
|
curr.typ.sons[col], false))
|
||||||
var ret: PNode
|
var ret: PNode
|
||||||
if base.typ.sons[0] != nil:
|
if base.typ.sons[0] != nil:
|
||||||
|
|
@ -230,11 +230,11 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
|
||||||
disp = ret
|
disp = ret
|
||||||
result.ast.sons[bodyPos] = disp
|
result.ast.sons[bodyPos] = disp
|
||||||
|
|
||||||
proc generateMethodDispatchers*(): PNode =
|
proc generateMethodDispatchers*(): PNode =
|
||||||
result = newNode(nkStmtList)
|
result = newNode(nkStmtList)
|
||||||
for bucket in countup(0, len(gMethods) - 1):
|
for bucket in countup(0, len(gMethods) - 1):
|
||||||
var relevantCols = initIntSet()
|
var relevantCols = initIntSet()
|
||||||
for col in countup(1, sonsLen(gMethods[bucket].methods[0].typ) - 1):
|
for col in countup(1, sonsLen(gMethods[bucket].methods[0].typ) - 1):
|
||||||
if relevantCol(gMethods[bucket].methods, col): incl(relevantCols, col)
|
if relevantCol(gMethods[bucket].methods, col): incl(relevantCols, col)
|
||||||
sortBucket(gMethods[bucket].methods, relevantCols)
|
sortBucket(gMethods[bucket].methods, relevantCols)
|
||||||
addSon(result,
|
addSon(result,
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
# This module implements a new documentation generator that runs after
|
# This module implements a new documentation generator that runs after
|
||||||
# semantic checking.
|
# semantic checking.
|
||||||
|
|
||||||
import
|
import
|
||||||
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen
|
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen
|
||||||
|
|
||||||
type
|
type
|
||||||
TGen = object of TPassContext
|
TGen = object of TPassContext
|
||||||
doc: PDoc
|
doc: PDoc
|
||||||
module: PSym
|
module: PSym
|
||||||
|
|
@ -29,12 +29,12 @@ proc close(p: PPassContext, n: PNode): PNode =
|
||||||
except IOError:
|
except IOError:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc processNode(c: PPassContext, n: PNode): PNode =
|
proc processNode(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
var g = PGen(c)
|
var g = PGen(c)
|
||||||
generateDoc(g.doc, n)
|
generateDoc(g.doc, n)
|
||||||
|
|
||||||
proc myOpen(module: PSym): PPassContext =
|
proc myOpen(module: PSym): PPassContext =
|
||||||
var g: PGen
|
var g: PGen
|
||||||
new(g)
|
new(g)
|
||||||
g.module = module
|
g.module = module
|
||||||
|
|
@ -45,5 +45,5 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
|
|
||||||
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
|
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
|
||||||
|
|
||||||
proc finishDoc2Pass*(project: string) =
|
proc finishDoc2Pass*(project: string) =
|
||||||
discard
|
discard
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||||
for y in items(x): result.add(y)
|
for y in items(x): result.add(y)
|
||||||
else:
|
else:
|
||||||
result.add copyTree(x)
|
result.add copyTree(x)
|
||||||
|
|
||||||
case templ.kind
|
case templ.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var s = templ.sym
|
var s = templ.sym
|
||||||
|
|
@ -81,7 +81,7 @@ proc evalTemplateArgs(n: PNode, s: PSym): PNode =
|
||||||
|
|
||||||
if totalParams > expectedRegularParams + genericParams:
|
if totalParams > expectedRegularParams + genericParams:
|
||||||
globalError(n.info, errWrongNumberOfArguments)
|
globalError(n.info, errWrongNumberOfArguments)
|
||||||
|
|
||||||
result = newNodeI(nkArgList, n.info)
|
result = newNodeI(nkArgList, n.info)
|
||||||
for i in 1 .. givenRegularParams:
|
for i in 1 .. givenRegularParams:
|
||||||
result.addSon n.sons[i]
|
result.addSon n.sons[i]
|
||||||
|
|
@ -96,7 +96,7 @@ proc evalTemplateArgs(n: PNode, s: PSym): PNode =
|
||||||
addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
else:
|
else:
|
||||||
addSon(result, default.copyTree)
|
addSon(result, default.copyTree)
|
||||||
|
|
||||||
# add any generic paramaters
|
# add any generic paramaters
|
||||||
for i in 1 .. genericParams:
|
for i in 1 .. genericParams:
|
||||||
result.addSon n.sons[givenRegularParams + i]
|
result.addSon n.sons[givenRegularParams + i]
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,18 @@
|
||||||
|
|
||||||
# This module implements Nim's standard template filter.
|
# This module implements Nim's standard template filter.
|
||||||
|
|
||||||
import
|
import
|
||||||
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
||||||
renderer, filters
|
renderer, filters
|
||||||
|
|
||||||
proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream
|
proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream
|
||||||
# #! template(subsChar='$', metaChar='#') | standard(version="0.7.2")
|
# #! template(subsChar='$', metaChar='#') | standard(version="0.7.2")
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
type
|
type
|
||||||
TParseState = enum
|
TParseState = enum
|
||||||
psDirective, psTempl
|
psDirective, psTempl
|
||||||
TTmplParser{.final.} = object
|
TTmplParser{.final.} = object
|
||||||
inp: PLLStream
|
inp: PLLStream
|
||||||
state: TParseState
|
state: TParseState
|
||||||
info: TLineInfo
|
info: TLineInfo
|
||||||
|
|
@ -33,18 +33,18 @@ type
|
||||||
pendingExprLine: bool
|
pendingExprLine: bool
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
|
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
|
||||||
|
|
||||||
proc newLine(p: var TTmplParser) =
|
proc newLine(p: var TTmplParser) =
|
||||||
llStreamWrite(p.outp, repeat(')', p.emitPar))
|
llStreamWrite(p.outp, repeat(')', p.emitPar))
|
||||||
p.emitPar = 0
|
p.emitPar = 0
|
||||||
if p.info.line > int16(1): llStreamWrite(p.outp, "\n")
|
if p.info.line > int16(1): llStreamWrite(p.outp, "\n")
|
||||||
if p.pendingExprLine:
|
if p.pendingExprLine:
|
||||||
llStreamWrite(p.outp, spaces(2))
|
llStreamWrite(p.outp, spaces(2))
|
||||||
p.pendingExprLine = false
|
p.pendingExprLine = false
|
||||||
|
|
||||||
proc scanPar(p: var TTmplParser, d: int) =
|
proc scanPar(p: var TTmplParser, d: int) =
|
||||||
var i = d
|
var i = d
|
||||||
while true:
|
while true:
|
||||||
case p.x[i]
|
case p.x[i]
|
||||||
|
|
@ -58,44 +58,44 @@ proc scanPar(p: var TTmplParser, d: int) =
|
||||||
else: discard
|
else: discard
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc withInExpr(p: TTmplParser): bool {.inline.} =
|
proc withInExpr(p: TTmplParser): bool {.inline.} =
|
||||||
result = p.par > 0 or p.bracket > 0 or p.curly > 0
|
result = p.par > 0 or p.bracket > 0 or p.curly > 0
|
||||||
|
|
||||||
proc parseLine(p: var TTmplParser) =
|
proc parseLine(p: var TTmplParser) =
|
||||||
var
|
var
|
||||||
d, j, curly: int
|
d, j, curly: int
|
||||||
keyw: string
|
keyw: string
|
||||||
j = 0
|
j = 0
|
||||||
while p.x[j] == ' ': inc(j)
|
while p.x[j] == ' ': inc(j)
|
||||||
if (p.x[0] == p.nimDirective) and (p.x[0 + 1] == '!'):
|
if (p.x[0] == p.nimDirective) and (p.x[0 + 1] == '!'):
|
||||||
newLine(p)
|
newLine(p)
|
||||||
elif (p.x[j] == p.nimDirective):
|
elif (p.x[j] == p.nimDirective):
|
||||||
newLine(p)
|
newLine(p)
|
||||||
inc(j)
|
inc(j)
|
||||||
while p.x[j] == ' ': inc(j)
|
while p.x[j] == ' ': inc(j)
|
||||||
d = j
|
d = j
|
||||||
keyw = ""
|
keyw = ""
|
||||||
while p.x[j] in PatternChars:
|
while p.x[j] in PatternChars:
|
||||||
add(keyw, p.x[j])
|
add(keyw, p.x[j])
|
||||||
inc(j)
|
inc(j)
|
||||||
|
|
||||||
scanPar(p, j)
|
scanPar(p, j)
|
||||||
p.pendingExprLine = withInExpr(p) or llstream.endsWithOpr(p.x)
|
p.pendingExprLine = withInExpr(p) or llstream.endsWithOpr(p.x)
|
||||||
case whichKeyword(keyw)
|
case whichKeyword(keyw)
|
||||||
of wEnd:
|
of wEnd:
|
||||||
if p.indent >= 2:
|
if p.indent >= 2:
|
||||||
dec(p.indent, 2)
|
dec(p.indent, 2)
|
||||||
else:
|
else:
|
||||||
p.info.col = int16(j)
|
p.info.col = int16(j)
|
||||||
localError(p.info, errXNotAllowedHere, "end")
|
localError(p.info, errXNotAllowedHere, "end")
|
||||||
llStreamWrite(p.outp, spaces(p.indent))
|
llStreamWrite(p.outp, spaces(p.indent))
|
||||||
llStreamWrite(p.outp, "#end")
|
llStreamWrite(p.outp, "#end")
|
||||||
of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
|
of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
|
||||||
wConverter, wMacro, wTemplate, wMethod:
|
wConverter, wMacro, wTemplate, wMethod:
|
||||||
llStreamWrite(p.outp, spaces(p.indent))
|
llStreamWrite(p.outp, spaces(p.indent))
|
||||||
llStreamWrite(p.outp, substr(p.x, d))
|
llStreamWrite(p.outp, substr(p.x, d))
|
||||||
inc(p.indent, 2)
|
inc(p.indent, 2)
|
||||||
of wElif, wOf, wElse, wExcept, wFinally:
|
of wElif, wOf, wElse, wExcept, wFinally:
|
||||||
llStreamWrite(p.outp, spaces(p.indent - 2))
|
llStreamWrite(p.outp, spaces(p.indent - 2))
|
||||||
llStreamWrite(p.outp, substr(p.x, d))
|
llStreamWrite(p.outp, substr(p.x, d))
|
||||||
of wLet, wVar, wConst, wType:
|
of wLet, wVar, wConst, wType:
|
||||||
|
|
@ -108,7 +108,7 @@ proc parseLine(p: var TTmplParser) =
|
||||||
llStreamWrite(p.outp, spaces(p.indent))
|
llStreamWrite(p.outp, spaces(p.indent))
|
||||||
llStreamWrite(p.outp, substr(p.x, d))
|
llStreamWrite(p.outp, substr(p.x, d))
|
||||||
p.state = psDirective
|
p.state = psDirective
|
||||||
else:
|
else:
|
||||||
# data line
|
# data line
|
||||||
# reset counters
|
# reset counters
|
||||||
p.par = 0
|
p.par = 0
|
||||||
|
|
@ -116,42 +116,42 @@ proc parseLine(p: var TTmplParser) =
|
||||||
p.bracket = 0
|
p.bracket = 0
|
||||||
j = 0
|
j = 0
|
||||||
case p.state
|
case p.state
|
||||||
of psTempl:
|
of psTempl:
|
||||||
# next line of string literal:
|
# next line of string literal:
|
||||||
llStreamWrite(p.outp, p.conc)
|
llStreamWrite(p.outp, p.conc)
|
||||||
llStreamWrite(p.outp, "\n")
|
llStreamWrite(p.outp, "\n")
|
||||||
llStreamWrite(p.outp, spaces(p.indent + 2))
|
llStreamWrite(p.outp, spaces(p.indent + 2))
|
||||||
llStreamWrite(p.outp, "\"")
|
llStreamWrite(p.outp, "\"")
|
||||||
of psDirective:
|
of psDirective:
|
||||||
newLine(p)
|
newLine(p)
|
||||||
llStreamWrite(p.outp, spaces(p.indent))
|
llStreamWrite(p.outp, spaces(p.indent))
|
||||||
llStreamWrite(p.outp, p.emit)
|
llStreamWrite(p.outp, p.emit)
|
||||||
llStreamWrite(p.outp, "(\"")
|
llStreamWrite(p.outp, "(\"")
|
||||||
inc(p.emitPar)
|
inc(p.emitPar)
|
||||||
p.state = psTempl
|
p.state = psTempl
|
||||||
while true:
|
while true:
|
||||||
case p.x[j]
|
case p.x[j]
|
||||||
of '\0':
|
of '\0':
|
||||||
break
|
break
|
||||||
of '\x01'..'\x1F', '\x80'..'\xFF':
|
of '\x01'..'\x1F', '\x80'..'\xFF':
|
||||||
llStreamWrite(p.outp, "\\x")
|
llStreamWrite(p.outp, "\\x")
|
||||||
llStreamWrite(p.outp, toHex(ord(p.x[j]), 2))
|
llStreamWrite(p.outp, toHex(ord(p.x[j]), 2))
|
||||||
inc(j)
|
inc(j)
|
||||||
of '\\':
|
of '\\':
|
||||||
llStreamWrite(p.outp, "\\\\")
|
llStreamWrite(p.outp, "\\\\")
|
||||||
inc(j)
|
inc(j)
|
||||||
of '\'':
|
of '\'':
|
||||||
llStreamWrite(p.outp, "\\\'")
|
llStreamWrite(p.outp, "\\\'")
|
||||||
inc(j)
|
inc(j)
|
||||||
of '\"':
|
of '\"':
|
||||||
llStreamWrite(p.outp, "\\\"")
|
llStreamWrite(p.outp, "\\\"")
|
||||||
inc(j)
|
inc(j)
|
||||||
else:
|
else:
|
||||||
if p.x[j] == p.subsChar:
|
if p.x[j] == p.subsChar:
|
||||||
# parse Nim expression:
|
# parse Nim expression:
|
||||||
inc(j)
|
inc(j)
|
||||||
case p.x[j]
|
case p.x[j]
|
||||||
of '{':
|
of '{':
|
||||||
p.info.col = int16(j)
|
p.info.col = int16(j)
|
||||||
llStreamWrite(p.outp, '\"')
|
llStreamWrite(p.outp, '\"')
|
||||||
llStreamWrite(p.outp, p.conc)
|
llStreamWrite(p.outp, p.conc)
|
||||||
|
|
@ -159,50 +159,50 @@ proc parseLine(p: var TTmplParser) =
|
||||||
llStreamWrite(p.outp, '(')
|
llStreamWrite(p.outp, '(')
|
||||||
inc(j)
|
inc(j)
|
||||||
curly = 0
|
curly = 0
|
||||||
while true:
|
while true:
|
||||||
case p.x[j]
|
case p.x[j]
|
||||||
of '\0':
|
of '\0':
|
||||||
localError(p.info, errXExpected, "}")
|
localError(p.info, errXExpected, "}")
|
||||||
break
|
break
|
||||||
of '{':
|
of '{':
|
||||||
inc(j)
|
inc(j)
|
||||||
inc(curly)
|
inc(curly)
|
||||||
llStreamWrite(p.outp, '{')
|
llStreamWrite(p.outp, '{')
|
||||||
of '}':
|
of '}':
|
||||||
inc(j)
|
inc(j)
|
||||||
if curly == 0: break
|
if curly == 0: break
|
||||||
if curly > 0: dec(curly)
|
if curly > 0: dec(curly)
|
||||||
llStreamWrite(p.outp, '}')
|
llStreamWrite(p.outp, '}')
|
||||||
else:
|
else:
|
||||||
llStreamWrite(p.outp, p.x[j])
|
llStreamWrite(p.outp, p.x[j])
|
||||||
inc(j)
|
inc(j)
|
||||||
llStreamWrite(p.outp, ')')
|
llStreamWrite(p.outp, ')')
|
||||||
llStreamWrite(p.outp, p.conc)
|
llStreamWrite(p.outp, p.conc)
|
||||||
llStreamWrite(p.outp, '\"')
|
llStreamWrite(p.outp, '\"')
|
||||||
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF':
|
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF':
|
||||||
llStreamWrite(p.outp, '\"')
|
llStreamWrite(p.outp, '\"')
|
||||||
llStreamWrite(p.outp, p.conc)
|
llStreamWrite(p.outp, p.conc)
|
||||||
llStreamWrite(p.outp, p.toStr)
|
llStreamWrite(p.outp, p.toStr)
|
||||||
llStreamWrite(p.outp, '(')
|
llStreamWrite(p.outp, '(')
|
||||||
while p.x[j] in PatternChars:
|
while p.x[j] in PatternChars:
|
||||||
llStreamWrite(p.outp, p.x[j])
|
llStreamWrite(p.outp, p.x[j])
|
||||||
inc(j)
|
inc(j)
|
||||||
llStreamWrite(p.outp, ')')
|
llStreamWrite(p.outp, ')')
|
||||||
llStreamWrite(p.outp, p.conc)
|
llStreamWrite(p.outp, p.conc)
|
||||||
llStreamWrite(p.outp, '\"')
|
llStreamWrite(p.outp, '\"')
|
||||||
else:
|
else:
|
||||||
if p.x[j] == p.subsChar:
|
if p.x[j] == p.subsChar:
|
||||||
llStreamWrite(p.outp, p.subsChar)
|
llStreamWrite(p.outp, p.subsChar)
|
||||||
inc(j)
|
inc(j)
|
||||||
else:
|
else:
|
||||||
p.info.col = int16(j)
|
p.info.col = int16(j)
|
||||||
localError(p.info, errInvalidExpression, "$")
|
localError(p.info, errInvalidExpression, "$")
|
||||||
else:
|
else:
|
||||||
llStreamWrite(p.outp, p.x[j])
|
llStreamWrite(p.outp, p.x[j])
|
||||||
inc(j)
|
inc(j)
|
||||||
llStreamWrite(p.outp, "\\n\"")
|
llStreamWrite(p.outp, "\\n\"")
|
||||||
|
|
||||||
proc filterTmpl(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
proc filterTmpl(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||||
var p: TTmplParser
|
var p: TTmplParser
|
||||||
p.info = newLineInfo(filename, 0, 0)
|
p.info = newLineInfo(filename, 0, 0)
|
||||||
p.outp = llStreamOpen("")
|
p.outp = llStreamOpen("")
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# This module implements Nim's simple filters and helpers for filters.
|
# This module implements Nim's simple filters and helpers for filters.
|
||||||
|
|
||||||
import
|
import
|
||||||
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
||||||
renderer
|
renderer
|
||||||
|
|
||||||
proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
|
proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
|
||||||
|
|
@ -21,40 +21,40 @@ proc strArg*(n: PNode, name: string, pos: int, default: string): string
|
||||||
proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
|
proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc invalidPragma(n: PNode) =
|
proc invalidPragma(n: PNode) =
|
||||||
localError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
|
localError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
|
||||||
|
|
||||||
proc getArg(n: PNode, name: string, pos: int): PNode =
|
proc getArg(n: PNode, name: string, pos: int): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
if n.kind in {nkEmpty..nkNilLit}: return
|
if n.kind in {nkEmpty..nkNilLit}: return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind == nkExprEqExpr:
|
if n.sons[i].kind == nkExprEqExpr:
|
||||||
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(n)
|
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(n)
|
||||||
if identEq(n.sons[i].sons[0].ident, name):
|
if identEq(n.sons[i].sons[0].ident, name):
|
||||||
return n.sons[i].sons[1]
|
return n.sons[i].sons[1]
|
||||||
elif i == pos:
|
elif i == pos:
|
||||||
return n.sons[i]
|
return n.sons[i]
|
||||||
|
|
||||||
proc charArg(n: PNode, name: string, pos: int, default: char): char =
|
proc charArg(n: PNode, name: string, pos: int, default: char): char =
|
||||||
var x = getArg(n, name, pos)
|
var x = getArg(n, name, pos)
|
||||||
if x == nil: result = default
|
if x == nil: result = default
|
||||||
elif x.kind == nkCharLit: result = chr(int(x.intVal))
|
elif x.kind == nkCharLit: result = chr(int(x.intVal))
|
||||||
else: invalidPragma(n)
|
else: invalidPragma(n)
|
||||||
|
|
||||||
proc strArg(n: PNode, name: string, pos: int, default: string): string =
|
proc strArg(n: PNode, name: string, pos: int, default: string): string =
|
||||||
var x = getArg(n, name, pos)
|
var x = getArg(n, name, pos)
|
||||||
if x == nil: result = default
|
if x == nil: result = default
|
||||||
elif x.kind in {nkStrLit..nkTripleStrLit}: result = x.strVal
|
elif x.kind in {nkStrLit..nkTripleStrLit}: result = x.strVal
|
||||||
else: invalidPragma(n)
|
else: invalidPragma(n)
|
||||||
|
|
||||||
proc boolArg(n: PNode, name: string, pos: int, default: bool): bool =
|
proc boolArg(n: PNode, name: string, pos: int, default: bool): bool =
|
||||||
var x = getArg(n, name, pos)
|
var x = getArg(n, name, pos)
|
||||||
if x == nil: result = default
|
if x == nil: result = default
|
||||||
elif (x.kind == nkIdent) and identEq(x.ident, "true"): result = true
|
elif (x.kind == nkIdent) and identEq(x.ident, "true"): result = true
|
||||||
elif (x.kind == nkIdent) and identEq(x.ident, "false"): result = false
|
elif (x.kind == nkIdent) and identEq(x.ident, "false"): result = false
|
||||||
else: invalidPragma(n)
|
else: invalidPragma(n)
|
||||||
|
|
||||||
proc filterStrip(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
proc filterStrip(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||||
var pattern = strArg(call, "startswith", 1, "")
|
var pattern = strArg(call, "startswith", 1, "")
|
||||||
var leading = boolArg(call, "leading", 2, true)
|
var leading = boolArg(call, "leading", 2, true)
|
||||||
var trailing = boolArg(call, "trailing", 3, true)
|
var trailing = boolArg(call, "trailing", 3, true)
|
||||||
|
|
@ -62,13 +62,13 @@ proc filterStrip(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||||
var line = newStringOfCap(80)
|
var line = newStringOfCap(80)
|
||||||
while llStreamReadLine(stdin, line):
|
while llStreamReadLine(stdin, line):
|
||||||
var stripped = strip(line, leading, trailing)
|
var stripped = strip(line, leading, trailing)
|
||||||
if (len(pattern) == 0) or startsWith(stripped, pattern):
|
if (len(pattern) == 0) or startsWith(stripped, pattern):
|
||||||
llStreamWriteln(result, stripped)
|
llStreamWriteln(result, stripped)
|
||||||
else:
|
else:
|
||||||
llStreamWriteln(result, line)
|
llStreamWriteln(result, line)
|
||||||
llStreamClose(stdin)
|
llStreamClose(stdin)
|
||||||
|
|
||||||
proc filterReplace(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
proc filterReplace(stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||||
var sub = strArg(call, "sub", 1, "")
|
var sub = strArg(call, "sub", 1, "")
|
||||||
if len(sub) == 0: invalidPragma(call)
|
if len(sub) == 0: invalidPragma(call)
|
||||||
var by = strArg(call, "by", 2, "")
|
var by = strArg(call, "by", 2, "")
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ import ast, astalgo
|
||||||
const
|
const
|
||||||
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||||
mEqUntracedRef, mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
|
mEqUntracedRef, mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
|
||||||
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
|
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
|
||||||
mLtCh, mLtB, mLtPtr}
|
mLtCh, mLtB, mLtPtr}
|
||||||
|
|
||||||
proc isCounter(s: PSym): bool {.inline.} =
|
proc isCounter(s: PSym): bool {.inline.} =
|
||||||
s.kind in {skResult, skVar, skLet, skTemp} and
|
s.kind in {skResult, skVar, skLet, skTemp} and
|
||||||
{sfGlobal, sfAddrTaken} * s.flags == {}
|
{sfGlobal, sfAddrTaken} * s.flags == {}
|
||||||
|
|
||||||
proc isCall(n: PNode): bool {.inline.} =
|
proc isCall(n: PNode): bool {.inline.} =
|
||||||
|
|
@ -29,7 +29,7 @@ proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags
|
||||||
proc getCounter(lastStmt: PNode): PSym =
|
proc getCounter(lastStmt: PNode): PSym =
|
||||||
if lastStmt.isCall:
|
if lastStmt.isCall:
|
||||||
let op = lastStmt.sym
|
let op = lastStmt.sym
|
||||||
if op.magic in {mDec, mInc} or
|
if op.magic in {mDec, mInc} or
|
||||||
((op.name.s == "+=" or op.name.s == "-=") and op.fromSystem):
|
((op.name.s == "+=" or op.name.s == "-=") and op.fromSystem):
|
||||||
if op[1].kind == nkSym and isCounter(op[1].sym):
|
if op[1].kind == nkSym and isCounter(op[1].sym):
|
||||||
result = op[1].sym
|
result = op[1].sym
|
||||||
|
|
@ -67,7 +67,7 @@ proc extractForLoop*(loop, fullTree: PNode): ForLoop =
|
||||||
|
|
||||||
if not cond.isCall: return
|
if not cond.isCall: return
|
||||||
if cond[0].sym.magic notin someCmp: return
|
if cond[0].sym.magic notin someCmp: return
|
||||||
|
|
||||||
var lastStmt = loop[1]
|
var lastStmt = loop[1]
|
||||||
while lastStmt.kind in {nkStmtList, nkStmtListExpr}:
|
while lastStmt.kind in {nkStmtList, nkStmtListExpr}:
|
||||||
lastStmt = lastStmt.lastSon
|
lastStmt = lastStmt.lastSon
|
||||||
|
|
@ -76,7 +76,7 @@ proc extractForLoop*(loop, fullTree: PNode): ForLoop =
|
||||||
if counter.isNil or counter.ast.isNil: return
|
if counter.isNil or counter.ast.isNil: return
|
||||||
|
|
||||||
template `=~`(a, b): expr = a.kind == nkSym and a.sym == b
|
template `=~`(a, b): expr = a.kind == nkSym and a.sym == b
|
||||||
|
|
||||||
if cond[1] =~ counter or cond[2] =~ counter:
|
if cond[1] =~ counter or cond[2] =~ counter:
|
||||||
# ok, now check 'counter' is not used *after* the loop
|
# ok, now check 'counter' is not used *after* the loop
|
||||||
if counterInTree(fullTree, loop, counter): return
|
if counterInTree(fullTree, loop, counter): return
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result = semDirectOp(c, n, {})
|
result = semDirectOp(c, n, {})
|
||||||
if optHints in gOptions and hintPattern in gNotes:
|
if optHints in gOptions and hintPattern in gNotes:
|
||||||
message(orig.info, hintPattern, rule & " --> '" &
|
message(orig.info, hintPattern, rule & " --> '" &
|
||||||
renderTree(result, {renderNoComments}) & "'")
|
renderTree(result, {renderNoComments}) & "'")
|
||||||
|
|
||||||
proc applyPatterns(c: PContext, n: PNode): PNode =
|
proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -68,7 +68,7 @@ proc hlo(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
|
if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
|
||||||
n.sons[0].kind == nkSym and
|
n.sons[0].kind == nkSym and
|
||||||
{sfGlobal, sfPure} * n.sons[0].sym.flags == {sfGlobal, sfPure}:
|
{sfGlobal, sfPure} * n.sons[0].sym.flags == {sfGlobal, sfPure}:
|
||||||
# do not optimize 'var g {.global} = re(...)' again!
|
# do not optimize 'var g {.global} = re(...)' again!
|
||||||
return n
|
return n
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@
|
||||||
# An identifier is a shared immutable 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
|
||||||
hashes, strutils, etcpriv
|
hashes, strutils, etcpriv
|
||||||
|
|
||||||
type
|
type
|
||||||
TIdObj* = object of RootObj
|
TIdObj* = object of RootObj
|
||||||
id*: int # unique id; use this for comparisons and not the pointers
|
id*: int # unique id; use this for comparisons and not the pointers
|
||||||
|
|
||||||
PIdObj* = ref TIdObj
|
PIdObj* = ref TIdObj
|
||||||
PIdent* = ref TIdent
|
PIdent* = ref TIdent
|
||||||
TIdent*{.acyclic.} = object of TIdObj
|
TIdent*{.acyclic.} = object of TIdObj
|
||||||
|
|
@ -45,12 +45,12 @@ proc cmpIgnoreStyle(a, b: cstring, blen: int): int =
|
||||||
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)
|
||||||
inc(j)
|
inc(j)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
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 i = 0
|
var i = 0
|
||||||
var j = 0
|
var j = 0
|
||||||
|
|
@ -59,10 +59,10 @@ proc cmpExact(a, b: cstring, blen: int): int =
|
||||||
var aa = a[i]
|
var aa = a[i]
|
||||||
var 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)
|
||||||
inc(j)
|
inc(j)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
if a[i] != '\0': result = 1
|
if a[i] != '\0': result = 1
|
||||||
|
|
||||||
var wordCounter = 1
|
var wordCounter = 1
|
||||||
|
|
@ -72,14 +72,14 @@ proc getIdent*(identifier: cstring, length: int, h: Hash): PIdent =
|
||||||
result = buckets[idx]
|
result = buckets[idx]
|
||||||
var last: PIdent = nil
|
var last: PIdent = nil
|
||||||
var 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:
|
||||||
# make access to last looked up identifier faster:
|
# make access to last looked up identifier faster:
|
||||||
last.next = result.next
|
last.next = result.next
|
||||||
result.next = buckets[idx]
|
result.next = buckets[idx]
|
||||||
buckets[idx] = result
|
buckets[idx] = result
|
||||||
return
|
return
|
||||||
elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0:
|
elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0:
|
||||||
assert((id == 0) or (id == result.id))
|
assert((id == 0) or (id == result.id))
|
||||||
id = result.id
|
id = result.id
|
||||||
|
|
@ -91,20 +91,20 @@ proc getIdent*(identifier: cstring, length: int, h: Hash): PIdent =
|
||||||
for i in countup(0, length - 1): result.s[i] = identifier[i]
|
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
|
result.id = id
|
||||||
|
|
||||||
proc getIdent*(identifier: string): PIdent =
|
proc getIdent*(identifier: string): PIdent =
|
||||||
result = getIdent(cstring(identifier), len(identifier),
|
result = getIdent(cstring(identifier), len(identifier),
|
||||||
hashIgnoreStyle(identifier))
|
hashIgnoreStyle(identifier))
|
||||||
|
|
||||||
proc getIdent*(identifier: string, h: Hash): PIdent =
|
proc getIdent*(identifier: string, h: Hash): PIdent =
|
||||||
result = getIdent(cstring(identifier), len(identifier), h)
|
result = getIdent(cstring(identifier), len(identifier), h)
|
||||||
|
|
||||||
proc identEq*(id: PIdent, name: string): bool =
|
proc identEq*(id: PIdent, name: string): bool =
|
||||||
result = id.id == getIdent(name).id
|
result = id.id == getIdent(name).id
|
||||||
|
|
||||||
var idAnon* = getIdent":anonymous"
|
var idAnon* = getIdent":anonymous"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# This module implements a generic doubled linked list.
|
# This module implements a generic doubled linked list.
|
||||||
# TODO Remove this and replace it with something sensible
|
# TODO Remove this and replace it with something sensible
|
||||||
import os
|
import os
|
||||||
type
|
type
|
||||||
PListEntry* = ref TListEntry
|
PListEntry* = ref TListEntry
|
||||||
TListEntry* = object of RootObj
|
TListEntry* = object of RootObj
|
||||||
prev*, next*: PListEntry
|
prev*, next*: PListEntry
|
||||||
|
|
@ -25,68 +25,68 @@ type
|
||||||
|
|
||||||
TCompareProc* = proc (entry: PListEntry, closure: pointer): bool {.nimcall.}
|
TCompareProc* = proc (entry: PListEntry, closure: pointer): bool {.nimcall.}
|
||||||
|
|
||||||
proc initLinkedList*(list: var TLinkedList) =
|
proc initLinkedList*(list: var TLinkedList) =
|
||||||
list.counter = 0
|
list.counter = 0
|
||||||
list.head = nil
|
list.head = nil
|
||||||
list.tail = nil
|
list.tail = nil
|
||||||
|
|
||||||
proc append*(list: var TLinkedList, entry: PListEntry) =
|
proc append*(list: var TLinkedList, entry: PListEntry) =
|
||||||
inc(list.counter)
|
inc(list.counter)
|
||||||
entry.next = nil
|
entry.next = nil
|
||||||
entry.prev = list.tail
|
entry.prev = list.tail
|
||||||
if list.tail != nil:
|
if list.tail != nil:
|
||||||
assert(list.tail.next == nil)
|
assert(list.tail.next == nil)
|
||||||
list.tail.next = entry
|
list.tail.next = entry
|
||||||
list.tail = entry
|
list.tail = entry
|
||||||
if list.head == nil: list.head = entry
|
if list.head == nil: list.head = entry
|
||||||
|
|
||||||
proc contains*(list: TLinkedList, data: string): bool =
|
proc contains*(list: TLinkedList, data: string): bool =
|
||||||
var it = list.head
|
var it = list.head
|
||||||
while it != nil:
|
while it != nil:
|
||||||
if PStrEntry(it).data == data:
|
if PStrEntry(it).data == data:
|
||||||
return true
|
return true
|
||||||
it = it.next
|
it = it.next
|
||||||
|
|
||||||
proc newStrEntry(data: string): PStrEntry =
|
proc newStrEntry(data: string): PStrEntry =
|
||||||
new(result)
|
new(result)
|
||||||
result.data = data
|
result.data = data
|
||||||
|
|
||||||
proc appendStr*(list: var TLinkedList, data: string) =
|
proc appendStr*(list: var TLinkedList, data: string) =
|
||||||
append(list, newStrEntry(data))
|
append(list, newStrEntry(data))
|
||||||
|
|
||||||
proc includeStr*(list: var TLinkedList, data: string): bool =
|
proc includeStr*(list: var TLinkedList, data: string): bool =
|
||||||
if contains(list, data): return true
|
if contains(list, data): return true
|
||||||
appendStr(list, data) # else: add to list
|
appendStr(list, data) # else: add to list
|
||||||
|
|
||||||
proc prepend*(list: var TLinkedList, entry: PListEntry) =
|
proc prepend*(list: var TLinkedList, entry: PListEntry) =
|
||||||
inc(list.counter)
|
inc(list.counter)
|
||||||
entry.prev = nil
|
entry.prev = nil
|
||||||
entry.next = list.head
|
entry.next = list.head
|
||||||
if list.head != nil:
|
if list.head != nil:
|
||||||
assert(list.head.prev == nil)
|
assert(list.head.prev == nil)
|
||||||
list.head.prev = entry
|
list.head.prev = entry
|
||||||
list.head = entry
|
list.head = entry
|
||||||
if list.tail == nil: list.tail = entry
|
if list.tail == nil: list.tail = entry
|
||||||
|
|
||||||
proc prependStr*(list: var TLinkedList, data: string) =
|
proc prependStr*(list: var TLinkedList, data: string) =
|
||||||
prepend(list, newStrEntry(data))
|
prepend(list, newStrEntry(data))
|
||||||
|
|
||||||
proc insertBefore*(list: var TLinkedList, pos, entry: PListEntry) =
|
proc insertBefore*(list: var TLinkedList, pos, entry: PListEntry) =
|
||||||
assert(pos != nil)
|
assert(pos != nil)
|
||||||
if pos == list.head:
|
if pos == list.head:
|
||||||
prepend(list, entry)
|
prepend(list, entry)
|
||||||
else:
|
else:
|
||||||
inc(list.counter)
|
inc(list.counter)
|
||||||
entry.next = pos
|
entry.next = pos
|
||||||
entry.prev = pos.prev
|
entry.prev = pos.prev
|
||||||
if pos.prev != nil: pos.prev.next = entry
|
if pos.prev != nil: pos.prev.next = entry
|
||||||
pos.prev = entry
|
pos.prev = entry
|
||||||
|
|
||||||
proc remove*(list: var TLinkedList, entry: PListEntry) =
|
proc remove*(list: var TLinkedList, entry: PListEntry) =
|
||||||
dec(list.counter)
|
dec(list.counter)
|
||||||
if entry == list.tail:
|
if entry == list.tail:
|
||||||
list.tail = entry.prev
|
list.tail = entry.prev
|
||||||
if entry == list.head:
|
if entry == list.head:
|
||||||
list.head = entry.next
|
list.head = entry.next
|
||||||
if entry.next != nil: entry.next.prev = entry.prev
|
if entry.next != nil: entry.next.prev = entry.prev
|
||||||
if entry.prev != nil: entry.prev.next = entry.next
|
if entry.prev != nil: entry.prev.next = entry.next
|
||||||
|
|
@ -112,8 +112,8 @@ proc excludePath*(list: var TLinkedList, data: string) =
|
||||||
remove(list, it)
|
remove(list, it)
|
||||||
it = nxt
|
it = nxt
|
||||||
|
|
||||||
proc find*(list: TLinkedList, fn: TCompareProc, closure: pointer): PListEntry =
|
proc find*(list: TLinkedList, fn: TCompareProc, closure: pointer): PListEntry =
|
||||||
result = list.head
|
result = list.head
|
||||||
while result != nil:
|
while result != nil:
|
||||||
if fn(result, closure): return
|
if fn(result, closure): return
|
||||||
result = result.next
|
result = result.next
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
# Built-in types and compilerprocs are registered here.
|
# Built-in types and compilerprocs are registered here.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
|
ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
|
||||||
|
|
||||||
var systemModule*: PSym
|
var systemModule*: PSym
|
||||||
|
|
@ -29,23 +29,23 @@ var
|
||||||
|
|
||||||
proc nilOrSysInt*: PType = gSysTypes[tyInt]
|
proc nilOrSysInt*: PType = gSysTypes[tyInt]
|
||||||
|
|
||||||
proc registerSysType(t: PType) =
|
proc registerSysType(t: PType) =
|
||||||
if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
|
if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
|
||||||
|
|
||||||
proc newSysType(kind: TTypeKind, size: int): PType =
|
proc newSysType(kind: TTypeKind, size: int): PType =
|
||||||
result = newType(kind, systemModule)
|
result = newType(kind, systemModule)
|
||||||
result.size = size
|
result.size = size
|
||||||
result.align = size.int16
|
result.align = size.int16
|
||||||
|
|
||||||
proc getSysSym(name: string): PSym =
|
proc getSysSym(name: string): PSym =
|
||||||
result = strTableGet(systemModule.tab, getIdent(name))
|
result = strTableGet(systemModule.tab, getIdent(name))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
rawMessage(errSystemNeeds, name)
|
rawMessage(errSystemNeeds, name)
|
||||||
result = newSym(skError, getIdent(name), systemModule, systemModule.info)
|
result = newSym(skError, getIdent(name), systemModule, systemModule.info)
|
||||||
result.typ = newType(tyError, systemModule)
|
result.typ = newType(tyError, systemModule)
|
||||||
if result.kind == skStub: loadStub(result)
|
if result.kind == skStub: loadStub(result)
|
||||||
if result.kind == skAlias: result = result.owner
|
if result.kind == skAlias: result = result.owner
|
||||||
|
|
||||||
proc getSysMagic*(name: string, m: TMagic): PSym =
|
proc getSysMagic*(name: string, m: TMagic): PSym =
|
||||||
var ti: TIdentIter
|
var ti: TIdentIter
|
||||||
let id = getIdent(name)
|
let id = getIdent(name)
|
||||||
|
|
@ -57,13 +57,13 @@ proc getSysMagic*(name: string, m: TMagic): PSym =
|
||||||
rawMessage(errSystemNeeds, name)
|
rawMessage(errSystemNeeds, name)
|
||||||
result = newSym(skError, id, systemModule, systemModule.info)
|
result = newSym(skError, id, systemModule, systemModule.info)
|
||||||
result.typ = newType(tyError, systemModule)
|
result.typ = newType(tyError, systemModule)
|
||||||
|
|
||||||
proc sysTypeFromName*(name: string): PType =
|
proc sysTypeFromName*(name: string): PType =
|
||||||
result = getSysSym(name).typ
|
result = getSysSym(name).typ
|
||||||
|
|
||||||
proc getSysType(kind: TTypeKind): PType =
|
proc getSysType(kind: TTypeKind): PType =
|
||||||
result = gSysTypes[kind]
|
result = gSysTypes[kind]
|
||||||
if result == nil:
|
if result == nil:
|
||||||
case kind
|
case kind
|
||||||
of tyInt: result = sysTypeFromName("int")
|
of tyInt: result = sysTypeFromName("int")
|
||||||
of tyInt8: result = sysTypeFromName("int8")
|
of tyInt8: result = sysTypeFromName("int8")
|
||||||
|
|
@ -87,7 +87,7 @@ proc getSysType(kind: TTypeKind): PType =
|
||||||
of tyNil: result = newSysType(tyNil, ptrSize)
|
of tyNil: result = newSysType(tyNil, ptrSize)
|
||||||
else: internalError("request for typekind: " & $kind)
|
else: internalError("request for typekind: " & $kind)
|
||||||
gSysTypes[kind] = result
|
gSysTypes[kind] = result
|
||||||
if result.kind != kind:
|
if result.kind != kind:
|
||||||
internalError("wanted: " & $kind & " got: " & $result.kind)
|
internalError("wanted: " & $kind & " got: " & $result.kind)
|
||||||
if result == nil: internalError("type not found: " & $kind)
|
if result == nil: internalError("type not found: " & $kind)
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ proc setIntLitType*(result: PNode) =
|
||||||
result.typ = getSysType(tyInt64)
|
result.typ = getSysType(tyInt64)
|
||||||
else: internalError(result.info, "invalid int size")
|
else: internalError(result.info, "invalid int size")
|
||||||
|
|
||||||
proc getCompilerProc(name: string): PSym =
|
proc getCompilerProc(name: string): PSym =
|
||||||
var ident = getIdent(name, hashIgnoreStyle(name))
|
var ident = getIdent(name, hashIgnoreStyle(name))
|
||||||
result = strTableGet(compilerprocs, ident)
|
result = strTableGet(compilerprocs, ident)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
|
|
||||||
import parseutils, strutils, strtabs, os, options, msgs, lists
|
import parseutils, strutils, strtabs, os, options, msgs, lists
|
||||||
|
|
||||||
proc addPath*(path: string, info: TLineInfo) =
|
proc addPath*(path: string, info: TLineInfo) =
|
||||||
if not contains(options.searchPaths, path):
|
if not contains(options.searchPaths, path):
|
||||||
lists.prependStr(options.searchPaths, path)
|
lists.prependStr(options.searchPaths, path)
|
||||||
|
|
||||||
proc versionSplitPos(s: string): int =
|
proc versionSplitPos(s: string): int =
|
||||||
|
|
@ -23,7 +23,7 @@ proc versionSplitPos(s: string): int =
|
||||||
const
|
const
|
||||||
latest = "head"
|
latest = "head"
|
||||||
|
|
||||||
proc `<.`(a, b: string): bool =
|
proc `<.`(a, b: string): bool =
|
||||||
# wether a has a smaller version than b:
|
# wether a has a smaller version than b:
|
||||||
if a == latest: return false
|
if a == latest: return false
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## exposes the Nim VM to clients.
|
## exposes the Nim VM to clients.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, modules, passes, passaux, condsyms,
|
ast, modules, passes, passaux, condsyms,
|
||||||
options, nimconf, lists, sem, semdata, llstream, vm
|
options, nimconf, lists, sem, semdata, llstream, vm
|
||||||
|
|
||||||
proc execute*(program: string) =
|
proc execute*(program: string) =
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@
|
||||||
# handling that exists! Only at line endings checks are necessary
|
# handling that exists! Only at line endings checks are necessary
|
||||||
# if the buffer needs refilling.
|
# if the buffer needs refilling.
|
||||||
|
|
||||||
import
|
import
|
||||||
llstream, strutils
|
llstream, strutils
|
||||||
|
|
||||||
const
|
const
|
||||||
Lrz* = ' '
|
Lrz* = ' '
|
||||||
Apo* = '\''
|
Apo* = '\''
|
||||||
Tabulator* = '\x09'
|
Tabulator* = '\x09'
|
||||||
|
|
@ -27,7 +27,7 @@ const
|
||||||
BACKSPACE* = '\x08'
|
BACKSPACE* = '\x08'
|
||||||
VT* = '\x0B'
|
VT* = '\x0B'
|
||||||
|
|
||||||
const
|
const
|
||||||
EndOfFile* = '\0' # end of file marker
|
EndOfFile* = '\0' # end of file marker
|
||||||
# A little picture makes everything clear :-)
|
# A little picture makes everything clear :-)
|
||||||
# buf:
|
# buf:
|
||||||
|
|
@ -36,7 +36,7 @@ const
|
||||||
#
|
#
|
||||||
NewLines* = {CR, LF}
|
NewLines* = {CR, LF}
|
||||||
|
|
||||||
type
|
type
|
||||||
TBaseLexer* = object of RootObj
|
TBaseLexer* = object of RootObj
|
||||||
bufpos*: int
|
bufpos*: int
|
||||||
buf*: cstring
|
buf*: cstring
|
||||||
|
|
@ -46,9 +46,9 @@ type
|
||||||
# private data:
|
# private data:
|
||||||
sentinel*: int
|
sentinel*: int
|
||||||
lineStart*: int # index of last line start in buffer
|
lineStart*: int # index of last line start in buffer
|
||||||
|
|
||||||
|
|
||||||
proc openBaseLexer*(L: var TBaseLexer, inputstream: PLLStream,
|
|
||||||
|
proc openBaseLexer*(L: var TBaseLexer, inputstream: PLLStream,
|
||||||
bufLen: int = 8192)
|
bufLen: int = 8192)
|
||||||
# 8K is a reasonable buffer size
|
# 8K is a reasonable buffer size
|
||||||
proc closeBaseLexer*(L: var TBaseLexer)
|
proc closeBaseLexer*(L: var TBaseLexer)
|
||||||
|
|
@ -64,15 +64,15 @@ proc handleLF*(L: var TBaseLexer, pos: int): int
|
||||||
# of the LF.
|
# of the LF.
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
chrSize = sizeof(char)
|
chrSize = sizeof(char)
|
||||||
|
|
||||||
proc closeBaseLexer(L: var TBaseLexer) =
|
proc closeBaseLexer(L: var TBaseLexer) =
|
||||||
dealloc(L.buf)
|
dealloc(L.buf)
|
||||||
llStreamClose(L.stream)
|
llStreamClose(L.stream)
|
||||||
|
|
||||||
proc fillBuffer(L: var TBaseLexer) =
|
proc fillBuffer(L: var TBaseLexer) =
|
||||||
var
|
var
|
||||||
charsRead, toCopy, s: int # all are in characters,
|
charsRead, toCopy, s: int # all are in characters,
|
||||||
# not bytes (in case this
|
# not bytes (in case this
|
||||||
# is not the same)
|
# is not the same)
|
||||||
|
|
@ -82,68 +82,68 @@ proc fillBuffer(L: var TBaseLexer) =
|
||||||
assert(L.sentinel < L.bufLen)
|
assert(L.sentinel < L.bufLen)
|
||||||
toCopy = L.bufLen - L.sentinel - 1
|
toCopy = L.bufLen - L.sentinel - 1
|
||||||
assert(toCopy >= 0)
|
assert(toCopy >= 0)
|
||||||
if toCopy > 0:
|
if toCopy > 0:
|
||||||
moveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize)
|
moveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize)
|
||||||
# "moveMem" handles overlapping regions
|
# "moveMem" handles overlapping regions
|
||||||
charsRead = llStreamRead(L.stream, addr(L.buf[toCopy]),
|
charsRead = llStreamRead(L.stream, addr(L.buf[toCopy]),
|
||||||
(L.sentinel + 1) * chrSize) div chrSize
|
(L.sentinel + 1) * chrSize) div chrSize
|
||||||
s = toCopy + charsRead
|
s = toCopy + charsRead
|
||||||
if charsRead < L.sentinel + 1:
|
if charsRead < L.sentinel + 1:
|
||||||
L.buf[s] = EndOfFile # set end marker
|
L.buf[s] = EndOfFile # set end marker
|
||||||
L.sentinel = s
|
L.sentinel = s
|
||||||
else:
|
else:
|
||||||
# compute sentinel:
|
# compute sentinel:
|
||||||
dec(s) # BUGFIX (valgrind)
|
dec(s) # BUGFIX (valgrind)
|
||||||
while true:
|
while true:
|
||||||
assert(s < L.bufLen)
|
assert(s < L.bufLen)
|
||||||
while (s >= 0) and not (L.buf[s] in NewLines): dec(s)
|
while (s >= 0) and not (L.buf[s] in NewLines): dec(s)
|
||||||
if s >= 0:
|
if s >= 0:
|
||||||
# we found an appropriate character for a sentinel:
|
# we found an appropriate character for a sentinel:
|
||||||
L.sentinel = s
|
L.sentinel = s
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# rather than to give up here because the line is too long,
|
# rather than to give up here because the line is too long,
|
||||||
# double the buffer's size and try again:
|
# double the buffer's size and try again:
|
||||||
oldBufLen = L.bufLen
|
oldBufLen = L.bufLen
|
||||||
L.bufLen = L.bufLen * 2
|
L.bufLen = L.bufLen * 2
|
||||||
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
|
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
|
||||||
assert(L.bufLen - oldBufLen == oldBufLen)
|
assert(L.bufLen - oldBufLen == oldBufLen)
|
||||||
charsRead = llStreamRead(L.stream, addr(L.buf[oldBufLen]),
|
charsRead = llStreamRead(L.stream, addr(L.buf[oldBufLen]),
|
||||||
oldBufLen * chrSize) div chrSize
|
oldBufLen * chrSize) div chrSize
|
||||||
if charsRead < oldBufLen:
|
if charsRead < oldBufLen:
|
||||||
L.buf[oldBufLen + charsRead] = EndOfFile
|
L.buf[oldBufLen + charsRead] = EndOfFile
|
||||||
L.sentinel = oldBufLen + charsRead
|
L.sentinel = oldBufLen + charsRead
|
||||||
break
|
break
|
||||||
s = L.bufLen - 1
|
s = L.bufLen - 1
|
||||||
|
|
||||||
proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
|
proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
|
||||||
assert(pos <= L.sentinel)
|
assert(pos <= L.sentinel)
|
||||||
if pos < L.sentinel:
|
if pos < L.sentinel:
|
||||||
result = pos + 1 # nothing to do
|
result = pos + 1 # nothing to do
|
||||||
else:
|
else:
|
||||||
fillBuffer(L)
|
fillBuffer(L)
|
||||||
L.bufpos = 0 # XXX: is this really correct?
|
L.bufpos = 0 # XXX: is this really correct?
|
||||||
result = 0
|
result = 0
|
||||||
L.lineStart = result
|
L.lineStart = result
|
||||||
|
|
||||||
proc handleCR(L: var TBaseLexer, pos: int): int =
|
proc handleCR(L: var TBaseLexer, pos: int): int =
|
||||||
assert(L.buf[pos] == CR)
|
assert(L.buf[pos] == CR)
|
||||||
inc(L.lineNumber)
|
inc(L.lineNumber)
|
||||||
result = fillBaseLexer(L, pos)
|
result = fillBaseLexer(L, pos)
|
||||||
if L.buf[result] == LF:
|
if L.buf[result] == LF:
|
||||||
result = fillBaseLexer(L, result)
|
result = fillBaseLexer(L, result)
|
||||||
|
|
||||||
proc handleLF(L: var TBaseLexer, pos: int): int =
|
proc handleLF(L: var TBaseLexer, pos: int): int =
|
||||||
assert(L.buf[pos] == LF)
|
assert(L.buf[pos] == LF)
|
||||||
inc(L.lineNumber)
|
inc(L.lineNumber)
|
||||||
result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
|
result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
|
||||||
|
|
||||||
proc skipUTF8BOM(L: var TBaseLexer) =
|
proc skipUTF8BOM(L: var TBaseLexer) =
|
||||||
if L.buf[0] == '\xEF' and L.buf[1] == '\xBB' and L.buf[2] == '\xBF':
|
if L.buf[0] == '\xEF' and L.buf[1] == '\xBB' and L.buf[2] == '\xBF':
|
||||||
inc(L.bufpos, 3)
|
inc(L.bufpos, 3)
|
||||||
inc(L.lineStart, 3)
|
inc(L.lineStart, 3)
|
||||||
|
|
||||||
proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
|
proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
|
||||||
assert(bufLen > 0)
|
assert(bufLen > 0)
|
||||||
L.bufpos = 0
|
L.bufpos = 0
|
||||||
L.bufLen = bufLen
|
L.bufLen = bufLen
|
||||||
|
|
@ -155,15 +155,15 @@ proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
|
||||||
fillBuffer(L)
|
fillBuffer(L)
|
||||||
skipUTF8BOM(L)
|
skipUTF8BOM(L)
|
||||||
|
|
||||||
proc getColNumber(L: TBaseLexer, pos: int): int =
|
proc getColNumber(L: TBaseLexer, pos: int): int =
|
||||||
result = abs(pos - L.lineStart)
|
result = abs(pos - L.lineStart)
|
||||||
|
|
||||||
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
||||||
result = ""
|
result = ""
|
||||||
var i = L.lineStart
|
var i = L.lineStart
|
||||||
while not (L.buf[i] in {CR, LF, EndOfFile}):
|
while not (L.buf[i] in {CR, LF, EndOfFile}):
|
||||||
add(result, L.buf[i])
|
add(result, L.buf[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
result.add("\n")
|
result.add("\n")
|
||||||
if marker:
|
if marker:
|
||||||
result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
|
result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
# this unit handles Nim sets; it implements symbolic sets
|
# this unit handles Nim sets; it implements symbolic sets
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
|
ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
|
||||||
|
|
||||||
proc toBitSet*(s: PNode, b: var TBitSet)
|
proc toBitSet*(s: PNode, b: var TBitSet)
|
||||||
|
|
@ -30,17 +30,17 @@ proc equalSets*(a, b: PNode): bool
|
||||||
proc cardSet*(s: PNode): BiggestInt
|
proc cardSet*(s: PNode): BiggestInt
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc inSet(s: PNode, elem: PNode): bool =
|
proc inSet(s: PNode, elem: PNode): bool =
|
||||||
if s.kind != nkCurly:
|
if s.kind != nkCurly:
|
||||||
internalError(s.info, "inSet")
|
internalError(s.info, "inSet")
|
||||||
return false
|
return false
|
||||||
for i in countup(0, sonsLen(s) - 1):
|
for i in countup(0, sonsLen(s) - 1):
|
||||||
if s.sons[i].kind == nkRange:
|
if s.sons[i].kind == nkRange:
|
||||||
if leValue(s.sons[i].sons[0], elem) and
|
if leValue(s.sons[i].sons[0], elem) and
|
||||||
leValue(elem, s.sons[i].sons[1]):
|
leValue(elem, s.sons[i].sons[1]):
|
||||||
return true
|
return true
|
||||||
else:
|
else:
|
||||||
if sameValue(s.sons[i], elem):
|
if sameValue(s.sons[i], elem):
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
|
|
@ -58,37 +58,37 @@ proc overlap(a, b: PNode): bool =
|
||||||
else:
|
else:
|
||||||
result = sameValue(a, b)
|
result = sameValue(a, b)
|
||||||
|
|
||||||
proc someInSet(s: PNode, a, b: PNode): bool =
|
proc someInSet(s: PNode, a, b: PNode): bool =
|
||||||
# checks if some element of a..b is in the set s
|
# checks if some element of a..b is in the set s
|
||||||
if s.kind != nkCurly:
|
if s.kind != nkCurly:
|
||||||
internalError(s.info, "SomeInSet")
|
internalError(s.info, "SomeInSet")
|
||||||
return false
|
return false
|
||||||
for i in countup(0, sonsLen(s) - 1):
|
for i in countup(0, sonsLen(s) - 1):
|
||||||
if s.sons[i].kind == nkRange:
|
if s.sons[i].kind == nkRange:
|
||||||
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
|
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
|
||||||
leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
|
leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
|
||||||
return true
|
return true
|
||||||
else:
|
else:
|
||||||
# a <= elem <= b
|
# a <= elem <= b
|
||||||
if leValue(a, s.sons[i]) and leValue(s.sons[i], b):
|
if leValue(a, s.sons[i]) and leValue(s.sons[i], b):
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc toBitSet(s: PNode, b: var TBitSet) =
|
proc toBitSet(s: PNode, b: var TBitSet) =
|
||||||
var first, j: BiggestInt
|
var first, j: BiggestInt
|
||||||
first = firstOrd(s.typ.sons[0])
|
first = firstOrd(s.typ.sons[0])
|
||||||
bitSetInit(b, int(getSize(s.typ)))
|
bitSetInit(b, int(getSize(s.typ)))
|
||||||
for i in countup(0, sonsLen(s) - 1):
|
for i in countup(0, sonsLen(s) - 1):
|
||||||
if s.sons[i].kind == nkRange:
|
if s.sons[i].kind == nkRange:
|
||||||
j = getOrdValue(s.sons[i].sons[0])
|
j = getOrdValue(s.sons[i].sons[0])
|
||||||
while j <= getOrdValue(s.sons[i].sons[1]):
|
while j <= getOrdValue(s.sons[i].sons[1]):
|
||||||
bitSetIncl(b, j - first)
|
bitSetIncl(b, j - first)
|
||||||
inc(j)
|
inc(j)
|
||||||
else:
|
else:
|
||||||
bitSetIncl(b, getOrdValue(s.sons[i]) - first)
|
bitSetIncl(b, getOrdValue(s.sons[i]) - first)
|
||||||
|
|
||||||
proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||||
var
|
var
|
||||||
a, b, e, first: BiggestInt # a, b are interval borders
|
a, b, e, first: BiggestInt # a, b are interval borders
|
||||||
elemType: PType
|
elemType: PType
|
||||||
n: PNode
|
n: PNode
|
||||||
|
|
@ -98,17 +98,17 @@ proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||||
result.typ = settype
|
result.typ = settype
|
||||||
result.info = info
|
result.info = info
|
||||||
e = 0
|
e = 0
|
||||||
while e < len(s) * ElemSize:
|
while e < len(s) * ElemSize:
|
||||||
if bitSetIn(s, e):
|
if bitSetIn(s, e):
|
||||||
a = e
|
a = e
|
||||||
b = e
|
b = e
|
||||||
while true:
|
while true:
|
||||||
inc(b)
|
inc(b)
|
||||||
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
|
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
|
||||||
dec(b)
|
dec(b)
|
||||||
if a == b:
|
if a == b:
|
||||||
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
|
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
|
||||||
else:
|
else:
|
||||||
n = newNodeI(nkRange, info)
|
n = newNodeI(nkRange, info)
|
||||||
n.typ = elemType
|
n.typ = elemType
|
||||||
addSon(n, newIntTypeNode(nkIntLit, a + first, elemType))
|
addSon(n, newIntTypeNode(nkIntLit, a + first, elemType))
|
||||||
|
|
@ -117,7 +117,7 @@ proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||||
e = b
|
e = b
|
||||||
inc(e)
|
inc(e)
|
||||||
|
|
||||||
template nodeSetOp(a, b: PNode, op: expr) {.dirty.} =
|
template nodeSetOp(a, b: PNode, op: expr) {.dirty.} =
|
||||||
var x, y: TBitSet
|
var x, y: TBitSet
|
||||||
toBitSet(a, x)
|
toBitSet(a, x)
|
||||||
toBitSet(b, y)
|
toBitSet(b, y)
|
||||||
|
|
@ -129,13 +129,13 @@ proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
|
||||||
proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
|
proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
|
||||||
proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
|
proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
|
||||||
|
|
||||||
proc containsSets(a, b: PNode): bool =
|
proc containsSets(a, b: PNode): bool =
|
||||||
var x, y: TBitSet
|
var x, y: TBitSet
|
||||||
toBitSet(a, x)
|
toBitSet(a, x)
|
||||||
toBitSet(b, y)
|
toBitSet(b, y)
|
||||||
result = bitSetContains(x, y)
|
result = bitSetContains(x, y)
|
||||||
|
|
||||||
proc equalSets(a, b: PNode): bool =
|
proc equalSets(a, b: PNode): bool =
|
||||||
var x, y: TBitSet
|
var x, y: TBitSet
|
||||||
toBitSet(a, x)
|
toBitSet(a, x)
|
||||||
toBitSet(b, y)
|
toBitSet(b, y)
|
||||||
|
|
@ -147,26 +147,26 @@ proc complement*(a: PNode): PNode =
|
||||||
for i in countup(0, high(x)): x[i] = not x[i]
|
for i in countup(0, high(x)): x[i] = not x[i]
|
||||||
result = toTreeSet(x, a.typ, a.info)
|
result = toTreeSet(x, a.typ, a.info)
|
||||||
|
|
||||||
proc cardSet(s: PNode): BiggestInt =
|
proc cardSet(s: PNode): BiggestInt =
|
||||||
# here we can do better than converting it into a compact set
|
# here we can do better than converting it into a compact set
|
||||||
# we just count the elements directly
|
# we just count the elements directly
|
||||||
result = 0
|
result = 0
|
||||||
for i in countup(0, sonsLen(s) - 1):
|
for i in countup(0, sonsLen(s) - 1):
|
||||||
if s.sons[i].kind == nkRange:
|
if s.sons[i].kind == nkRange:
|
||||||
result = result + getOrdValue(s.sons[i].sons[1]) -
|
result = result + getOrdValue(s.sons[i].sons[1]) -
|
||||||
getOrdValue(s.sons[i].sons[0]) + 1
|
getOrdValue(s.sons[i].sons[0]) + 1
|
||||||
else:
|
else:
|
||||||
inc(result)
|
inc(result)
|
||||||
|
|
||||||
proc setHasRange(s: PNode): bool =
|
proc setHasRange(s: PNode): bool =
|
||||||
if s.kind != nkCurly:
|
if s.kind != nkCurly:
|
||||||
internalError(s.info, "SetHasRange")
|
internalError(s.info, "SetHasRange")
|
||||||
return false
|
return false
|
||||||
for i in countup(0, sonsLen(s) - 1):
|
for i in countup(0, sonsLen(s) - 1):
|
||||||
if s.sons[i].kind == nkRange:
|
if s.sons[i].kind == nkRange:
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc emptyRange(a, b: PNode): bool =
|
proc emptyRange(a, b: PNode): bool =
|
||||||
result = not leValue(a, b) # a > b iff not (a <= b)
|
result = not leValue(a, b) # a > b iff not (a <= b)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# This module contains Nim's version. It is the only place where it needs
|
# This module contains Nim's version. It is the only place where it needs
|
||||||
# to be changed.
|
# to be changed.
|
||||||
|
|
||||||
const
|
const
|
||||||
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
||||||
VersionAsString* = system.NimVersion
|
VersionAsString* = system.NimVersion
|
||||||
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
||||||
|
|
|
||||||
|
|
@ -9,38 +9,38 @@
|
||||||
|
|
||||||
## implements some little helper passes
|
## implements some little helper passes
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, ast, astalgo, passes, msgs, options, idgen
|
strutils, ast, astalgo, passes, msgs, options, idgen
|
||||||
|
|
||||||
proc verboseOpen(s: PSym): PPassContext =
|
proc verboseOpen(s: PSym): PPassContext =
|
||||||
#MessageOut('compiling ' + s.name.s);
|
#MessageOut('compiling ' + s.name.s);
|
||||||
result = nil # we don't need a context
|
result = nil # we don't need a context
|
||||||
rawMessage(hintProcessing, s.name.s)
|
rawMessage(hintProcessing, s.name.s)
|
||||||
|
|
||||||
proc verboseProcess(context: PPassContext, n: PNode): PNode =
|
proc verboseProcess(context: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
if context != nil: internalError("logpass: context is not nil")
|
if context != nil: internalError("logpass: context is not nil")
|
||||||
if gVerbosity == 3:
|
if gVerbosity == 3:
|
||||||
# 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, $idgen.gBackendId)
|
message(n.info, hintProcessing, $idgen.gBackendId)
|
||||||
|
|
||||||
const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)
|
const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)
|
||||||
|
|
||||||
proc cleanUp(c: PPassContext, n: PNode): PNode =
|
proc cleanUp(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
# we cannot clean up if dead code elimination is activated
|
# we cannot clean up if dead code elimination is activated
|
||||||
if optDeadCodeElim in gGlobalOptions or n == nil: return
|
if optDeadCodeElim in gGlobalOptions or n == nil: return
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkStmtList:
|
of nkStmtList:
|
||||||
for i in countup(0, sonsLen(n) - 1): discard cleanUp(c, n.sons[i])
|
for i in countup(0, sonsLen(n) - 1): discard cleanUp(c, n.sons[i])
|
||||||
of nkProcDef, nkMethodDef:
|
of nkProcDef, nkMethodDef:
|
||||||
if n.sons[namePos].kind == nkSym:
|
if n.sons[namePos].kind == nkSym:
|
||||||
var s = n.sons[namePos].sym
|
var s = n.sons[namePos].sym
|
||||||
if sfDeadCodeElim notin getModule(s).flags and not astNeeded(s):
|
if sfDeadCodeElim notin getModule(s).flags and not astNeeded(s):
|
||||||
s.ast.sons[bodyPos] = ast.emptyNode # free the memory
|
s.ast.sons[bodyPos] = ast.emptyNode # free the memory
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
const cleanupPass* = makePass(process = cleanUp, close = cleanUp)
|
const cleanupPass* = makePass(process = cleanUp, close = cleanUp)
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ proc inSymChoice(sc, x: PNode): bool =
|
||||||
elif sc.kind == nkOpenSymChoice:
|
elif sc.kind == nkOpenSymChoice:
|
||||||
# same name suffices for open sym choices!
|
# same name suffices for open sym choices!
|
||||||
result = sc.sons[0].sym.name.id == x.sym.name.id
|
result = sc.sons[0].sym.name.id == x.sym.name.id
|
||||||
|
|
||||||
proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
|
proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
|
||||||
# check param constraints first here as this is quite optimized:
|
# check param constraints first here as this is quite optimized:
|
||||||
if p.constraint != nil:
|
if p.constraint != nil:
|
||||||
|
|
@ -115,13 +115,13 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
|
||||||
if rpn: arglist.add(n.sons[0])
|
if rpn: arglist.add(n.sons[0])
|
||||||
elif n.kind == nkHiddenStdConv and n.sons[1].kind == nkBracket:
|
elif n.kind == nkHiddenStdConv and n.sons[1].kind == nkBracket:
|
||||||
let n = n.sons[1]
|
let n = n.sons[1]
|
||||||
for i in 0.. <n.len:
|
for i in 0.. <n.len:
|
||||||
if not matchStarAux(c, op, n[i], arglist, rpn): return false
|
if not matchStarAux(c, op, n[i], arglist, rpn): return false
|
||||||
elif checkTypes(c, p.sons[2].sym, n):
|
elif checkTypes(c, p.sons[2].sym, n):
|
||||||
add(arglist, n)
|
add(arglist, n)
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
if n.kind notin nkCallKinds: return false
|
if n.kind notin nkCallKinds: return false
|
||||||
if matches(c, p.sons[1], n.sons[0]):
|
if matches(c, p.sons[1], n.sons[0]):
|
||||||
var arglist = newNodeI(nkArgList, n.info)
|
var arglist = newNodeI(nkArgList, n.info)
|
||||||
|
|
@ -151,7 +151,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
|
||||||
of "**": result = matchNested(c, p, n, rpn=true)
|
of "**": result = matchNested(c, p, n, rpn=true)
|
||||||
of "~": result = not matches(c, p.sons[1], n)
|
of "~": result = not matches(c, p.sons[1], n)
|
||||||
else: internalError(p.info, "invalid pattern")
|
else: internalError(p.info, "invalid pattern")
|
||||||
# template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) =
|
# template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) =
|
||||||
# add(a, b)
|
# add(a, b)
|
||||||
elif p.kind == nkCurlyExpr:
|
elif p.kind == nkCurlyExpr:
|
||||||
if p.sons[1].kind == nkPrefix:
|
if p.sons[1].kind == nkPrefix:
|
||||||
|
|
@ -212,7 +212,7 @@ proc matchStmtList(c: PPatternContext, p, n: PNode): PNode =
|
||||||
if not isNil(c.mapping): c.mapping = nil
|
if not isNil(c.mapping): c.mapping = nil
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
if p.kind == nkStmtList and n.kind == p.kind and p.len < n.len:
|
if p.kind == nkStmtList and n.kind == p.kind and p.len < n.len:
|
||||||
let n = flattenStmts(n)
|
let n = flattenStmts(n)
|
||||||
# no need to flatten 'p' here as that has already been done
|
# no need to flatten 'p' here as that has already been done
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
import
|
import
|
||||||
llstream, lexer, parser, idents, strutils, ast, msgs
|
llstream, lexer, parser, idents, strutils, ast, msgs
|
||||||
|
|
||||||
proc parseAll*(p: var TParser): PNode =
|
proc parseAll*(p: var TParser): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc parseTopLevelStmt*(p: var TParser): PNode =
|
proc parseTopLevelStmt*(p: var TParser): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
result = nextIdentIter(it, scope.symbols)
|
result = nextIdentIter(it, scope.symbols)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||||
|
|
@ -99,17 +99,17 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||||
debug fn.typ
|
debug fn.typ
|
||||||
debug if result != nil: result.typ else: nil
|
debug if result != nil: result.typ else: nil
|
||||||
debug if old != nil: old.typ else: nil
|
debug if old != nil: old.typ else: nil
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc paramsFitBorrow(child, parent: PNode): bool =
|
proc paramsFitBorrow(child, parent: PNode): bool =
|
||||||
var length = sonsLen(child)
|
var length = sonsLen(child)
|
||||||
result = false
|
result = false
|
||||||
if length == sonsLen(parent):
|
if length == sonsLen(parent):
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
var m = child.sons[i].sym
|
var m = child.sons[i].sym
|
||||||
var n = parent.sons[i].sym
|
var n = parent.sons[i].sym
|
||||||
assert((m.kind == skParam) and (n.kind == skParam))
|
assert((m.kind == skParam) and (n.kind == skParam))
|
||||||
if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return
|
if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return
|
||||||
if not compareTypes(child.sons[0].typ, parent.sons[0].typ,
|
if not compareTypes(child.sons[0].typ, parent.sons[0].typ,
|
||||||
dcEqOrDistinctOf): return
|
dcEqOrDistinctOf): return
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -120,10 +120,10 @@ when false:
|
||||||
var it: TIdentIter
|
var it: TIdentIter
|
||||||
for scope in walkScopes(startScope):
|
for scope in walkScopes(startScope):
|
||||||
result = initIdentIter(it, scope.symbols, fn.Name)
|
result = initIdentIter(it, scope.symbols, fn.Name)
|
||||||
while result != nil:
|
while result != nil:
|
||||||
# watchout! result must not be the same as fn!
|
# watchout! result must not be the same as fn!
|
||||||
if (result.Kind == fn.kind) and (result.id != fn.id):
|
if (result.Kind == fn.kind) and (result.id != fn.id):
|
||||||
if equalGenericParams(result.ast.sons[genericParamsPos],
|
if equalGenericParams(result.ast.sons[genericParamsPos],
|
||||||
fn.ast.sons[genericParamsPos]):
|
fn.ast.sons[genericParamsPos]):
|
||||||
if paramsFitBorrow(fn.typ.n, result.typ.n): return
|
if paramsFitBorrow(fn.typ.n, result.typ.n): return
|
||||||
result = NextIdentIter(it, scope.symbols)
|
result = NextIdentIter(it, scope.symbols)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import strutils
|
||||||
|
|
||||||
proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", header: "<stdio.h>", nodecl, varargs.}
|
proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", header: "<stdio.h>", nodecl, varargs.}
|
||||||
|
|
||||||
proc toStrMaxPrecision*(f: BiggestFloat): string =
|
proc toStrMaxPrecision*(f: BiggestFloat): string =
|
||||||
if f != f:
|
if f != f:
|
||||||
result = "NAN"
|
result = "NAN"
|
||||||
elif f == 0.0:
|
elif f == 0.0:
|
||||||
|
|
@ -21,17 +21,17 @@ proc toStrMaxPrecision*(f: BiggestFloat): string =
|
||||||
if f > 0.0: result = "INF"
|
if f > 0.0: result = "INF"
|
||||||
else: result = "-INF"
|
else: result = "-INF"
|
||||||
else:
|
else:
|
||||||
var buf: array [0..80, char]
|
var buf: array [0..80, char]
|
||||||
c_sprintf(buf, "%#.16e", f)
|
c_sprintf(buf, "%#.16e", f)
|
||||||
result = $buf
|
result = $buf
|
||||||
|
|
||||||
proc encodeStr*(s: string, result: var string) =
|
proc encodeStr*(s: string, result: var string) =
|
||||||
for i in countup(0, len(s) - 1):
|
for i in countup(0, len(s) - 1):
|
||||||
case s[i]
|
case s[i]
|
||||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
|
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
|
||||||
else: add(result, '\\' & toHex(ord(s[i]), 2))
|
else: add(result, '\\' & toHex(ord(s[i]), 2))
|
||||||
|
|
||||||
proc hexChar(c: char, xi: var int) =
|
proc hexChar(c: char, xi: var int) =
|
||||||
case c
|
case c
|
||||||
of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
|
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)
|
||||||
|
|
@ -41,18 +41,18 @@ proc hexChar(c: char, xi: var int) =
|
||||||
proc decodeStr*(s: cstring, pos: var int): string =
|
proc decodeStr*(s: cstring, pos: var int): string =
|
||||||
var i = pos
|
var i = pos
|
||||||
result = ""
|
result = ""
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\\':
|
of '\\':
|
||||||
inc(i, 3)
|
inc(i, 3)
|
||||||
var xi = 0
|
var xi = 0
|
||||||
hexChar(s[i-2], xi)
|
hexChar(s[i-2], xi)
|
||||||
hexChar(s[i-1], xi)
|
hexChar(s[i-1], xi)
|
||||||
add(result, chr(xi))
|
add(result, chr(xi))
|
||||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_':
|
of 'a'..'z', 'A'..'Z', '0'..'9', '_':
|
||||||
add(result, s[i])
|
add(result, s[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
else: break
|
else: break
|
||||||
pos = i
|
pos = i
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -68,11 +68,11 @@ template encodeIntImpl(self: expr) =
|
||||||
var d: char
|
var d: char
|
||||||
var v = x
|
var v = x
|
||||||
var rem = v mod 190
|
var rem = v mod 190
|
||||||
if rem < 0:
|
if rem < 0:
|
||||||
add(result, '-')
|
add(result, '-')
|
||||||
v = - (v div 190)
|
v = - (v div 190)
|
||||||
rem = - rem
|
rem = - rem
|
||||||
else:
|
else:
|
||||||
v = v div 190
|
v = v div 190
|
||||||
var idx = int(rem)
|
var idx = int(rem)
|
||||||
if idx < 62: d = chars[idx]
|
if idx < 62: d = chars[idx]
|
||||||
|
|
@ -89,11 +89,11 @@ proc encodeVBiggestInt*(x: BiggestInt, result: var string) =
|
||||||
encodeVBiggestIntAux(x +% vintDelta, result)
|
encodeVBiggestIntAux(x +% vintDelta, result)
|
||||||
# encodeIntImpl(encodeVBiggestInt)
|
# encodeIntImpl(encodeVBiggestInt)
|
||||||
|
|
||||||
proc encodeVIntAux(x: int, result: var string) =
|
proc encodeVIntAux(x: int, result: var string) =
|
||||||
## encode an int as a variable length base 190 int.
|
## encode an int as a variable length base 190 int.
|
||||||
encodeIntImpl(encodeVIntAux)
|
encodeIntImpl(encodeVIntAux)
|
||||||
|
|
||||||
proc encodeVInt*(x: int, result: var string) =
|
proc encodeVInt*(x: int, result: var string) =
|
||||||
## encode an int as a variable length base 190 int.
|
## encode an int as a variable length base 190 int.
|
||||||
encodeVIntAux(x +% vintDelta, result)
|
encodeVIntAux(x +% vintDelta, result)
|
||||||
|
|
||||||
|
|
@ -101,11 +101,11 @@ template decodeIntImpl() =
|
||||||
var i = pos
|
var i = pos
|
||||||
var sign = - 1
|
var sign = - 1
|
||||||
assert(s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
assert(s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
||||||
if s[i] == '-':
|
if s[i] == '-':
|
||||||
inc(i)
|
inc(i)
|
||||||
sign = 1
|
sign = 1
|
||||||
result = 0
|
result = 0
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '0'..'9': result = result * 190 - (ord(s[i]) - ord('0'))
|
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') + 10)
|
||||||
|
|
@ -116,7 +116,7 @@ template decodeIntImpl() =
|
||||||
result = result * sign -% vintDelta
|
result = result * sign -% vintDelta
|
||||||
pos = i
|
pos = i
|
||||||
|
|
||||||
proc decodeVInt*(s: cstring, pos: var int): int =
|
proc decodeVInt*(s: cstring, pos: var int): int =
|
||||||
decodeIntImpl()
|
decodeIntImpl()
|
||||||
|
|
||||||
proc decodeVBiggestInt*(s: cstring, pos: var int): BiggestInt =
|
proc decodeVBiggestInt*(s: cstring, pos: var int): BiggestInt =
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ const
|
||||||
|
|
||||||
proc equalsFile*(r: Rope, f: File): bool =
|
proc equalsFile*(r: Rope, f: File): bool =
|
||||||
## returns true if the contents of the file `f` equal `r`.
|
## returns true if the contents of the file `f` equal `r`.
|
||||||
var
|
var
|
||||||
buf: array[bufSize, char]
|
buf: array[bufSize, char]
|
||||||
bpos = buf.len
|
bpos = buf.len
|
||||||
blen = buf.len
|
blen = buf.len
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ proc `|*|`*(a, b: BiggestInt): BiggestInt =
|
||||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if floatProd >= 0.0:
|
if floatProd >= 0.0:
|
||||||
result = high(result)
|
result = high(result)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
x.call.add newSymNode(s, n.info)
|
x.call.add newSymNode(s, n.info)
|
||||||
else:
|
else:
|
||||||
internalAssert false
|
internalAssert false
|
||||||
|
|
||||||
result = x.call
|
result = x.call
|
||||||
instGenericConvertersSons(c, result, x)
|
instGenericConvertersSons(c, result, x)
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
|
||||||
let L = forLoop.len
|
let L = forLoop.len
|
||||||
let call = forLoop.sons[L-2]
|
let call = forLoop.sons[L-2]
|
||||||
if call.len > 2:
|
if call.len > 2:
|
||||||
localError(forLoop.info, errGenerated,
|
localError(forLoop.info, errGenerated,
|
||||||
"parallel 'fields' iterator does not work for 'case' objects")
|
"parallel 'fields' iterator does not work for 'case' objects")
|
||||||
return
|
return
|
||||||
# iterate over the selector:
|
# iterate over the selector:
|
||||||
|
|
@ -106,7 +106,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
# a 'while true: stmt; break' loop ...
|
# a 'while true: stmt; break' loop ...
|
||||||
result = newNodeI(nkWhileStmt, n.info, 2)
|
result = newNodeI(nkWhileStmt, n.info, 2)
|
||||||
var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true")
|
var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true")
|
||||||
if trueSymbol == nil:
|
if trueSymbol == nil:
|
||||||
localError(n.info, errSystemNeeds, "true")
|
localError(n.info, errSystemNeeds, "true")
|
||||||
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
||||||
trueSymbol.typ = getSysType(tyBool)
|
trueSymbol.typ = getSysType(tyBool)
|
||||||
|
|
@ -114,13 +114,13 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
result.sons[0] = newSymNode(trueSymbol, n.info)
|
result.sons[0] = newSymNode(trueSymbol, n.info)
|
||||||
var stmts = newNodeI(nkStmtList, n.info)
|
var stmts = newNodeI(nkStmtList, n.info)
|
||||||
result.sons[1] = stmts
|
result.sons[1] = stmts
|
||||||
|
|
||||||
var length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
var call = n.sons[length-2]
|
var call = n.sons[length-2]
|
||||||
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
|
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
|
||||||
localError(n.info, errWrongNumberOfVariables)
|
localError(n.info, errWrongNumberOfVariables)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
|
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
|
||||||
if tupleTypeA.kind notin {tyTuple, tyObject}:
|
if tupleTypeA.kind notin {tyTuple, tyObject}:
|
||||||
localError(n.info, errGenerated, "no object or tuple type")
|
localError(n.info, errGenerated, "no object or tuple type")
|
||||||
|
|
@ -129,7 +129,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
|
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
|
||||||
if not sameType(tupleTypeA, tupleTypeB):
|
if not sameType(tupleTypeA, tupleTypeB):
|
||||||
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
|
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
|
||||||
|
|
||||||
inc(c.p.nestedLoopCounter)
|
inc(c.p.nestedLoopCounter)
|
||||||
if tupleTypeA.kind == tyTuple:
|
if tupleTypeA.kind == tyTuple:
|
||||||
var loopBody = n.sons[length-1]
|
var loopBody = n.sons[length-1]
|
||||||
|
|
|
||||||
|
|
@ -1327,7 +1327,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
# because in that case there is no point in continuing.
|
# because in that case there is no point in continuing.
|
||||||
var bothMetaCounter = 0
|
var bothMetaCounter = 0
|
||||||
var lastBindingsLength = -1
|
var lastBindingsLength = -1
|
||||||
while r == isBothMetaConvertible and
|
while r == isBothMetaConvertible and
|
||||||
lastBindingsLength != m.bindings.counter and
|
lastBindingsLength != m.bindings.counter and
|
||||||
bothMetaCounter < 100:
|
bothMetaCounter < 100:
|
||||||
lastBindingsLength = m.bindings.counter
|
lastBindingsLength = m.bindings.counter
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ var
|
||||||
|
|
||||||
template origModuleName(m: PSym): string = m.name.s
|
template origModuleName(m: PSym): string = m.name.s
|
||||||
|
|
||||||
proc symToSuggest(s: PSym, isLocal: bool, section: string, li: TLineInfo): Suggest =
|
proc symToSuggest(s: PSym, isLocal: bool, section: string, li: TLineInfo): Suggest =
|
||||||
result.section = parseIdeCmd(section)
|
result.section = parseIdeCmd(section)
|
||||||
if optIdeTerse in gGlobalOptions:
|
if optIdeTerse in gGlobalOptions:
|
||||||
result.symkind = s.kind
|
result.symkind = s.kind
|
||||||
|
|
@ -52,7 +52,7 @@ proc symToSuggest(s: PSym, isLocal: bool, section: string, li: TLineInfo): Sugge
|
||||||
result.qualifiedPath.add(ow.origModuleName)
|
result.qualifiedPath.add(ow.origModuleName)
|
||||||
result.qualifiedPath.add(s.name.s)
|
result.qualifiedPath.add(s.name.s)
|
||||||
|
|
||||||
if s.typ != nil:
|
if s.typ != nil:
|
||||||
result.forth = typeToString(s.typ)
|
result.forth = typeToString(s.typ)
|
||||||
else:
|
else:
|
||||||
result.forth = ""
|
result.forth = ""
|
||||||
|
|
@ -62,7 +62,7 @@ proc symToSuggest(s: PSym, isLocal: bool, section: string, li: TLineInfo): Sugge
|
||||||
when not defined(noDocgen):
|
when not defined(noDocgen):
|
||||||
result.doc = s.extractDocComment
|
result.doc = s.extractDocComment
|
||||||
|
|
||||||
proc `$`(suggest: Suggest): string =
|
proc `$`(suggest: Suggest): string =
|
||||||
result = $suggest.section
|
result = $suggest.section
|
||||||
result.add(sep)
|
result.add(sep)
|
||||||
result.add($suggest.symkind)
|
result.add($suggest.symkind)
|
||||||
|
|
@ -80,7 +80,7 @@ proc `$`(suggest: Suggest): string =
|
||||||
when not defined(noDocgen):
|
when not defined(noDocgen):
|
||||||
result.add(suggest.doc.escape)
|
result.add(suggest.doc.escape)
|
||||||
|
|
||||||
proc symToSuggest(s: PSym, isLocal: bool, section: string): Suggest =
|
proc symToSuggest(s: PSym, isLocal: bool, section: string): Suggest =
|
||||||
result = symToSuggest(s, isLocal, section, s.info)
|
result = symToSuggest(s, isLocal, section, s.info)
|
||||||
|
|
||||||
proc suggestResult(s: Suggest) =
|
proc suggestResult(s: Suggest) =
|
||||||
|
|
@ -104,7 +104,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
|
||||||
result = true
|
result = true
|
||||||
break
|
break
|
||||||
|
|
||||||
proc suggestField(c: PContext, s: PSym, outputs: var int) =
|
proc suggestField(c: PContext, s: PSym, outputs: var int) =
|
||||||
if filterSym(s) and fieldVisible(c, s):
|
if filterSym(s) and fieldVisible(c, s):
|
||||||
suggestResult(symToSuggest(s, isLocal=true, $ideSug))
|
suggestResult(symToSuggest(s, isLocal=true, $ideSug))
|
||||||
inc outputs
|
inc outputs
|
||||||
|
|
@ -122,17 +122,17 @@ template wholeSymTab(cond, section: expr) {.immediate.} =
|
||||||
suggestResult(symToSuggest(it, isLocal = isLocal, section))
|
suggestResult(symToSuggest(it, isLocal = isLocal, section))
|
||||||
inc outputs
|
inc outputs
|
||||||
|
|
||||||
proc suggestSymList(c: PContext, list: PNode, outputs: var int) =
|
proc suggestSymList(c: PContext, list: PNode, outputs: var int) =
|
||||||
for i in countup(0, sonsLen(list) - 1):
|
for i in countup(0, sonsLen(list) - 1):
|
||||||
if list.sons[i].kind == nkSym:
|
if list.sons[i].kind == nkSym:
|
||||||
suggestField(c, list.sons[i].sym, outputs)
|
suggestField(c, list.sons[i].sym, outputs)
|
||||||
#else: InternalError(list.info, "getSymFromList")
|
#else: InternalError(list.info, "getSymFromList")
|
||||||
|
|
||||||
proc suggestObject(c: PContext, n: PNode, outputs: var int) =
|
proc suggestObject(c: PContext, n: PNode, outputs: var int) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in countup(0, sonsLen(n)-1): suggestObject(c, n.sons[i], outputs)
|
for i in countup(0, sonsLen(n)-1): suggestObject(c, n.sons[i], outputs)
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
if L > 0:
|
if L > 0:
|
||||||
suggestObject(c, n.sons[0], outputs)
|
suggestObject(c, n.sons[0], outputs)
|
||||||
|
|
@ -140,7 +140,7 @@ proc suggestObject(c: PContext, n: PNode, outputs: var int) =
|
||||||
of nkSym: suggestField(c, n.sym, outputs)
|
of nkSym: suggestField(c, n.sym, outputs)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
||||||
var op = n.sons[0]
|
var op = n.sons[0]
|
||||||
if op.kind in {nkOpenSymChoice, nkClosedSymChoice}: op = op.sons[0]
|
if op.kind in {nkOpenSymChoice, nkClosedSymChoice}: op = op.sons[0]
|
||||||
var opr: PIdent
|
var opr: PIdent
|
||||||
|
|
@ -150,8 +150,8 @@ proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
||||||
else: return false
|
else: return false
|
||||||
result = opr.id == s.name.id
|
result = opr.id == s.name.id
|
||||||
|
|
||||||
proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
|
proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
|
||||||
case candidate.kind
|
case candidate.kind
|
||||||
of OverloadableSyms:
|
of OverloadableSyms:
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(c, m, candidate, nil)
|
initCandidate(c, m, candidate, nil)
|
||||||
|
|
@ -160,11 +160,11 @@ proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc suggestCall(c: PContext, n, nOrig: PNode, outputs: var int) =
|
proc suggestCall(c: PContext, n, nOrig: PNode, outputs: var int) =
|
||||||
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n, nOrig),
|
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n, nOrig),
|
||||||
$ideCon)
|
$ideCon)
|
||||||
|
|
||||||
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
|
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
|
||||||
if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil:
|
if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil:
|
||||||
# special rule: if system and some weird generic match via 'tyExpr'
|
# special rule: if system and some weird generic match via 'tyExpr'
|
||||||
# or 'tyGenericParam' we won't list it either to reduce the noise (nobody
|
# or 'tyGenericParam' we won't list it either to reduce the noise (nobody
|
||||||
|
|
@ -198,48 +198,48 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
|
||||||
var typ = n.typ
|
var typ = n.typ
|
||||||
if typ == nil:
|
if typ == nil:
|
||||||
# a module symbol has no type for example:
|
# a module symbol has no type for example:
|
||||||
if n.kind == nkSym and n.sym.kind == skModule:
|
if n.kind == nkSym and n.sym.kind == skModule:
|
||||||
if n.sym == c.module:
|
if n.sym == c.module:
|
||||||
# all symbols accessible, because we are in the current module:
|
# all symbols accessible, because we are in the current module:
|
||||||
for it in items(c.topLevelScope.symbols):
|
for it in items(c.topLevelScope.symbols):
|
||||||
if filterSym(it):
|
if filterSym(it):
|
||||||
suggestResult(symToSuggest(it, isLocal=false, $ideSug))
|
suggestResult(symToSuggest(it, isLocal=false, $ideSug))
|
||||||
inc outputs
|
inc outputs
|
||||||
else:
|
else:
|
||||||
for it in items(n.sym.tab):
|
for it in items(n.sym.tab):
|
||||||
if filterSym(it):
|
if filterSym(it):
|
||||||
suggestResult(symToSuggest(it, isLocal=false, $ideSug))
|
suggestResult(symToSuggest(it, isLocal=false, $ideSug))
|
||||||
inc outputs
|
inc outputs
|
||||||
else:
|
else:
|
||||||
# fallback:
|
# fallback:
|
||||||
suggestEverything(c, n, outputs)
|
suggestEverything(c, n, outputs)
|
||||||
elif typ.kind == tyEnum and n.kind == nkSym and n.sym.kind == skType:
|
elif typ.kind == tyEnum and n.kind == nkSym and n.sym.kind == skType:
|
||||||
# look up if the identifier belongs to the enum:
|
# look up if the identifier belongs to the enum:
|
||||||
var t = typ
|
var t = typ
|
||||||
while t != nil:
|
while t != nil:
|
||||||
suggestSymList(c, t.n, outputs)
|
suggestSymList(c, t.n, outputs)
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
suggestOperations(c, n, typ, outputs)
|
suggestOperations(c, n, typ, outputs)
|
||||||
else:
|
else:
|
||||||
typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||||
if typ.kind == tyObject:
|
if typ.kind == tyObject:
|
||||||
var t = typ
|
var t = typ
|
||||||
while true:
|
while true:
|
||||||
suggestObject(c, t.n, outputs)
|
suggestObject(c, t.n, outputs)
|
||||||
if t.sons[0] == nil: break
|
if t.sons[0] == nil: break
|
||||||
t = skipTypes(t.sons[0], {tyGenericInst})
|
t = skipTypes(t.sons[0], {tyGenericInst})
|
||||||
suggestOperations(c, n, typ, outputs)
|
suggestOperations(c, n, typ, outputs)
|
||||||
elif typ.kind == tyTuple and typ.n != nil:
|
elif typ.kind == tyTuple and typ.n != nil:
|
||||||
suggestSymList(c, typ.n, outputs)
|
suggestSymList(c, typ.n, outputs)
|
||||||
suggestOperations(c, n, typ, outputs)
|
suggestOperations(c, n, typ, outputs)
|
||||||
else:
|
else:
|
||||||
suggestOperations(c, n, typ, outputs)
|
suggestOperations(c, n, typ, outputs)
|
||||||
|
|
||||||
type
|
type
|
||||||
TCheckPointResult = enum
|
TCheckPointResult = enum
|
||||||
cpNone, cpFuzzy, cpExact
|
cpNone, cpFuzzy, cpExact
|
||||||
|
|
||||||
proc inCheckpoint(current: TLineInfo): TCheckPointResult =
|
proc inCheckpoint(current: TLineInfo): TCheckPointResult =
|
||||||
if current.fileIndex == gTrackPos.fileIndex:
|
if current.fileIndex == gTrackPos.fileIndex:
|
||||||
if current.line == gTrackPos.line and
|
if current.line == gTrackPos.line and
|
||||||
abs(current.col-gTrackPos.col) < 4:
|
abs(current.col-gTrackPos.col) < 4:
|
||||||
|
|
@ -255,8 +255,8 @@ proc findClosestDot(n: PNode): PNode =
|
||||||
result = findClosestDot(n.sons[i])
|
result = findClosestDot(n.sons[i])
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
|
|
||||||
proc findClosestCall(n: PNode): PNode =
|
proc findClosestCall(n: PNode): PNode =
|
||||||
if n.kind in nkCallKinds and inCheckpoint(n.info) == cpExact:
|
if n.kind in nkCallKinds and inCheckpoint(n.info) == cpExact:
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
for i in 0.. <safeLen(n):
|
for i in 0.. <safeLen(n):
|
||||||
|
|
@ -270,8 +270,8 @@ proc isTracked(current: TLineInfo, tokenLen: int): bool =
|
||||||
if col >= current.col and col <= current.col+tokenLen-1:
|
if col >= current.col and col <= current.col+tokenLen-1:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc findClosestSym(n: PNode): PNode =
|
proc findClosestSym(n: PNode): PNode =
|
||||||
if n.kind == nkSym and inCheckpoint(n.info) == cpExact:
|
if n.kind == nkSym and inCheckpoint(n.info) == cpExact:
|
||||||
result = n
|
result = n
|
||||||
elif n.kind notin {nkNone..nkNilLit}:
|
elif n.kind notin {nkNone..nkNilLit}:
|
||||||
for i in 0.. <sonsLen(n):
|
for i in 0.. <sonsLen(n):
|
||||||
|
|
@ -328,7 +328,7 @@ proc safeSemExpr*(c: PContext, n: PNode): PNode =
|
||||||
except ERecoverableError:
|
except ERecoverableError:
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc suggestExpr*(c: PContext, node: PNode) =
|
proc suggestExpr*(c: PContext, node: PNode) =
|
||||||
if nfIsCursor notin node.flags:
|
if nfIsCursor notin node.flags:
|
||||||
if gTrackPos.line < 0: return
|
if gTrackPos.line < 0: return
|
||||||
var cp = inCheckpoint(node.info)
|
var cp = inCheckpoint(node.info)
|
||||||
|
|
@ -349,7 +349,7 @@ proc suggestExpr*(c: PContext, node: PNode) =
|
||||||
#writeStackTrace()
|
#writeStackTrace()
|
||||||
else:
|
else:
|
||||||
suggestEverything(c, n, outputs)
|
suggestEverything(c, n, outputs)
|
||||||
|
|
||||||
elif gIdeCmd == ideCon:
|
elif gIdeCmd == ideCon:
|
||||||
var n = if nfIsCursor in node.flags: node else: findClosestCall(node)
|
var n = if nfIsCursor in node.flags: node else: findClosestCall(node)
|
||||||
if n == nil: n = node
|
if n == nil: n = node
|
||||||
|
|
@ -364,9 +364,9 @@ proc suggestExpr*(c: PContext, node: PNode) =
|
||||||
if x.kind == nkEmpty or x.typ == nil: break
|
if x.kind == nkEmpty or x.typ == nil: break
|
||||||
addSon(a, x)
|
addSon(a, x)
|
||||||
suggestCall(c, a, n, outputs)
|
suggestCall(c, a, n, outputs)
|
||||||
|
|
||||||
dec(c.inCompilesContext)
|
dec(c.inCompilesContext)
|
||||||
if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
|
if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
|
||||||
|
|
||||||
proc suggestStmt*(c: PContext, n: PNode) =
|
proc suggestStmt*(c: PContext, n: PNode) =
|
||||||
suggestExpr(c, n)
|
suggestExpr(c, n)
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,24 @@
|
||||||
|
|
||||||
## Implements the dispatcher for the different parsers.
|
## Implements the dispatcher for the different parsers.
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
|
strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
|
||||||
pbraces, filters, filter_tmpl, renderer
|
pbraces, filters, filter_tmpl, renderer
|
||||||
|
|
||||||
type
|
type
|
||||||
TFilterKind* = enum
|
TFilterKind* = enum
|
||||||
filtNone, filtTemplate, filtReplace, filtStrip
|
filtNone, filtTemplate, filtReplace, filtStrip
|
||||||
TParserKind* = enum
|
TParserKind* = enum
|
||||||
skinStandard, skinStrongSpaces, skinBraces, skinEndX
|
skinStandard, skinStrongSpaces, skinBraces, skinEndX
|
||||||
|
|
||||||
const
|
const
|
||||||
parserNames*: array[TParserKind, string] = ["standard", "strongspaces",
|
parserNames*: array[TParserKind, string] = ["standard", "strongspaces",
|
||||||
"braces", "endx"]
|
"braces", "endx"]
|
||||||
filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
|
filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
|
||||||
"strip"]
|
"strip"]
|
||||||
|
|
||||||
type
|
type
|
||||||
TParsers*{.final.} = object
|
TParsers*{.final.} = object
|
||||||
skin*: TParserKind
|
skin*: TParserKind
|
||||||
parser*: TParser
|
parser*: TParser
|
||||||
|
|
||||||
|
|
@ -42,53 +42,53 @@ proc parseTopLevelStmt*(p: var TParsers): PNode
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc parseFile(fileIdx: int32): PNode =
|
proc parseFile(fileIdx: int32): PNode =
|
||||||
var
|
var
|
||||||
p: TParsers
|
p: TParsers
|
||||||
f: File
|
f: File
|
||||||
let filename = fileIdx.toFullPathConsiderDirty
|
let filename = fileIdx.toFullPathConsiderDirty
|
||||||
if not open(f, filename):
|
if not open(f, filename):
|
||||||
rawMessage(errCannotOpenFile, filename)
|
rawMessage(errCannotOpenFile, filename)
|
||||||
return
|
return
|
||||||
openParsers(p, fileIdx, llStreamOpen(f))
|
openParsers(p, fileIdx, llStreamOpen(f))
|
||||||
result = parseAll(p)
|
result = parseAll(p)
|
||||||
closeParsers(p)
|
closeParsers(p)
|
||||||
|
|
||||||
proc parseAll(p: var TParsers): PNode =
|
proc parseAll(p: var TParsers): PNode =
|
||||||
case p.skin
|
case p.skin
|
||||||
of skinStandard, skinStrongSpaces:
|
of skinStandard, skinStrongSpaces:
|
||||||
result = parser.parseAll(p.parser)
|
result = parser.parseAll(p.parser)
|
||||||
of skinBraces:
|
of skinBraces:
|
||||||
result = pbraces.parseAll(p.parser)
|
result = pbraces.parseAll(p.parser)
|
||||||
of skinEndX:
|
of skinEndX:
|
||||||
internalError("parser to implement")
|
internalError("parser to implement")
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc parseTopLevelStmt(p: var TParsers): PNode =
|
proc parseTopLevelStmt(p: var TParsers): PNode =
|
||||||
case p.skin
|
case p.skin
|
||||||
of skinStandard, skinStrongSpaces:
|
of skinStandard, skinStrongSpaces:
|
||||||
result = parser.parseTopLevelStmt(p.parser)
|
result = parser.parseTopLevelStmt(p.parser)
|
||||||
of skinBraces:
|
of skinBraces:
|
||||||
result = pbraces.parseTopLevelStmt(p.parser)
|
result = pbraces.parseTopLevelStmt(p.parser)
|
||||||
of skinEndX:
|
of skinEndX:
|
||||||
internalError("parser to implement")
|
internalError("parser to implement")
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc utf8Bom(s: string): int =
|
proc utf8Bom(s: string): int =
|
||||||
if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'):
|
if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'):
|
||||||
result = 3
|
result = 3
|
||||||
else:
|
else:
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
proc containsShebang(s: string, i: int): bool =
|
proc containsShebang(s: string, i: int): bool =
|
||||||
if (s[i] == '#') and (s[i + 1] == '!'):
|
if (s[i] == '#') and (s[i + 1] == '!'):
|
||||||
var j = i + 2
|
var j = i + 2
|
||||||
while s[j] in Whitespace: inc(j)
|
while s[j] in Whitespace: inc(j)
|
||||||
result = s[j] == '/'
|
result = s[j] == '/'
|
||||||
|
|
||||||
proc parsePipe(filename: string, inputStream: PLLStream): PNode =
|
proc parsePipe(filename: string, inputStream: PLLStream): PNode =
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
var s = llStreamOpen(filename, fmRead)
|
var s = llStreamOpen(filename, fmRead)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
var line = newStringOfCap(80)
|
var line = newStringOfCap(80)
|
||||||
discard llStreamReadLine(s, line)
|
discard llStreamReadLine(s, line)
|
||||||
var i = utf8Bom(line)
|
var i = utf8Bom(line)
|
||||||
|
|
@ -104,50 +104,50 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode =
|
||||||
closeParser(q)
|
closeParser(q)
|
||||||
llStreamClose(s)
|
llStreamClose(s)
|
||||||
|
|
||||||
proc getFilter(ident: PIdent): TFilterKind =
|
proc getFilter(ident: PIdent): TFilterKind =
|
||||||
for i in countup(low(TFilterKind), high(TFilterKind)):
|
for i in countup(low(TFilterKind), high(TFilterKind)):
|
||||||
if identEq(ident, filterNames[i]):
|
if identEq(ident, filterNames[i]):
|
||||||
return i
|
return i
|
||||||
result = filtNone
|
result = filtNone
|
||||||
|
|
||||||
proc getParser(ident: PIdent): TParserKind =
|
proc getParser(ident: PIdent): TParserKind =
|
||||||
for i in countup(low(TParserKind), high(TParserKind)):
|
for i in countup(low(TParserKind), high(TParserKind)):
|
||||||
if identEq(ident, parserNames[i]):
|
if identEq(ident, parserNames[i]):
|
||||||
return i
|
return i
|
||||||
rawMessage(errInvalidDirectiveX, ident.s)
|
rawMessage(errInvalidDirectiveX, ident.s)
|
||||||
|
|
||||||
proc getCallee(n: PNode): PIdent =
|
proc getCallee(n: PNode): PIdent =
|
||||||
if n.kind in nkCallKinds and n.sons[0].kind == nkIdent:
|
if n.kind in nkCallKinds and n.sons[0].kind == nkIdent:
|
||||||
result = n.sons[0].ident
|
result = n.sons[0].ident
|
||||||
elif n.kind == nkIdent:
|
elif n.kind == nkIdent:
|
||||||
result = n.ident
|
result = n.ident
|
||||||
else:
|
else:
|
||||||
rawMessage(errXNotAllowedHere, renderTree(n))
|
rawMessage(errXNotAllowedHere, renderTree(n))
|
||||||
|
|
||||||
proc applyFilter(p: var TParsers, n: PNode, filename: string,
|
proc applyFilter(p: var TParsers, n: PNode, filename: string,
|
||||||
stdin: PLLStream): PLLStream =
|
stdin: PLLStream): PLLStream =
|
||||||
var ident = getCallee(n)
|
var ident = getCallee(n)
|
||||||
var f = getFilter(ident)
|
var f = getFilter(ident)
|
||||||
case f
|
case f
|
||||||
of filtNone:
|
of filtNone:
|
||||||
p.skin = getParser(ident)
|
p.skin = getParser(ident)
|
||||||
result = stdin
|
result = stdin
|
||||||
of filtTemplate:
|
of filtTemplate:
|
||||||
result = filterTmpl(stdin, filename, n)
|
result = filterTmpl(stdin, filename, n)
|
||||||
of filtStrip:
|
of filtStrip:
|
||||||
result = filterStrip(stdin, filename, n)
|
result = filterStrip(stdin, filename, n)
|
||||||
of filtReplace:
|
of filtReplace:
|
||||||
result = filterReplace(stdin, filename, n)
|
result = filterReplace(stdin, filename, n)
|
||||||
if f != filtNone:
|
if f != filtNone:
|
||||||
if hintCodeBegin in gNotes:
|
if hintCodeBegin in gNotes:
|
||||||
rawMessage(hintCodeBegin, [])
|
rawMessage(hintCodeBegin, [])
|
||||||
msgWriteln(result.s)
|
msgWriteln(result.s)
|
||||||
rawMessage(hintCodeEnd, [])
|
rawMessage(hintCodeEnd, [])
|
||||||
|
|
||||||
proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||||
start: PLLStream): PLLStream =
|
start: PLLStream): PLLStream =
|
||||||
result = start
|
result = start
|
||||||
if n.kind == nkEmpty: return
|
if n.kind == nkEmpty: return
|
||||||
if n.kind == nkInfix and n.sons[0].kind == nkIdent and
|
if n.kind == nkInfix and n.sons[0].kind == nkIdent and
|
||||||
identEq(n.sons[0].ident, "|"):
|
identEq(n.sons[0].ident, "|"):
|
||||||
for i in countup(1, 2):
|
for i in countup(1, 2):
|
||||||
|
|
@ -159,8 +159,8 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||||
result = evalPipe(p, n.sons[0], filename, result)
|
result = evalPipe(p, n.sons[0], filename, result)
|
||||||
else:
|
else:
|
||||||
result = applyFilter(p, n, filename, result)
|
result = applyFilter(p, n, filename, result)
|
||||||
|
|
||||||
proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
||||||
var s: PLLStream
|
var s: PLLStream
|
||||||
p.skin = skinStandard
|
p.skin = skinStandard
|
||||||
let filename = fileIdx.toFullPathConsiderDirty
|
let filename = fileIdx.toFullPathConsiderDirty
|
||||||
|
|
@ -172,6 +172,6 @@ proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
||||||
parser.openParser(p.parser, fileIdx, s, false)
|
parser.openParser(p.parser, fileIdx, s, false)
|
||||||
of skinStrongSpaces:
|
of skinStrongSpaces:
|
||||||
parser.openParser(p.parser, fileIdx, s, true)
|
parser.openParser(p.parser, fileIdx, s, true)
|
||||||
|
|
||||||
proc closeParsers(p: var TParsers) =
|
proc closeParsers(p: var TParsers) =
|
||||||
parser.closeParser(p.parser)
|
parser.closeParser(p.parser)
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ import
|
||||||
|
|
||||||
{.compile: "../tinyc/libtcc.c".}
|
{.compile: "../tinyc/libtcc.c".}
|
||||||
|
|
||||||
proc tinyCErrorHandler(closure: pointer, msg: cstring) {.cdecl.} =
|
proc tinyCErrorHandler(closure: pointer, msg: cstring) {.cdecl.} =
|
||||||
rawMessage(errGenerated, $msg)
|
rawMessage(errGenerated, $msg)
|
||||||
|
|
||||||
proc initTinyCState: PccState =
|
proc initTinyCState: PccState =
|
||||||
result = openCCState()
|
result = openCCState()
|
||||||
setErrorFunc(result, nil, tinyCErrorHandler)
|
setErrorFunc(result, nil, tinyCErrorHandler)
|
||||||
|
|
||||||
|
|
@ -23,25 +23,25 @@ var
|
||||||
gTinyC = initTinyCState()
|
gTinyC = initTinyCState()
|
||||||
libIncluded = false
|
libIncluded = false
|
||||||
|
|
||||||
proc addFile(filename: string) =
|
proc addFile(filename: string) =
|
||||||
if addFile(gTinyC, filename) != 0'i32:
|
if addFile(gTinyC, filename) != 0'i32:
|
||||||
rawMessage(errCannotOpenFile, filename)
|
rawMessage(errCannotOpenFile, filename)
|
||||||
|
|
||||||
proc setupEnvironment =
|
proc setupEnvironment =
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
defineSymbol(gTinyC, "__x86_64__", nil)
|
defineSymbol(gTinyC, "__x86_64__", nil)
|
||||||
elif defined(i386):
|
elif defined(i386):
|
||||||
defineSymbol(gTinyC, "__i386__", nil)
|
defineSymbol(gTinyC, "__i386__", nil)
|
||||||
when defined(linux):
|
when defined(linux):
|
||||||
defineSymbol(gTinyC, "__linux__", nil)
|
defineSymbol(gTinyC, "__linux__", nil)
|
||||||
defineSymbol(gTinyC, "__linux", nil)
|
defineSymbol(gTinyC, "__linux", nil)
|
||||||
var nimrodDir = getPrefixDir()
|
var nimrodDir = getPrefixDir()
|
||||||
|
|
||||||
addIncludePath(gTinyC, libpath)
|
addIncludePath(gTinyC, libpath)
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
addSysincludePath(gTinyC, nimrodDir / "tinyc/win32/include")
|
addSysincludePath(gTinyC, nimrodDir / "tinyc/win32/include")
|
||||||
addSysincludePath(gTinyC, nimrodDir / "tinyc/include")
|
addSysincludePath(gTinyC, nimrodDir / "tinyc/include")
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
defineSymbol(gTinyC, "_WIN32", nil)
|
defineSymbol(gTinyC, "_WIN32", nil)
|
||||||
# we need Mingw's headers too:
|
# we need Mingw's headers too:
|
||||||
var gccbin = getConfigVar("gcc.path") % ["nimrod", nimrodDir]
|
var gccbin = getConfigVar("gcc.path") % ["nimrod", nimrodDir]
|
||||||
|
|
@ -54,7 +54,7 @@ proc setupEnvironment =
|
||||||
#addFile(nimrodDir / r"tinyc\win32\dllcrt1.o")
|
#addFile(nimrodDir / r"tinyc\win32\dllcrt1.o")
|
||||||
#addFile(nimrodDir / r"tinyc\win32\dllmain.o")
|
#addFile(nimrodDir / r"tinyc\win32\dllmain.o")
|
||||||
addFile(nimrodDir / r"tinyc\win32\libtcc1.o")
|
addFile(nimrodDir / r"tinyc\win32\libtcc1.o")
|
||||||
|
|
||||||
#addFile(nimrodDir / r"tinyc\win32\lib\crt1.c")
|
#addFile(nimrodDir / r"tinyc\win32\lib\crt1.c")
|
||||||
#addFile(nimrodDir / r"tinyc\lib\libtcc1.c")
|
#addFile(nimrodDir / r"tinyc\lib\libtcc1.c")
|
||||||
else:
|
else:
|
||||||
|
|
@ -62,12 +62,12 @@ proc setupEnvironment =
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
addSysincludePath(gTinyC, "/usr/include/x86_64-linux-gnu")
|
addSysincludePath(gTinyC, "/usr/include/x86_64-linux-gnu")
|
||||||
|
|
||||||
proc compileCCode*(ccode: string) =
|
proc compileCCode*(ccode: string) =
|
||||||
if not libIncluded:
|
if not libIncluded:
|
||||||
libIncluded = true
|
libIncluded = true
|
||||||
setupEnvironment()
|
setupEnvironment()
|
||||||
discard compileString(gTinyC, ccode)
|
discard compileString(gTinyC, ccode)
|
||||||
|
|
||||||
proc run*(args: string) =
|
proc run*(args: string) =
|
||||||
var s = @[cstring(gProjectName)] & map(split(args), proc(x: string): cstring = cstring(x))
|
var s = @[cstring(gProjectName)] & map(split(args), proc(x: string): cstring = cstring(x))
|
||||||
var err = tinyc.run(gTinyC, cint(len(s)), cast[cstringArray](addr(s[0]))) != 0'i32
|
var err = tinyc.run(gTinyC, cint(len(s)), cast[cstringArray](addr(s[0]))) != 0'i32
|
||||||
|
|
|
||||||
|
|
@ -9,36 +9,36 @@
|
||||||
|
|
||||||
# Implements a table from trees to trees. Does structural equivalence checking.
|
# Implements a table from trees to trees. Does structural equivalence checking.
|
||||||
|
|
||||||
import
|
import
|
||||||
hashes, ast, astalgo, types
|
hashes, ast, astalgo, types
|
||||||
|
|
||||||
proc hashTree(n: PNode): Hash =
|
proc hashTree(n: PNode): Hash =
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
result = ord(n.kind)
|
result = ord(n.kind)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty, nkNilLit, nkType:
|
of nkEmpty, nkNilLit, nkType:
|
||||||
discard
|
discard
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
result = result !& n.ident.h
|
result = result !& n.ident.h
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result = result !& n.sym.name.h
|
result = result !& n.sym.name.h
|
||||||
of nkCharLit..nkUInt64Lit:
|
of nkCharLit..nkUInt64Lit:
|
||||||
if (n.intVal >= low(int)) and (n.intVal <= high(int)):
|
if (n.intVal >= low(int)) and (n.intVal <= high(int)):
|
||||||
result = result !& int(n.intVal)
|
result = result !& int(n.intVal)
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat64Lit:
|
||||||
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
|
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
|
||||||
result = result !& toInt(n.floatVal)
|
result = result !& toInt(n.floatVal)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if not n.strVal.isNil:
|
if not n.strVal.isNil:
|
||||||
result = result !& hash(n.strVal)
|
result = result !& hash(n.strVal)
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result = result !& hashTree(n.sons[i])
|
result = result !& hashTree(n.sons[i])
|
||||||
|
|
||||||
proc treesEquivalent(a, b: PNode): bool =
|
proc treesEquivalent(a, b: PNode): bool =
|
||||||
if a == b:
|
if a == b:
|
||||||
result = true
|
result = true
|
||||||
elif (a != nil) and (b != nil) and (a.kind == b.kind):
|
elif (a != nil) and (b != nil) and (a.kind == b.kind):
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkEmpty, nkNilLit, nkType: result = true
|
of nkEmpty, nkNilLit, nkType: result = true
|
||||||
of nkSym: result = a.sym.id == b.sym.id
|
of nkSym: result = a.sym.id == b.sym.id
|
||||||
|
|
@ -46,28 +46,28 @@ proc treesEquivalent(a, b: PNode): bool =
|
||||||
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
|
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
|
||||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||||
else:
|
else:
|
||||||
if sonsLen(a) == sonsLen(b):
|
if sonsLen(a) == sonsLen(b):
|
||||||
for i in countup(0, sonsLen(a) - 1):
|
for i in countup(0, sonsLen(a) - 1):
|
||||||
if not treesEquivalent(a.sons[i], b.sons[i]): return
|
if not treesEquivalent(a.sons[i], b.sons[i]): return
|
||||||
result = true
|
result = true
|
||||||
if result: result = sameTypeOrNil(a.typ, b.typ)
|
if result: result = sameTypeOrNil(a.typ, b.typ)
|
||||||
|
|
||||||
proc nodeTableRawGet(t: TNodeTable, k: Hash, key: PNode): int =
|
proc nodeTableRawGet(t: TNodeTable, k: Hash, key: PNode): int =
|
||||||
var h: Hash = k and high(t.data)
|
var h: Hash = k and high(t.data)
|
||||||
while t.data[h].key != nil:
|
while t.data[h].key != nil:
|
||||||
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key):
|
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key):
|
||||||
return h
|
return h
|
||||||
h = nextTry(h, high(t.data))
|
h = nextTry(h, high(t.data))
|
||||||
result = -1
|
result = -1
|
||||||
|
|
||||||
proc nodeTableGet*(t: TNodeTable, key: PNode): int =
|
proc nodeTableGet*(t: TNodeTable, key: PNode): int =
|
||||||
var index = nodeTableRawGet(t, hashTree(key), key)
|
var index = nodeTableRawGet(t, hashTree(key), key)
|
||||||
if index >= 0: result = t.data[index].val
|
if index >= 0: result = t.data[index].val
|
||||||
else: result = low(int)
|
else: result = low(int)
|
||||||
|
|
||||||
proc nodeTableRawInsert(data: var TNodePairSeq, k: Hash, key: PNode,
|
proc nodeTableRawInsert(data: var TNodePairSeq, k: Hash, key: PNode,
|
||||||
val: int) =
|
val: int) =
|
||||||
var h: Hash = k and high(data)
|
var h: Hash = k and high(data)
|
||||||
while data[h].key != nil: h = nextTry(h, high(data))
|
while data[h].key != nil: h = nextTry(h, high(data))
|
||||||
assert(data[h].key == nil)
|
assert(data[h].key == nil)
|
||||||
|
|
@ -75,35 +75,35 @@ proc nodeTableRawInsert(data: var TNodePairSeq, k: Hash, key: PNode,
|
||||||
data[h].key = key
|
data[h].key = key
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
|
|
||||||
proc nodeTablePut*(t: var TNodeTable, key: PNode, val: int) =
|
proc nodeTablePut*(t: var TNodeTable, key: PNode, val: int) =
|
||||||
var n: TNodePairSeq
|
var n: TNodePairSeq
|
||||||
var k: Hash = hashTree(key)
|
var k: Hash = hashTree(key)
|
||||||
var index = nodeTableRawGet(t, k, key)
|
var index = nodeTableRawGet(t, k, key)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
assert(t.data[index].key != nil)
|
assert(t.data[index].key != nil)
|
||||||
t.data[index].val = val
|
t.data[index].val = val
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(t.data), t.counter):
|
if mustRehash(len(t.data), t.counter):
|
||||||
newSeq(n, len(t.data) * GrowthFactor)
|
newSeq(n, len(t.data) * GrowthFactor)
|
||||||
for i in countup(0, high(t.data)):
|
for i in countup(0, high(t.data)):
|
||||||
if t.data[i].key != nil:
|
if t.data[i].key != nil:
|
||||||
nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
|
nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
|
||||||
swap(t.data, n)
|
swap(t.data, n)
|
||||||
nodeTableRawInsert(t.data, k, key, val)
|
nodeTableRawInsert(t.data, k, key, val)
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc nodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int =
|
proc nodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int =
|
||||||
var n: TNodePairSeq
|
var n: TNodePairSeq
|
||||||
var k: Hash = hashTree(key)
|
var k: Hash = hashTree(key)
|
||||||
var index = nodeTableRawGet(t, k, key)
|
var index = nodeTableRawGet(t, k, key)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
assert(t.data[index].key != nil)
|
assert(t.data[index].key != nil)
|
||||||
result = t.data[index].val
|
result = t.data[index].val
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(t.data), t.counter):
|
if mustRehash(len(t.data), t.counter):
|
||||||
newSeq(n, len(t.data) * GrowthFactor)
|
newSeq(n, len(t.data) * GrowthFactor)
|
||||||
for i in countup(0, high(t.data)):
|
for i in countup(0, high(t.data)):
|
||||||
if t.data[i].key != nil:
|
if t.data[i].key != nil:
|
||||||
nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
|
nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
|
||||||
swap(t.data, n)
|
swap(t.data, n)
|
||||||
nodeTableRawInsert(t.data, k, key, val)
|
nodeTableRawInsert(t.data, k, key, val)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue