diff options
author | Araq <rumpf_a@web.de> | 2014-06-26 17:19:28 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-06-26 17:19:28 +0200 |
commit | 85a1d896c2ccb69d81003673b00ac21b53133b06 (patch) | |
tree | 673fdbe85f8291a658282a885d0d80f90d9e230c /compiler | |
parent | eed443d4b390b10e710d80619f5a7bc19fefb8d1 (diff) | |
parent | f793523ade7aa48dcf13ede123a0a434e39e54e0 (diff) | |
download | Nim-85a1d896c2ccb69d81003673b00ac21b53133b06.tar.gz |
Merge branch 'devel' of https://github.com/Araq/Nimrod into new_spawn
Conflicts: lib/system.nim
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 24 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 5 | ||||
-rw-r--r-- | compiler/cgen.nim | 1 | ||||
-rw-r--r-- | compiler/cgendata.nim | 1 | ||||
-rw-r--r-- | compiler/guards.nim | 2 | ||||
-rw-r--r-- | compiler/llstream.nim | 3 | ||||
-rw-r--r-- | compiler/parser.nim | 44 | ||||
-rw-r--r-- | compiler/sem.nim | 10 | ||||
-rw-r--r-- | compiler/semdata.nim | 4 | ||||
-rw-r--r-- | compiler/seminst.nim | 8 | ||||
-rw-r--r-- | compiler/semstmts.nim | 10 | ||||
-rw-r--r-- | compiler/semtypes.nim | 5 | ||||
-rw-r--r-- | compiler/suggest.nim | 9 | ||||
-rw-r--r-- | compiler/vmdeps.nim | 2 |
15 files changed, 84 insertions, 45 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 1755dcce9..461854496 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -511,6 +511,7 @@ const tfUncheckedArray* = tfVarargs tfUnion* = tfNoSideEffect tfGcSafe* = tfThread + tfObjHasKids* = tfEnumHasHoles skError* = skUnknown # type flags that are essential for type equality: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 69e382f8d..e6b22819f 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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) = diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 7a490082f..8e762ce27 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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")) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 314af7784..a5852c735 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -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) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index e7d818556..12041c55b 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -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 diff --git a/compiler/guards.nim b/compiler/guards.nim index 813a30014..4cf06fe02 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -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: diff --git a/compiler/llstream.nim b/compiler/llstream.nim index 510880ffd..86bfeaabd 100644 --- a/compiler/llstream.nim +++ b/compiler/llstream.nim @@ -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 diff --git a/compiler/parser.nim b/compiler/parser.nim index 2f9deb6b3..18de1570a 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -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) diff --git a/compiler/sem.nim b/compiler/sem.nim index 2e3b10a40..e4ef6473f 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -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 = diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 19181d98e..abecc1b6d 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -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() diff --git a/compiler/seminst.nim b/compiler/seminst.nim index f7d5fa6f8..b93d7ca15 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 43c7bf3fe..d17351988 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 3b9e82261..9d38c4619 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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 diff --git a/compiler/suggest.nim b/compiler/suggest.nim index fc6ba2f77..db95c480f 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -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) = diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 0e01f5031..9a213d813 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -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) |