Merge branch 'devel' of https://github.com/Araq/Nimrod into new_spawn

Conflicts:
	lib/system.nim
This commit is contained in:
Araq 2014-06-26 17:19:28 +02:00
commit 85a1d896c2
40 changed files with 385 additions and 114 deletions

View file

@ -511,6 +511,7 @@ const
tfUncheckedArray* = tfVarargs
tfUnion* = tfNoSideEffect
tfGcSafe* = tfThread
tfObjHasKids* = tfEnumHasHoles
skError* = skUnknown
# type flags that are essential for type equality:

View file

@ -1144,6 +1144,24 @@ proc genNewFinalize(p: BProc, e: PNode) =
genObjectInit(p, cpsStmts, bt, a, false)
gcUsage(e)
proc genOfHelper(p: BProc; dest: PType; a: PRope): PRope =
# unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
# have to call it here first:
let ti = genTypeInfo(p.module, dest)
if tfFinal in dest.flags or (p.module.objHasKidsValid and
tfObjHasKids notin dest.flags):
result = ropef("$1.m_type == $2", a, ti)
else:
discard cgsym(p.module, "TNimType")
inc p.module.labels
let cache = con("Nim_OfCheck_CACHE", p.module.labels.toRope)
appf(p.module.s[cfsVars], "static TNimType* $#[2];$n", cache)
result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
when false:
# former version:
result = rfmt(p.module, "#isObj($1.m_type, $2)",
a, genTypeInfo(p.module, dest))
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
var a: TLoc
initLocExpr(p, x, a)
@ -1163,11 +1181,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
globalError(x.info, errGenerated,
"no 'of' operator available for pure objects")
if nilCheck != nil:
r = rfmt(p.module, "(($1) && #isObj($2.m_type, $3))",
nilCheck, r, genTypeInfo(p.module, dest))
r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
else:
r = rfmt(p.module, "#isObj($1.m_type, $2)",
r, genTypeInfo(p.module, dest))
r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
putIntoDest(p, d, getSysType(tyBool), r)
proc genOf(p: BProc, n: PNode, d: var TLoc) =

View file

@ -796,6 +796,11 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
var tmp = getNimNode(m)
genObjectFields(m, typ, typ.n, tmp)
appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
var t = typ.sons[0]
while t != nil:
t = t.skipTypes(abstractInst)
t.flags.incl tfObjHasKids
t = t.sons[0]
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
genTypeInfoAuxBase(m, typ, name, toRope("0"))

View file

@ -1384,6 +1384,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
registerModuleToMain(m.module)
if sfMainModule in m.module.flags:
m.objHasKidsValid = true
var disp = generateMethodDispatchers()
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
genMainProc(m)

View file

@ -96,6 +96,7 @@ type
# a frame var twice in an init proc
isHeaderFile*: bool # C source file is the header file
includesStringh*: bool # C source file already includes ``<string.h>``
objHasKidsValid*: bool # whether we can rely on tfObjHasKids
cfilename*: string # filename of the module (including path,
# without extension)
typeCache*: TIdTable # cache the generated types

View file

@ -625,7 +625,7 @@ proc factImplies(fact, prop: PNode): TImplication =
# == not a or not b == not (a and b)
let arg = fact.sons[1]
case arg.getMagic
of mIsNil:
of mIsNil, mEqRef:
return ~factImplies(arg, prop)
of mAnd:
# not (a and b) means not a or not b:

View file

@ -82,6 +82,9 @@ when not defined(readLineFromStdin):
proc readLineFromStdin(prompt: string, line: var string): bool =
stdout.write(prompt)
result = readLine(stdin, line)
if not result:
stdout.write("\n")
quit(0)
proc endsWith*(x: string, s: set[char]): bool =
var i = x.len-1

View file

@ -147,8 +147,10 @@ proc expectIdent(p: TParser) =
proc eat(p: var TParser, tokType: TTokType) =
## Move the parser to the next token if the current token is of type
## `tokType`, otherwise error.
if p.tok.tokType == tokType: getTok(p)
else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
if p.tok.tokType == tokType:
getTok(p)
else:
lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
proc parLineInfo(p: TParser): TLineInfo =
## Retrieve the line information associated with the parser's current state.
@ -285,7 +287,7 @@ proc colcom(p: var TParser, n: PNode) =
skipComment(p, n)
proc parseSymbol(p: var TParser, allowNil = false): PNode =
#| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
#| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
#| | IDENT
case p.tok.tokType
of tkSymbol:
@ -296,31 +298,22 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode =
getTok(p)
while true:
case p.tok.tokType
of tkBracketLe:
add(result, newIdentNodeP(getIdent"[]", p))
getTok(p)
eat(p, tkBracketRi)
of tkEquals:
add(result, newIdentNodeP(getIdent"=", p))
getTok(p)
of tkParLe:
add(result, newIdentNodeP(getIdent"()", p))
getTok(p)
eat(p, tkParRi)
of tkCurlyLe:
add(result, newIdentNodeP(getIdent"{}", p))
getTok(p)
eat(p, tkCurlyRi)
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot:
add(result, newIdentNodeP(p.tok.ident, p))
getTok(p)
of tkIntLit..tkCharLit:
add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p))
getTok(p)
else:
of tkAccent:
if result.len == 0:
parMessage(p, errIdentifierExpected, p.tok)
break
of tkOpr, tkDot, tkDotDot, tkEquals, tkParLe..tkParDotRi:
var accm = ""
while p.tok.tokType in {tkOpr, tkDot, tkDotDot, tkEquals,
tkParLe..tkParDotRi}:
accm.add(tokToStr(p.tok))
getTok(p)
result.add(newIdentNodeP(getIdent(accm), p))
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkIntLit..tkCharLit:
result.add(newIdentNodeP(getIdent(tokToStr(p.tok)), p))
getTok(p)
else:
parMessage(p, errIdentifierExpected, p.tok)
eat(p, tkAccent)
else:
if allowNil and p.tok.tokType == tkNil:
@ -993,6 +986,7 @@ proc parseSymbolList(p: var TParser, result: PNode, allowNil = false) =
proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
mode: TPrimaryMode): PNode =
#| distinct = 'distinct' optInd typeDesc
result = newNodeP(kind, p)
getTok(p)
optInd(p, result)

