Skip to content

Commit

Permalink
Merge branch 'devel' into auto-backwards-index
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq authored Feb 28, 2018
2 parents 784ad2e + 51935c4 commit 7044343
Show file tree
Hide file tree
Showing 18 changed files with 755 additions and 269 deletions.
751 changes: 574 additions & 177 deletions changelog.md

Large diffs are not rendered by default.

32 changes: 17 additions & 15 deletions compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -549,15 +549,13 @@ proc pragmaLine(c: PContext, n: PNode) =
n.info = getInfoContext(-1)

proc processPragma(c: PContext, n: PNode, i: int) =
var it = n.sons[i]
let it = n[i]
if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(n)
elif it.sons[0].kind != nkIdent: invalidPragma(n)
elif it.sons[1].kind != nkIdent: invalidPragma(n)
elif it[0].kind != nkIdent: invalidPragma(n)
elif it[1].kind != nkIdent: invalidPragma(n)

var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info)
var body = newNodeI(nkPragma, n.info)
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
userPragma.ast = body
var userPragma = newSym(skTemplate, it[1].ident, nil, it.info)
userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1])
strTableAdd(c.userPragmas, userPragma)

proc pragmaRaisesOrTags(c: PContext, n: PNode) =
Expand Down Expand Up @@ -678,7 +676,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
elif n.kind == nkExprColonExpr:
result.kind = n.kind # pragma(arg) -> pragma: arg

proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords): bool =
var it = n.sons[i]
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it.sons[0] else: it
Expand All @@ -691,13 +689,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
let ident = considerQuotedIdent(key)
var userPragma = strTableGet(c.userPragmas, ident)
if userPragma != nil:
# number of pragmas increase/decrease with user pragma expansion
inc c.instCounter
if c.instCounter > 100:
globalError(it.info, errRecursiveDependencyX, userPragma.name.s)

pragma(c, sym, userPragma.ast, validPragmas)
# ensure the pragma is also remember for generic instantiations in other
# modules:
n.sons[i] = userPragma.ast
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
dec c.instCounter
else:
var k = whichKeyword(ident)
Expand Down Expand Up @@ -1032,9 +1031,11 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
let o = it.otherPragmas
if not o.isNil:
pushInfoContext(n.info)
for i in countup(0, sonsLen(o) - 1):
var i = 0
while i < o.len():
if singlePragma(c, sym, o, i, validPragmas):
internalError(n.info, "implicitPragmas")
inc i
popInfoContext()

if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
Expand All @@ -1059,9 +1060,10 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =

proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
if n == nil: return
for i in countup(0, sonsLen(n) - 1):
if n.sons[i].kind == nkPragma: pragmaRec(c, sym, n.sons[i], validPragmas)
elif singlePragma(c, sym, n, i, validPragmas): break
var i = 0
while i < n.len():
if singlePragma(c, sym, n, i, validPragmas): break
inc i

proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
if n == nil: return
Expand Down
2 changes: 2 additions & 0 deletions compiler/rod.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ when not defined(nimSymbolfiles):

template addModuleDep*(module, fileIdx: int32; isIncludeFile: bool) = discard

template storeRemaining*(module: PSym) = discard

else:
include rodimpl

Expand Down
41 changes: 26 additions & 15 deletions compiler/rodimpl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import strutils, os, intsets, tables, ropes, db_sqlite, msgs, options, types,
## Todo:
## - Implement the 'import' replay logic so that the codegen runs over
## dependent modules.
## - Make conditional symbols and the configuration part of a module's
## dependencies.
## - Test multi methods.
## - Implement the limited VM support based on sets.
## - Depencency computation should use signature hashes in order to
Expand Down Expand Up @@ -49,7 +51,7 @@ proc getModuleId*(fileIdx: int32; fullpath: string): int =
if gSymbolFiles != v2Sf: return getID()
let module = db.getRow(
sql"select id, fullHash from modules where fullpath = ?", fullpath)
let currentFullhash = $secureHashFile(fullpath)
let currentFullhash = hashFileCached(fileIdx, fullpath)
if module[0].len == 0:
result = int db.insertID(sql"insert into modules(fullpath, interfHash, fullHash) values (?, ?, ?)",
fullpath, "", currentFullhash)
Expand All @@ -75,12 +77,13 @@ type
sstack: seq[PSym] # a stack of symbols to process
tstack: seq[PType] # a stack of types to process
tmarks, smarks: IntSet
forwardedSyms: seq[PSym]

PRodWriter = var TRodWriter

proc initRodWriter(module: PSym): TRodWriter =
result = TRodWriter(module: module, sstack: @[], tstack: @[],
tmarks: initIntSet(), smarks: initIntSet())
tmarks: initIntSet(), smarks: initIntSet(), forwardedSyms: @[])

when false:
proc getDefines(): string =
Expand All @@ -89,13 +92,6 @@ when false:
if result.len != 0: add(result, " ")
add(result, d)

proc addInclDep(w: PRodWriter, dep: string; info: TLineInfo) =
let resolved = dep.findModule(info.toFullPath)
encodeVInt(fileIdx(w, resolved), w.inclDeps)
add(w.inclDeps, " ")
encodeStr($secureHashFile(resolved), w.inclDeps)
add(w.inclDeps, rodNL)

const
rodNL = "\L"

Expand Down Expand Up @@ -381,6 +377,9 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
encodeNode(w, s.info, s.ast, result)

proc storeSym(w: PRodWriter; s: PSym) =
if sfForward in s.flags and s.kind != skModule:
w.forwardedSyms.add s
return
var buf = newStringOfCap(160)
encodeSym(w, s, buf)
# XXX only store the name for exported symbols in order to speed up lookup
Expand All @@ -401,8 +400,9 @@ proc storeNode*(module: PSym; n: PNode) =
w.module = module
var buf = newStringOfCap(160)
encodeNode(w, module.info, n, buf)
db.exec(sql"insert into toplevelstmts(module, data) values (?, ?)",
abs(module.id), buf)
db.exec(sql"insert into toplevelstmts(module, position, data) values (?, ?, ?)",
abs(module.id), module.offset, buf)
inc module.offset
var i = 0
while true:
if i > 10_000:
Expand All @@ -421,6 +421,14 @@ proc storeNode*(module: PSym; n: PNode) =
break
inc i

proc storeRemaining*(module: PSym) =
if gSymbolFiles != v2Sf: return
w.module = module
for s in w.forwardedSyms:
assert sfForward notin s.flags
storeSym(w, s)
w.forwardedSyms.setLen 0

# ---------------- decoder -----------------------------------
type
TRodReader = object
Expand Down Expand Up @@ -781,6 +789,7 @@ proc loadSymFromBlob(r; b; info: TLineInfo): PSym =
result.ast = decodeNode(r, b, result.info)
if sfCompilerProc in result.flags:
registerCompilerProc(result)
#echo "loading ", result.name.s

proc loadSym(r; id: int; info: TLineInfo): PSym =
result = r.syms.getOrDefault(id)
Expand All @@ -804,14 +813,14 @@ proc loadModuleSymTab(r; module: PSym) =
if sfSystemModule in module.flags:
magicsys.systemModule = module

proc loadNode*(module: PSym; index: var int): PNode =
proc loadNode*(module: PSym; index: int): PNode =
assert gSymbolFiles == v2Sf
if index == 0:
loadModuleSymTab(gr, module)
index = parseInt db.getValue(
sql"select min(id) from toplevelstmts where module = ?", abs module.id)
#index = parseInt db.getValue(
# sql"select min(id) from toplevelstmts where module = ?", abs module.id)
var b = BlobReader(pos: 0)
b.s = db.getValue(sql"select data from toplevelstmts where id = ? and module = ?",
b.s = db.getValue(sql"select data from toplevelstmts where position = ? and module = ?",
index, abs module.id)
if b.s.len == 0:
db.exec(sql"insert into controlblock(idgen) values (?)", gFrontEndId)
Expand Down Expand Up @@ -900,12 +909,14 @@ proc createDb() =
db.exec(sql"""
create table if not exists toplevelstmts(
id integer primary key,
position integer not null,
module integer not null,
data blob not null,
foreign key (module) references module(id)
);
""")
db.exec sql"create index TopLevelStmtByModuleIdx on toplevelstmts(module);"
db.exec sql"create index TopLevelStmtByPositionIdx on toplevelstmts(position);"

db.exec(sql"""
create table if not exists statics(
Expand Down
1 change: 1 addition & 0 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
replayMethodDefs(graph, c.rd)
popOwner(c)
popProcCon(c)
storeRemaining(c.module)
if c.runnableExamples != nil: testExamples(c)

const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose,
Expand Down
2 changes: 1 addition & 1 deletion compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
if cond: candidates.add typeToString(got)
if wanted != nil and got != nil:
effectProblem(wanted, got, candidates)
candidates.add "\n"
if cond: candidates.add "\n"
elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
add(candidates, "for a 'var' type a variable needs to be passed, but '" &
renderNotLValue(n[err.unmatchedVarParam]) &
Expand Down
18 changes: 15 additions & 3 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
of opcEqRef:
decodeBC(rkInt)
regs[ra].intVal = ord((regs[rb].node.kind == nkNilLit and
regs[rc].node.kind == nkNilLit) or
regs[rb].node == regs[rc].node)
if regs[rb].kind == rkNodeAddr:
if regs[rc].kind == rkNodeAddr:
regs[ra].intVal = ord(regs[rb].nodeAddr == regs[rc].nodeAddr)
else:
assert regs[rc].kind == rkNode
# we know these cannot be equal
regs[ra].intVal = ord(false)
elif regs[rc].kind == rkNodeAddr:
assert regs[rb].kind == rkNode
# we know these cannot be equal
regs[ra].intVal = ord(false)
else:
regs[ra].intVal = ord((regs[rb].node.kind == nkNilLit and
regs[rc].node.kind == nkNilLit) or
regs[rb].node == regs[rc].node)
of opcEqNimrodNode:
decodeBC(rkInt)
regs[ra].intVal =
Expand Down
2 changes: 1 addition & 1 deletion compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ proc whichAsgnOpc(n: PNode): TOpcode =
opcAsgnStr
of tyFloat..tyFloat128:
opcAsgnFloat
of tyRef, tyNil, tyVar, tyLent:
of tyRef, tyNil, tyVar, tyLent, tyPtr:
opcAsgnRef
else:
opcAsgnComplex
Expand Down
44 changes: 0 additions & 44 deletions lib/impure/rdstdin.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,32 +73,6 @@ when defined(Windows):
discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead)
return result

from unicode import toUTF8, Rune, runeLenAt

proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
## Reads a `password` from stdin without printing it. `password` must not
## be ``nil``! Returns ``false`` if the end of the file has been reached,
## ``true`` otherwise.
password.setLen(0)
stdout.write(prompt)
while true:
let c = getch()
case c.char
of '\r', chr(0xA):
break
of '\b':
# ensure we delete the whole UTF-8 character:
var i = 0
var x = 1
while i < password.len:
x = runeLenAt(password, i)
inc i, x
password.setLen(max(password.len - x, 0))
else:
password.add(toUTF8(c.Rune))
stdout.write "\n"

else:
import linenoise, termios

Expand All @@ -124,21 +98,3 @@ else:
linenoise.free(buffer)
result = true

proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
password.setLen(0)
let fd = stdin.getFileHandle()
var cur, old: Termios
discard fd.tcgetattr(cur.addr)
old = cur
cur.c_lflag = cur.c_lflag and not Cflag(ECHO)
discard fd.tcsetattr(TCSADRAIN, cur.addr)
stdout.write prompt
result = stdin.readLine(password)
stdout.write "\n"
discard fd.tcsetattr(TCSADRAIN, old.addr)

proc readPasswordFromStdin*(prompt: string): TaintedString =
## Reads a password from stdin without printing it.
result = TaintedString("")
discard readPasswordFromStdin(prompt, result)
14 changes: 8 additions & 6 deletions lib/js/asyncjs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@ type
PromiseJs* {.importcpp: "Promise".} = ref object
## A JavaScript Promise


proc replaceReturn(node: var NimNode) =
var z = 0
for s in node:
var son = node[z]
let jsResolve = ident("jsResolve")
if son.kind == nnkReturnStmt:
node[z] = nnkReturnStmt.newTree(nnkCall.newTree(ident("jsResolve"), son[0]))
let value = if son[0].kind != nnkEmpty: nnkCall.newTree(jsResolve, son[0]) else: jsResolve
node[z] = nnkReturnStmt.newTree(value)
elif son.kind == nnkAsgn and son[0].kind == nnkIdent and $son[0] == "result":
node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(ident("jsResolve"), son[1]))
node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(jsResolve, son[1]))
else:
replaceReturn(son)
inc z
Expand All @@ -92,8 +95,7 @@ proc generateJsasync(arg: NimNode): NimNode =
assert arg.kind == nnkProcDef
result = arg
var isVoid = false
var jsResolveNode = ident("jsResolve")

let jsResolve = ident("jsResolve")
if arg.params[0].kind == nnkEmpty:
result.params[0] = nnkBracketExpr.newTree(ident("Future"), ident("void"))
isVoid = true
Expand All @@ -112,7 +114,7 @@ proc generateJsasync(arg: NimNode): NimNode =
var resolve: NimNode
if isVoid:
resolve = quote:
var `jsResolveNode` {.importcpp: "undefined".}: Future[void]
var `jsResolve` {.importcpp: "undefined".}: Future[void]
else:
resolve = quote:
proc jsResolve[T](a: T): Future[T] {.importcpp: "#".}
Expand All @@ -124,7 +126,7 @@ proc generateJsasync(arg: NimNode): NimNode =

if len(code) > 0 and isVoid:
var voidFix = quote:
return `jsResolveNode`
return `jsResolve`
result.body.add(voidFix)

result.pragma = quote:
Expand Down
2 changes: 1 addition & 1 deletion lib/pure/asyncdispatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,7 @@ proc poll*(timeout = 500) =
# Common procedures between current and upcoming asyncdispatch
include includes.asynccommon

proc sleepAsync*(ms: int): Future[void] =
proc sleepAsync*(ms: int | float): Future[void] =
## Suspends the execution of the current async procedure for the next
## ``ms`` milliseconds.
var retFuture = newFuture[void]("sleepAsync")
Expand Down
1 change: 1 addition & 0 deletions lib/pure/parseopt2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
## 2. long option - ``--foo:bar``, ``--foo=bar`` or ``--foo``
## 3. argument - everything else

{.deprecated.}
{.push debugger: off.}

include "system/inclrtl"
Expand Down
Loading

0 comments on commit 7044343

Please sign in to comment.