compiler: Trim .nim files trailing whitespace

via OSX: find . -name '*.nim' -exec sed -i '' -E 's/[[:space:]]+$//' {} +
This commit is contained in:
Adam Strzelecki 2015-09-04 23:02:43 +02:00
commit d681812465
32 changed files with 570 additions and 570 deletions

View file

@ -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)

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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]

View file

@ -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("")

View file

@ -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, "")

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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) =

View file

@ -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")

View file

@ -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)

View file

@ -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!

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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 =

View file

@ -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

View file

@ -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:

View file

@ -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)

View file

@ -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]

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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)