Merge branch 'devel' of https://github.com/Araq/Nimrod into new_spawn
Conflicts: lib/system.nim
This commit is contained in:
commit
85a1d896c2
40 changed files with 385 additions and 114 deletions
|
|
@ -511,6 +511,7 @@ const
|
|||
tfUncheckedArray* = tfVarargs
|
||||
tfUnion* = tfNoSideEffect
|
||||
tfGcSafe* = tfThread
|
||||
tfObjHasKids* = tfEnumHasHoles
|
||||
skError* = skUnknown
|
||||
|
||||
# type flags that are essential for type equality:
|
||||
|
|
|
|||
|
|
@ -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) =
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) =
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue