extended system.type/typeof to support an upcoming 'collect' macro that works much better than sugar.lc

This commit is contained in:
Andreas Rumpf 2018-09-11 19:02:05 +02:00
commit 84d122b5c8
5 changed files with 67 additions and 56 deletions

View file

@ -37,7 +37,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool)
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
proc semStmt(c: PContext, n: PNode): PNode proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode
proc semOpAux(c: PContext, n: PNode) proc semOpAux(c: PContext, n: PNode)
proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
proc addParams(c: PContext, n: PNode, kind: TSymKind) proc addParams(c: PContext, n: PNode, kind: TSymKind)
@ -399,7 +399,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
excl(result.flags, nfSem) excl(result.flags, nfSem)
#resetSemFlag n #resetSemFlag n
if s.typ.sons[0] == nil: if s.typ.sons[0] == nil:
result = semStmt(c, result) result = semStmt(c, result, flags)
else: else:
case s.typ.sons[0].kind case s.typ.sons[0].kind
of tyExpr: of tyExpr:
@ -408,7 +408,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# semExprWithType(c, result) # semExprWithType(c, result)
result = semExpr(c, result, flags) result = semExpr(c, result, flags)
of tyStmt: of tyStmt:
result = semStmt(c, result) result = semStmt(c, result, flags)
of tyTypeDesc: of tyTypeDesc:
if result.kind == nkStmtList: result.kind = nkStmtListType if result.kind == nkStmtList: result.kind = nkStmtListType
var typ = semTypeNode(c, result, nil) var typ = semTypeNode(c, result, nil)
@ -557,7 +557,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = semAllTypeSections(c, n) result = semAllTypeSections(c, n)
else: else:
result = n result = n
result = semStmt(c, result) result = semStmt(c, result, {})
when false: when false:
# Code generators are lazy now and can deal with undeclared procs, so these # Code generators are lazy now and can deal with undeclared procs, so these
# steps are not required anymore and actually harmful for the upcoming # steps are not required anymore and actually harmful for the upcoming

View file