View file

@ -269,11 +269,15 @@ include hlo, seminst, semcall
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
flags: TExprFlags): PNode =
## Semantically check the output of a macro.
## This involves processes such as re-checking the macro output for type
## coherence, making sure that variables declared with 'let' aren't
## reassigned, and binding the unbound identifiers that the macro output
## contains.
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
globalError(s.info, errTemplateInstantiationTooNested)
let oldFriend = c.friendModule
c.friendModule = s.owner.getModule
c.friendModules.add(s.owner.getModule)
result = n
if s.typ.sons[0] == nil:
@ -297,7 +301,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
result = fitNode(c, s.typ.sons[0], result)
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(evalTemplateCounter)
c.friendModule = oldFriend
discard c.friendModules.pop()
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =

View file

@ -52,7 +52,7 @@ type
importTable*: PScope # scope for all imported symbols
topLevelScope*: PScope # scope for all top-level symbols
p*: PProcCon # procedure context
friendModule*: PSym # current friend module; may access private data;
friendModules*: seq[PSym] # friend modules; may access private data;
# this is used so that generic instantiations
# can access private object fields
instCounter*: int # to prevent endless instantiations
@ -169,7 +169,7 @@ proc newContext(module: PSym): PContext =
initLinkedList(result.libs)
append(result.optionStack, newOptionEntry())
result.module = module
result.friendModule = module
result.friendModules = @[module]
result.converters = @[]
result.patterns = @[]
result.includedFiles = initIntSet()

View file

@ -190,6 +190,9 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym =
## Generates a new instance of a generic procedure.
## The `pt` parameter is a type-unsafe mapping table used to link generic
## parameters to their concrete types within the generic instance.
# no need to instantiate generic templates/macros:
if fn.kind in {skTemplate, skMacro}: return fn
# generates an instantiated proc
@ -199,8 +202,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
var n = copyTree(fn.ast)
# NOTE: for access of private fields within generics from a different module
# we set the friend module:
var oldFriend = c.friendModule
c.friendModule = getModule(fn)
c.friendModules.add(getModule(fn))
#let oldScope = c.currentScope
#c.currentScope = fn.scope
result = copySym(fn, false)
@ -236,6 +238,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
closeScope(c) # close scope for parameters
popOwner()
#c.currentScope = oldScope
c.friendModule = oldFriend
discard c.friendModules.pop()
dec(c.instCounter)
if result.kind == skMethod: finishMethod(c, result)

View file

@ -66,10 +66,16 @@ proc toCover(t: PType): BiggestInt =
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
## Checks that the given symbol is a proper procedure variable, meaning
## that it
var smoduleId = getModule(s).id
if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
smoduleId != c.module.id and smoduleId != c.friendModule.id:
localError(n.info, errXCannotBePassedToProcVar, s.name.s)
smoduleId != c.module.id:
block outer:
for module in c.friendModules:
if smoduleId == module.id:
break outer
localError(n.info, errXCannotBePassedToProcVar, s.name.s)
proc semProcvarCheck(c: PContext, n: PNode) =
let n = n.skipConv

View file

@ -70,9 +70,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
counter = x
of nkSym:
e = n.sons[i].sym
of nkIdent:
of nkIdent, nkAccQuoted:
e = newSymS(skEnumField, n.sons[i], c)
else: illFormedAst(n)
else:
illFormedAst(n[i])
e.typ = result
e.position = int(counter)
if e.position == 0: hasNull = true

View file

@ -63,8 +63,11 @@ proc filterSym(s: PSym): bool {.inline.} =
proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
let fmoduleId = getModule(f).id
result = sfExported in f.flags or fmoduleId == c.module.id or
fmoduleId == c.friendModule.id
result = sfExported in f.flags or fmoduleId == c.module.id
for module in c.friendModules:
if fmoduleId == module.id:
result = true
break
proc suggestField(c: PContext, s: PSym, outputs: var int) =
if filterSym(s) and fieldVisible(c, s):
@ -319,7 +322,7 @@ proc suggestSym*(n: PNode, s: PSym) {.inline.} =
findUsages(n, s)
if optDef in gGlobalOptions:
findDefinition(n, s)
if isServing:
if isServing and not n.isNil:
addToSourceMap(s, n.info)
proc markUsed(n: PNode, s: PSym) =

View file

@ -15,6 +15,8 @@ proc readOutput(p: PProcess): string =
discard p.waitForExit
while not output.atEnd:
result.add(output.readLine)
result.add("\n")
result.setLen(result.len - "\n".len)
proc opGorge*(cmd, input: string): string =
var p = startCmd(cmd)