@ -918,7 +918,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
let isPush = hintExtendedContext in c.config.notes let isPush = hintExtendedContext in c.config.notes
if isPush: pushInfoContext(c.config, n.info) if isPush: pushInfoContext(c.config, n.info)
result = semExpr(c, n, {efWantStmt}) result = semExpr(c, n, {efWantStmt})
discardCheck(c, result) discardCheck(c, result, {})
if isPush: popInfoContext(c.config) if isPush: popInfoContext(c.config)
proc isTypeExpr(n: PNode): bool = proc isTypeExpr(n: PNode): bool =
@ -1530,7 +1530,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so # unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we # that overloading of the assignment operator still works. Usually we
# prefer to do these rewritings in transf.nim: # prefer to do these rewritings in transf.nim:
return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.p.owner)) return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.p.owner), {})
else: else:
a = semExprWithType(c, a, {efLValue}) a = semExprWithType(c, a, {efLValue})
else: else:
@ -1614,7 +1614,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
a.sons[1] = result a.sons[1] = result
result = semAsgn(c, a) result = semAsgn(c, a)
else: else:
discardCheck(c, result) discardCheck(c, result, {})
if c.p.owner.kind notin {skMacro, skTemplate} and if c.p.owner.kind notin {skMacro, skTemplate} and
c.p.resultSym != nil and c.p.resultSym.typ.isMetaType: c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
@ -1990,7 +1990,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
var x = n.lastSon var x = n.lastSon
if x.kind == nkDo: x = x.sons[bodyPos] if x.kind == nkDo: x = x.sons[bodyPos]
inc c.inParallelStmt inc c.inParallelStmt
result.sons[1] = semStmt(c, x) result.sons[1] = semStmt(c, x, {})
dec c.inParallelStmt dec c.inParallelStmt
of mSpawn: of mSpawn:
result = setMs(n, s) result = setMs(n, s)
@ -2241,7 +2241,7 @@ proc isTupleType(n: PNode): bool =
include semobjconstr include semobjconstr
proc semBlock(c: PContext, n: PNode): PNode = proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n result = n
inc(c.p.nestedBlockCounter) inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2, c.config) checkSonsLen(n, 2, c.config)
@ -2253,7 +2253,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(labl, n.sons[0].info) n.sons[0] = newSymNode(labl, n.sons[0].info)
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym) suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
styleCheckDef(c.config, labl) styleCheckDef(c.config, labl)
n.sons[1] = semExpr(c, n.sons[1]) n.sons[1] = semExpr(c, n.sons[1], flags)
n.typ = n.sons[1].typ n.typ = n.sons[1].typ
if isEmptyType(n.typ): n.kind = nkBlockStmt if isEmptyType(n.typ): n.kind = nkBlockStmt
else: n.kind = nkBlockExpr else: n.kind = nkBlockExpr
@ -2498,7 +2498,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
checkSonsLen(n, 1, c.config) checkSonsLen(n, 1, c.config)
n.sons[0] = semExpr(c, n.sons[0], flags) n.sons[0] = semExpr(c, n.sons[0], flags)
of nkCast: result = semCast(c, n) of nkCast: result = semCast(c, n)
of nkIfExpr, nkIfStmt: result = semIf(c, n) of nkIfExpr, nkIfStmt: result = semIf(c, n, flags)
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
checkSonsLen(n, 2, c.config) checkSonsLen(n, 2, c.config)
considerGenSyms(c, n) considerGenSyms(c, n)
@ -2519,7 +2519,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
discard discard
of nkStaticExpr: result = semStaticExpr(c, n[0]) of nkStaticExpr: result = semStaticExpr(c, n[0])
of nkAsgn: result = semAsgn(c, n) of nkAsgn: result = semAsgn(c, n)
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n) of nkBlockStmt, nkBlockExpr: result = semBlock(c, n, flags)
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags) of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)
of nkRaiseStmt: result = semRaise(c, n) of nkRaiseStmt: result = semRaise(c, n)
of nkVarSection: result = semVarOrLet(c, n, skVar) of nkVarSection: result = semVarOrLet(c, n, skVar)
@ -2527,11 +2527,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkConstSection: result = semConst(c, n) of nkConstSection: result = semConst(c, n)
of nkTypeSection: result = semTypeSection(c, n) of nkTypeSection: result = semTypeSection(c, n)
of nkDiscardStmt: result = semDiscard(c, n) of nkDiscardStmt: result = semDiscard(c, n)
of nkWhileStmt: result = semWhile(c, n) of nkWhileStmt: result = semWhile(c, n, flags)
of nkTryStmt: result = semTry(c, n) of nkTryStmt: result = semTry(c, n, flags)
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n) of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
of nkForStmt, nkParForStmt: result = semFor(c, n) of nkForStmt, nkParForStmt: result = semFor(c, n, flags)
of nkCaseStmt: result = semCase(c, n) of nkCaseStmt: result = semCase(c, n, flags)
of nkReturnStmt: result = semReturn(c, n) of nkReturnStmt: result = semReturn(c, n)
of nkUsingStmt: result = semUsing(c, n) of nkUsingStmt: result = semUsing(c, n)
of nkAsmStmt: result = semAsm(c, n) of nkAsmStmt: result = semAsm(c, n)

View file

@ -70,7 +70,7 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
openScope(c.c) openScope(c.c)
inc c.c.inUnrolledContext inc c.c.inUnrolledContext
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop) let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
father.add(semStmt(c.c, body)) father.add(semStmt(c.c, body, {}))
dec c.c.inUnrolledContext dec c.c.inUnrolledContext
closeScope(c.c) closeScope(c.c)
of nkNilLit: discard of nkNilLit: discard
@ -145,7 +145,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
fc.replaceByFieldName = m == mFieldPairs fc.replaceByFieldName = m == mFieldPairs
var body = instFieldLoopBody(fc, loopBody, n) var body = instFieldLoopBody(fc, loopBody, n)
inc c.inUnrolledContext inc c.inUnrolledContext
stmts.add(semStmt(c, body)) stmts.add(semStmt(c, body, {}))
dec c.inUnrolledContext dec c.inUnrolledContext
closeScope(c) closeScope(c)
else: else:

View file

@ -76,17 +76,19 @@ proc semAsm(c: PContext, n: PNode): PNode =
if marker == '\0': marker = '`' # default marker if marker == '\0': marker = '`' # default marker
result = semAsmOrEmit(c, n, marker) result = semAsmOrEmit(c, n, marker)
proc semWhile(c: PContext, n: PNode): PNode = proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n result = n
checkSonsLen(n, 2, c.config) checkSonsLen(n, 2, c.config)
openScope(c) openScope(c)
n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0])) n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
inc(c.p.nestedLoopCounter) inc(c.p.nestedLoopCounter)
n.sons[1] = semStmt(c, n.sons[1]) n.sons[1] = semStmt(c, n.sons[1], flags)
dec(c.p.nestedLoopCounter) dec(c.p.nestedLoopCounter)
closeScope(c) closeScope(c)
if n.sons[1].typ == c.enforceVoidContext: if n.sons[1].typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext result.typ = c.enforceVoidContext
elif efInTypeof in flags:
result.typ = n[1].typ
proc toCover(c: PContext, t: PType): BiggestInt = proc toCover(c: PContext, t: PType): BiggestInt =
let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc}) let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
@ -97,8 +99,8 @@ proc toCover(c: PContext, t: PType): BiggestInt =
proc semProc(c: PContext, n: PNode): PNode proc semProc(c: PContext, n: PNode): PNode
proc semExprBranch(c: PContext, n: PNode): PNode = proc semExprBranch(c: PContext, n: PNode; flags: TExprFlags = {}): PNode =
result = semExpr(c, n) result = semExpr(c, n, flags)
if result.typ != nil: if result.typ != nil:
# XXX tyGenericInst here? # XXX tyGenericInst here?
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result) if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
@ -130,8 +132,9 @@ proc fixNilType(c: PContext; n: PNode) =
for it in n: fixNilType(c, it) for it in n: fixNilType(c, it)
n.typ = nil n.typ = nil
proc discardCheck(c: PContext, result: PNode) = proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
if c.matchedConcept != nil: return if c.matchedConcept != nil or efInTypeof in flags: return
if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}: if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}:
if implicitlyDiscardable(result): if implicitlyDiscardable(result):
var n = newNodeI(nkDiscardStmt, result.info, 1) var n = newNodeI(nkDiscardStmt, result.info, 1)
@ -148,7 +151,7 @@ proc discardCheck(c: PContext, result: PNode) =
s.add "; for a function call use ()" s.add "; for a function call use ()"
localError(c.config, n.info, s) localError(c.config, n.info, s)
proc semIf(c: PContext, n: PNode): PNode = proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n result = n
var typ = commonTypeBegin var typ = commonTypeBegin
var hasElse = false var hasElse = false
@ -165,8 +168,9 @@ proc semIf(c: PContext, n: PNode): PNode =
it.sons[0] = semExprBranchScope(c, it.sons[0]) it.sons[0] = semExprBranchScope(c, it.sons[0])
typ = commonType(typ, it.sons[0]) typ = commonType(typ, it.sons[0])
else: illFormedAst(it, c.config) else: illFormedAst(it, c.config)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
for it in n: discardCheck(c, it.lastSon) (not hasElse and efInTypeof notin flags):
for it in n: discardCheck(c, it.lastSon, flags)
result.kind = nkIfStmt result.kind = nkIfStmt
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
@ -178,8 +182,7 @@ proc semIf(c: PContext, n: PNode): PNode =
result.kind = nkIfExpr result.kind = nkIfExpr
result.typ = typ result.typ = typ
proc semTry(c: PContext, n: PNode): PNode = proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
var check = initIntSet() var check = initIntSet()
template semExceptBranchType(typeNode: PNode): bool = template semExceptBranchType(typeNode: PNode): bool =
# returns true if exception type is imported type # returns true if exception type is imported type
@ -246,12 +249,12 @@ proc semTry(c: PContext, n: PNode): PNode =
dec c.p.inTryStmt dec c.p.inTryStmt
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}: if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}:
discardCheck(c, n.sons[0]) discardCheck(c, n.sons[0], flags)
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
if typ == c.enforceVoidContext: if typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext result.typ = c.enforceVoidContext
else: else:
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon) if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info) n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info)
for i in 1..last: for i in 1..last:
var it = n.sons[i] var it = n.sons[i]
@ -570,7 +573,7 @@ proc symForVar(c: PContext, n: PNode): PSym =
if n.kind == nkPragmaExpr: if n.kind == nkPragmaExpr:
pragma(c, result, n.sons[1], forVarPragmas) pragma(c, result, n.sons[1], forVarPragmas)
proc semForVars(c: PContext, n: PNode): PNode = proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n result = n
var length = sonsLen(n) var length = sonsLen(n)
let iterBase = n.sons[length-2].typ let iterBase = n.sons[length-2].typ
@ -601,7 +604,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
addForVarDecl(c, v) addForVarDecl(c, v)
inc(c.p.nestedLoopCounter) inc(c.p.nestedLoopCounter)
openScope(c) openScope(c)
n.sons[length-1] = semExprBranch(c, n.sons[length-1]) n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
closeScope(c) closeScope(c)
dec(c.p.nestedLoopCounter) dec(c.p.nestedLoopCounter)
@ -685,7 +688,7 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
when false: when false:
result = handleStmtMacro(c, n, n[0], "CaseStmt") result = handleStmtMacro(c, n, n[0], "CaseStmt")
proc semFor(c: PContext, n: PNode): PNode = proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
checkMinSonsLen(n, 3, c.config) checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n) var length = sonsLen(n)
if forLoopMacros in c.features: if forLoopMacros in c.features:
@ -702,14 +705,14 @@ proc semFor(c: PContext, n: PNode): PNode =
if isCallExpr and call[0].kind == nkSym and if isCallExpr and call[0].kind == nkSym and
call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}: call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}:
if call.sons[0].sym.magic == mOmpParFor: if call.sons[0].sym.magic == mOmpParFor:
result = semForVars(c, n) result = semForVars(c, n, flags)
result.kind = nkParForStmt result.kind = nkParForStmt
else: else:
result = semForFields(c, n, call.sons[0].sym.magic) result = semForFields(c, n, call.sons[0].sym.magic)
elif isCallExpr and call.sons[0].typ.callConv == ccClosure and elif isCallExpr and call.sons[0].typ.callConv == ccClosure and
tfIterator in call.sons[0].typ.flags: tfIterator in call.sons[0].typ.flags:
# first class iterator: # first class iterator:
result = semForVars(c, n) result = semForVars(c, n, flags)
elif not isCallExpr or call.sons[0].kind != nkSym or elif not isCallExpr or call.sons[0].kind != nkSym or
call.sons[0].sym.kind != skIterator: call.sons[0].sym.kind != skIterator:
if length == 3: if length == 3:
@ -718,15 +721,17 @@ proc semFor(c: PContext, n: PNode): PNode =
n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2]) n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
else: else:
localError(c.config, n.sons[length-2].info, "iterator within for loop context expected") localError(c.config, n.sons[length-2].info, "iterator within for loop context expected")
result = semForVars(c, n) result = semForVars(c, n, flags)
else: else:
result = semForVars(c, n) result = semForVars(c, n, flags)
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
if n.sons[length-1].typ == c.enforceVoidContext: if n.sons[length-1].typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext result.typ = c.enforceVoidContext
elif efInTypeof in flags:
result.typ = result.lastSon.typ
closeScope(c) closeScope(c)
proc semCase(c: PContext, n: PNode): PNode = proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n result = n
checkMinSonsLen(n, 2, c.config) checkMinSonsLen(n, 2, c.config)
openScope(c) openScope(c)
@ -782,8 +787,9 @@ proc semCase(c: PContext, n: PNode): PNode =
else: else:
localError(c.config, n.info, "not all cases are covered") localError(c.config, n.info, "not all cases are covered")
closeScope(c) closeScope(c)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) (not hasElse and efInTypeof notin flags):
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
if typ == c.enforceVoidContext: if typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext result.typ = c.enforceVoidContext
@ -1792,7 +1798,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
if containsOrIncl(c.includedFiles, f.int): if containsOrIncl(c.includedFiles, f.int):
localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f)) localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
else: else:
addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f))) addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {}))
excl(c.includedFiles, f.int) excl(c.includedFiles, f.int)
proc setLine(n: PNode, info: TLineInfo) = proc setLine(n: PNode, info: TLineInfo) =
@ -1819,7 +1825,7 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
#writeStackTrace() #writeStackTrace()
inc c.inStaticContext inc c.inStaticContext
openScope(c) openScope(c)
let a = semStmt(c, n.sons[0]) let a = semStmt(c, n.sons[0], {})
closeScope(c) closeScope(c)
dec c.inStaticContext dec c.inStaticContext
n.sons[0] = a n.sons[0] = a
@ -1895,11 +1901,11 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
if n.sons[i].typ == c.enforceVoidContext: #or usesResult(n.sons[i]): if n.sons[i].typ == c.enforceVoidContext: #or usesResult(n.sons[i]):
voidContext = true voidContext = true
n.typ = c.enforceVoidContext n.typ = c.enforceVoidContext
if i == last and (length == 1 or efWantValue in flags): if i == last and (length == 1 or ({efWantValue, efInTypeof} * flags != {})):
n.typ = n.sons[i].typ n.typ = n.sons[i].typ
if not isEmptyType(n.typ): n.kind = nkStmtListExpr if not isEmptyType(n.typ): n.kind = nkStmtListExpr
elif i != last or voidContext: elif i != last or voidContext:
discardCheck(c, n.sons[i]) discardCheck(c, n.sons[i], flags)
else: else:
n.typ = n.sons[i].typ n.typ = n.sons[i].typ
if not isEmptyType(n.typ): n.kind = nkStmtListExpr if not isEmptyType(n.typ): n.kind = nkStmtListExpr
@ -1928,6 +1934,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
# it is an old-style comment statement: we replace it with 'discard ""': # it is an old-style comment statement: we replace it with 'discard ""':
prettybase.replaceComment(result.info) prettybase.replaceComment(result.info)
proc semStmt(c: PContext, n: PNode): PNode = proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode =
# now: simply an alias: if efInTypeof notin flags:
result = semExprNoType(c, n) result = semExprNoType(c, n)
else:
result = semExpr(c, n, flags)

View file

@ -1161,7 +1161,7 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
checkMinSonsLen(n, 1, c.config) checkMinSonsLen(n, 1, c.config)
var length = sonsLen(n) var length = sonsLen(n)
for i in countup(0, length - 2): for i in countup(0, length - 2):
n.sons[i] = semStmt(c, n.sons[i]) n.sons[i] = semStmt(c, n.sons[i], {})
if length > 0: if length > 0:
result = semTypeNode(c, n.sons[length - 1], prev) result = semTypeNode(c, n.sons[length - 1], prev)
n.typ = result n.typ = result
@ -1406,6 +1406,13 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
result.rawAddSon(base) result.rawAddSon(base)
result.flags.incl tfHasStatic result.flags.incl tfHasStatic
proc semTypeof(c: PContext; n: PNode; prev: PType): PType =
openScope(c)
let t = semExprWithType(c, n, {efInTypeof})
closeScope(c)
fixupTypeOf(c, prev, t)
result = t.typ
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
inc c.inTypeContext inc c.inTypeContext
@ -1416,9 +1423,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkTypeOfExpr: of nkTypeOfExpr:
# for ``type(countup(1,3))``, see ``tests/ttoseq``. # for ``type(countup(1,3))``, see ``tests/ttoseq``.
checkSonsLen(n, 1, c.config) checkSonsLen(n, 1, c.config)
let typExpr = semExprWithType(c, n.sons[0], {efInTypeof}) result = semTypeof(c, n.sons[0], prev)
fixupTypeOf(c, prev, typExpr)
result = typExpr.typ
if result.kind == tyTypeDesc: result.flags.incl tfExplicit if result.kind == tyTypeDesc: result.flags.incl tfExplicit
of nkPar: of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
@ -1487,9 +1492,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semAnyRef(c, n, tyRef, prev) result = semAnyRef(c, n, tyRef, prev)
elif op.id == ord(wType): elif op.id == ord(wType):
checkSonsLen(n, 2, c.config) checkSonsLen(n, 2, c.config)
let typExpr = semExprWithType(c, n.sons[1], {efInTypeof}) result = semTypeof(c, n[1], prev)
fixupTypeOf(c, prev, typExpr)
result = typExpr.typ
else: else:
if c.inGenericContext > 0 and n.kind == nkCall: if c.inGenericContext > 0 and n.kind == nkCall:
result = makeTypeFromExpr(c, n.copyTree) result = makeTypeFromExpr(c, n.copyTree)