A minimal patch enabling the new typedesc and static types syntax

This commit is contained in:
Zahary Karadjov 2018-04-20 11:44:13 +03:00
commit fb27357b62
10 changed files with 228 additions and 110 deletions

View file

@ -571,8 +571,8 @@ type
TMagic* = enum # symbols that require compiler magic: TMagic* = enum # symbols that require compiler magic:
mNone, mNone,
mDefined, mDefinedInScope, mCompiles, mArrGet, mArrPut, mAsgn, mDefined, mDefinedInScope, mCompiles, mArrGet, mArrPut, mAsgn,
mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mRoof, mPlugin, mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mType, mTypeOf,
mEcho, mShallowCopy, mSlurp, mStaticExec, mRoof, mPlugin, mEcho, mShallowCopy, mSlurp, mStaticExec, mStatic,
mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst, mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
mUnaryLt, mInc, mDec, mOrd, mUnaryLt, mInc, mDec, mOrd,
mNew, mNewFinalize, mNewSeq, mNewSeqOfCap, mNew, mNewFinalize, mNewSeq, mNewSeqOfCap,

View file

@ -44,6 +44,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimcomputedgoto") defineSymbol("nimcomputedgoto")
defineSymbol("nimunion") defineSymbol("nimunion")
defineSymbol("nimnewshared") defineSymbol("nimnewshared")
defineSymbol("nimNewTypedesc")
defineSymbol("nimrequiresnimframe") defineSymbol("nimrequiresnimframe")
defineSymbol("nimparsebiggestfloatmagic") defineSymbol("nimparsebiggestfloatmagic")
defineSymbol("nimalias") defineSymbol("nimalias")

View file

@ -50,6 +50,9 @@ type
SymbolMode = enum SymbolMode = enum
smNormal, smAllowNil, smAfterDot smNormal, smAllowNil, smAfterDot
TPrimaryMode = enum
pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
proc parseAll*(p: var TParser): PNode proc parseAll*(p: var TParser): PNode
proc closeParser*(p: var TParser) proc closeParser*(p: var TParser)
proc parseTopLevelStmt*(p: var TParser): PNode proc parseTopLevelStmt*(p: var TParser): PNode
@ -81,6 +84,9 @@ proc parsePragma(p: var TParser): PNode
proc postExprBlocks(p: var TParser, x: PNode): PNode proc postExprBlocks(p: var TParser, x: PNode): PNode
proc parseExprStmt(p: var TParser): PNode proc parseExprStmt(p: var TParser): PNode
proc parseBlock(p: var TParser): PNode proc parseBlock(p: var TParser): PNode
proc primary(p: var TParser, mode: TPrimaryMode): PNode
proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode
# implementation # implementation
proc getTok(p: var TParser) = proc getTok(p: var TParser) =
@ -332,6 +338,8 @@ proc colcom(p: var TParser, n: PNode) =
eat(p, tkColon) eat(p, tkColon)
skipComment(p, n) skipComment(p, n)
const tkBuiltInMagics = {tkType, tkStatic, tkAddr}
proc parseSymbol(p: var TParser, mode = smNormal): PNode = proc parseSymbol(p: var TParser, mode = smNormal): PNode =
#| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`' #| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
#| | IDENT | KEYW #| | IDENT | KEYW
@ -340,7 +348,7 @@ proc parseSymbol(p: var TParser, mode = smNormal): PNode =
result = newIdentNodeP(p.tok.ident, p) result = newIdentNodeP(p.tok.ident, p)
getTok(p) getTok(p)
of tokKeywordLow..tokKeywordHigh: of tokKeywordLow..tokKeywordHigh:
if p.tok.tokType == tkAddr or p.tok.tokType == tkType or mode == smAfterDot: if p.tok.tokType in tkBuiltInMagics or mode == smAfterDot:
# for backwards compatibility these 2 are always valid: # for backwards compatibility these 2 are always valid:
result = newIdentNodeP(p.tok.ident, p) result = newIdentNodeP(p.tok.ident, p)
getTok(p) getTok(p)
@ -525,9 +533,6 @@ proc parseGStrLit(p: var TParser, a: PNode): PNode =
else: else:
result = a result = a
type
TPrimaryMode = enum pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
proc complexOrSimpleStmt(p: var TParser): PNode proc complexOrSimpleStmt(p: var TParser): PNode
proc simpleExpr(p: var TParser, mode = pmNormal): PNode proc simpleExpr(p: var TParser, mode = pmNormal): PNode
@ -625,7 +630,7 @@ proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
#| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')' #| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
#| arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']' #| arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
case p.tok.tokType case p.tok.tokType
of tkSymbol, tkType, tkAddr: of tkSymbol, tkBuiltInMagics:
result = newIdentNodeP(p.tok.ident, p) result = newIdentNodeP(p.tok.ident, p)
getTok(p) getTok(p)
result = parseGStrLit(p, result) result = parseGStrLit(p, result)
@ -741,7 +746,12 @@ proc commandParam(p: var TParser, isFirstParam: var bool): PNode =
addSon(result, parseExpr(p)) addSon(result, parseExpr(p))
isFirstParam = false isFirstParam = false
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = const
tkTypeClasses = {tkRef, tkPtr, tkVar, tkStatic, tkType,
tkEnum, tkTuple, tkObject, tkProc}
proc primarySuffix(p: var TParser, r: PNode,
baseIndent: int, mode: TPrimaryMode): PNode =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks? #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
#| | doBlocks #| | doBlocks
#| | '.' optInd symbol generalizedLit? #| | '.' optInd symbol generalizedLit?
@ -758,7 +768,14 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
case p.tok.tokType case p.tok.tokType
of tkParLe: of tkParLe:
# progress guaranteed # progress guaranteed
somePar() if p.tok.strongSpaceA > 0:
# inside type sections, expressions such as `ref (int, bar)`
# are parsed as a nkCommand with a single tuple argument (nkPar)
if mode == pmTypeDef:
result = newNodeP(nkCommand, p)
result.addSon r
result.addSon primary(p, pmNormal)
break
result = namedParams(p, result, nkCall, tkParRi) result = namedParams(p, result, nkCall, tkParRi)
if result.len > 1 and result.sons[1].kind == nkExprColonExpr: if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
result.kind = nkObjConstr result.kind = nkObjConstr
@ -774,9 +791,15 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
# progress guaranteed # progress guaranteed
somePar() somePar()
result = namedParams(p, result, nkCurlyExpr, tkCurlyRi) result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkAddr, tkType, of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast,
tkOpr, tkDotDot: tkOpr, tkDotDot, tkTypeClasses - {tkRef, tkPtr}:
if p.inPragma == 0 and (isUnary(p) or p.tok.tokType notin {tkOpr, tkDotDot}): # XXX: In type sections we allow the free application of the
# command syntax, with the exception of expressions such as
# `foo ref` or `foo ptr`. Unfortunately, these two are also
# used as infix operators for the memory regions feature and
# the current parsing rules don't play well here.
if mode == pmTypeDef or
(p.inPragma == 0 and (isUnary(p) or p.tok.tokType notin {tkOpr, tkDotDot})):
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet # actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
# solution, but pragmas.nim can't handle that # solution, but pragmas.nim can't handle that
let a = result let a = result
@ -800,9 +823,6 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
else: else:
break break
proc primary(p: var TParser, mode: TPrimaryMode): PNode
proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode
proc parseOperators(p: var TParser, headNode: PNode, proc parseOperators(p: var TParser, headNode: PNode,
limit: int, mode: TPrimaryMode): PNode = limit: int, mode: TPrimaryMode): PNode =
result = headNode result = headNode
@ -1107,9 +1127,9 @@ proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
proc isExprStart(p: TParser): bool = proc isExprStart(p: TParser): bool =
case p.tok.tokType case p.tok.tokType
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
tkProc, tkFunc, tkIterator, tkBind, tkAddr, tkProc, tkFunc, tkIterator, tkBind, tkBuiltInMagics,
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut: tkTuple, tkObject, tkWhen, tkCase, tkOut:
result = true result = true
else: result = false else: result = false
@ -1170,7 +1190,6 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
#| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum' #| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
#| primary = typeKeyw typeDescK #| primary = typeKeyw typeDescK
#| / prefixOperator* identOrLiteral primarySuffix* #| / prefixOperator* identOrLiteral primarySuffix*
#| / 'static' primary
#| / 'bind' primary #| / 'bind' primary
if isOperator(p.tok): if isOperator(p.tok):
let isSigil = isSigilLike(p.tok) let isSigil = isSigilLike(p.tok)
@ -1183,7 +1202,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
#XXX prefix operators #XXX prefix operators
let baseInd = p.lex.currLineIndent let baseInd = p.lex.currLineIndent
addSon(result, primary(p, pmSkipSuffix)) addSon(result, primary(p, pmSkipSuffix))
result = primarySuffix(p, result, baseInd) result = primarySuffix(p, result, baseInd, mode)
else: else:
addSon(result, primary(p, pmNormal)) addSon(result, primary(p, pmNormal))
return return
@ -1213,14 +1232,6 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
result = parseTypeClass(p) result = parseTypeClass(p)
else: else:
parMessage(p, "the 'concept' keyword is only valid in 'type' sections") parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
of tkStatic:
let info = parLineInfo(p)
getTokNoInd(p)
let next = primary(p, pmNormal)
if next.kind == nkBracket and next.sonsLen == 1:
result = newNode(nkStaticTy, info, @[next.sons[0]])
else:
result = newNode(nkStaticExpr, info, @[next])
of tkBind: of tkBind:
result = newNodeP(nkBind, p) result = newNodeP(nkBind, p)
getTok(p) getTok(p)
@ -1235,7 +1246,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
let baseInd = p.lex.currLineIndent let baseInd = p.lex.currLineIndent
result = identOrLiteral(p, mode) result = identOrLiteral(p, mode)
if mode != pmSkipSuffix: if mode != pmSkipSuffix:
result = primarySuffix(p, result, baseInd) result = primarySuffix(p, result, baseInd, mode)
proc parseTypeDesc(p: var TParser): PNode = proc parseTypeDesc(p: var TParser): PNode =
#| typeDesc = simpleExpr #| typeDesc = simpleExpr

View file

@ -48,6 +48,9 @@ proc semQuoteAst(c: PContext, n: PNode): PNode
proc finishMethod(c: PContext, s: PSym) proc finishMethod(c: PContext, s: PSym)
proc evalAtCompileTime(c: PContext, n: PNode): PNode proc evalAtCompileTime(c: PContext, n: PNode): PNode
proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
proc semStaticExpr(c: PContext, n: PNode): PNode
proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType
proc semTypeOf(c: PContext; n: PNode): PNode
proc isArrayConstr(n: PNode): bool {.inline.} = proc isArrayConstr(n: PNode): bool {.inline.} =
result = n.kind == nkBracket and result = n.kind == nkBracket and

View file

@ -191,7 +191,25 @@ proc semConv(c: PContext, n: PNode): PNode =
return n return n
result = newNodeI(nkConv, n.info) result = newNodeI(nkConv, n.info)
var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
var targetType = semTypeNode(c, n.sons[0], nil)
if targetType.kind == tyTypeDesc:
internalAssert targetType.len > 0
if targetType.base.kind == tyNone:
return semTypeOf(c, n[1])
else:
targetType = targetType.base
elif targetType.kind == tyStatic:
var evaluated = semStaticExpr(c, n[1])
if evaluated.kind == nkType or evaluated.typ.kind == tyTypeDesc:
result = n
result.typ = c.makeTypeDesc semStaticType(c, evaluated, nil)
return
elif targetType.base.kind == tyNone:
return evaluated
else:
targetType = targetType.base
maybeLiftType(targetType, c, n[0].info) maybeLiftType(targetType, c, n[0].info)
if targetType.kind in {tySink, tyLent}: if targetType.kind in {tySink, tyLent}:
@ -632,7 +650,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
# echo "SUCCESS evaluated at compile time: ", call.renderTree # echo "SUCCESS evaluated at compile time: ", call.renderTree
proc semStaticExpr(c: PContext, n: PNode): PNode = proc semStaticExpr(c: PContext, n: PNode): PNode =
let a = semExpr(c, n.sons[0]) let a = semExpr(c, n)
if a.findUnresolvedStatic != nil: return a if a.findUnresolvedStatic != nil: return a
result = evalStaticExpr(c.module, c.graph, a, c.p.owner) result = evalStaticExpr(c.module, c.graph, a, c.p.owner)
if result.isNil: if result.isNil:
@ -1034,7 +1052,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
of skType: of skType:
markUsed(c.config, n.info, s, c.graph.usageSym) markUsed(c.config, n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil: if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
return s.typ.n return s.typ.n
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
result.typ = makeTypeDesc(c, s.typ) result.typ = makeTypeDesc(c, s.typ)
@ -1261,8 +1279,18 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
# make sure we don't evaluate generic macros/templates # make sure we don't evaluate generic macros/templates
n.sons[0] = semExprWithType(c, n.sons[0], n.sons[0] = semExprWithType(c, n.sons[0],
{efNoEvaluateGeneric}) {efNoEvaluateGeneric})
let arr = skipTypes(n.sons[0].typ, {tyGenericInst, var arr = skipTypes(n.sons[0].typ, {tyGenericInst,
tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink}) tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink})
if arr.kind == tyStatic:
if arr.base.kind == tyNone:
result = n
result.typ = semStaticType(c, n[1], nil)
return
elif arr.n != nil:
return semSubscript(c, arr.n, flags)
else:
arr = arr.base
case arr.kind case arr.kind
of tyArray, tyOpenArray, tyVarargs, tySequence, tyString, of tyArray, tyOpenArray, tyVarargs, tySequence, tyString,
tyCString: tyCString:
@ -2426,8 +2454,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# handling of sym choices is context dependent # handling of sym choices is context dependent
# the node is left intact for now # the node is left intact for now
discard discard
of nkStaticExpr: of nkStaticExpr: result = semStaticExpr(c, n[0])
result = semStaticExpr(c, n)
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)
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags) of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)

View file

@ -37,6 +37,12 @@ const
errNoGenericParamsAllowedForX = "no generic parameters allowed for $1" errNoGenericParamsAllowedForX = "no generic parameters allowed for $1"
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types" errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"
const
mStaticTy = {mStatic}
mTypeTy = {mType, mTypeOf}
# XXX: This should be needed only temporarily until the C
# sources are rebuilt
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType = proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
if prev == nil: if prev == nil:
result = newTypeS(kind, c) result = newTypeS(kind, c)
@ -363,6 +369,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
if result != nil: if result != nil:
markUsed(c.config, n.info, result, c.graph.usageSym) markUsed(c.config, n.info, result, c.graph.usageSym)
styleCheckUse(n.info, result) styleCheckUse(n.info, result)
if result.kind == skParam and result.typ.kind == tyTypeDesc: if result.kind == skParam and result.typ.kind == tyTypeDesc:
# This is a typedesc param. is it already bound? # This is a typedesc param. is it already bound?
# it's not bound when it's used multiple times in the # it's not bound when it's used multiple times in the
@ -388,8 +395,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
else: else:
localError(c.config, n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
return errorSym(c, n) return errorSym(c, n)
if result.kind != skType and result.magic notin (mStaticTy + mTypeTy):
if result.kind != skType:
# this implements the wanted ``var v: V, x: V`` feature ... # this implements the wanted ``var v: V, x: V`` feature ...
var ov: TOverloadIter var ov: TOverloadIter
var amb = initOverloadIter(ov, c, n) var amb = initOverloadIter(ov, c, n)
@ -856,9 +862,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = addImplicitGenericImpl(c, newTypeS(tyGenericParam, c), nil) result = addImplicitGenericImpl(c, newTypeS(tyGenericParam, c), nil)
of tyStatic: of tyStatic:
# proc(a: expr{string}, b: expr{nkLambda}) if paramType.base.kind != tyNone and paramType.n != nil:
# overload on compile time values and AST trees # this is a concrete type
if paramType.n != nil: return # this is a concrete type return
if tfUnresolved in paramType.flags: return # already lifted if tfUnresolved in paramType.flags: return # already lifted
let base = paramType.base.maybeLift let base = paramType.base.maybeLift
if base.isMetaType and procKind == skMacro: if base.isMetaType and procKind == skMacro:
@ -879,7 +885,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyDistinct: of tyDistinct:
if paramType.sonsLen == 1: if paramType.sonsLen == 1:
# disable the bindOnce behavior for the type class # disable the bindOnce behavior for the type class
result = liftingWalk(paramType.sons[0], true) result = liftingWalk(paramType.base, true)
of tySequence, tySet, tyArray, tyOpenArray, of tySequence, tySet, tyArray, tyOpenArray,
tyVar, tyLent, tyPtr, tyRef, tyProc: tyVar, tyLent, tyPtr, tyRef, tyProc:
@ -1349,6 +1355,12 @@ proc symFromExpectedTypeNode(c: PContext, n: PNode): PSym =
localError(c.config, n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = errorSym(c, n) result = errorSym(c, n)
proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
result = newOrPrevType(tyStatic, prev, c)
var base = semTypeNode(c, childNode, nil).skipTypes({tyTypeDesc, tyAlias})
result.rawAddSon(base)
result.flags.incl tfHasStatic
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
@ -1456,7 +1468,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mSeq: result = semContainer(c, n, tySequence, "seq", prev) of mSeq: result = semContainer(c, n, tySequence, "seq", prev)
of mOpt: result = semContainer(c, n, tyOpt, "opt", prev) of mOpt: result = semContainer(c, n, tyOpt, "opt", prev)
of mVarargs: result = semVarargs(c, n, prev) of mVarargs: result = semVarargs(c, n, prev)
of mTypeDesc: result = makeTypeDesc(c, semTypeNode(c, n[1], nil)) of mTypeDesc, mTypeTy: result = makeTypeDesc(c, semTypeNode(c, n[1], nil))
of mStaticTy: result = semStaticType(c, n[1], prev)
of mExpr: of mExpr:
result = semTypeNode(c, n.sons[0], nil) result = semTypeNode(c, n.sons[0], nil)
if result != nil: if result != nil:
@ -1545,11 +1558,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev) of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
of nkVarTy: result = semVarType(c, n, prev) of nkVarTy: result = semVarType(c, n, prev)
of nkDistinctTy: result = semDistinct(c, n, prev) of nkDistinctTy: result = semDistinct(c, n, prev)
of nkStaticTy: of nkStaticTy: result = semStaticType(c, n[0], prev)
result = newOrPrevType(tyStatic, prev, c)
var base = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
result.rawAddSon(base)
result.flags.incl tfHasStatic
of nkIteratorTy: of nkIteratorTy:
if n.sonsLen == 0: if n.sonsLen == 0:
result = newTypeS(tyBuiltInTypeClass, c) result = newTypeS(tyBuiltInTypeClass, c)
@ -1645,9 +1654,12 @@ proc processMagicType(c: PContext, m: PSym) =
of mStmt: of mStmt:
setMagicType(c.config, m, tyStmt, 0) setMagicType(c.config, m, tyStmt, 0)
if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
of mTypeDesc: of mTypeDesc, mType:
setMagicType(c.config, m, tyTypeDesc, 0) setMagicType(c.config, m, tyTypeDesc, 0)
rawAddSon(m.typ, newTypeS(tyNone, c)) rawAddSon(m.typ, newTypeS(tyNone, c))
of mStatic:
setMagicType(m, tyStatic, 0)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mVoidType: of mVoidType:
setMagicType(c.config, m, tyVoid, 0) setMagicType(c.config, m, tyVoid, 0)
of mArray: of mArray:

View file

@ -1666,13 +1666,17 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
let prev = PType(idTableGet(c.bindings, f)) let prev = PType(idTableGet(c.bindings, f))
if prev == nil: if prev == nil:
if aOrig.kind == tyStatic: if aOrig.kind == tyStatic:
result = typeRel(c, f.lastSon, a) if f.base.kind != tyNone:
if result != isNone and f.n != nil: result = typeRel(c, f.base, a)
if not exprStructuralEquivalent(f.n, aOrig.n): if result != isNone and f.n != nil:
result = isNone if not exprStructuralEquivalent(f.n, aOrig.n):
result = isNone
else:
result = isGeneric
if result != isNone: put(c, f, aOrig) if result != isNone: put(c, f, aOrig)
elif aOrig.n != nil and aOrig.n.typ != nil: elif aOrig.n != nil and aOrig.n.typ != nil:
result = typeRel(c, f.lastSon, aOrig.n.typ) result = if f.base.kind != tyNone: typeRel(c, f.lastSon, aOrig.n.typ)
else: isGeneric
if result != isNone: if result != isNone:
var boundType = newTypeWithSons(c.c, tyStatic, @[aOrig.n.typ]) var boundType = newTypeWithSons(c.c, tyStatic, @[aOrig.n.typ])
boundType.n = aOrig.n boundType.n = aOrig.n

View file

@ -179,10 +179,24 @@ proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
## Cannot be overloaded. ## Cannot be overloaded.
discard discard
proc `type`*(x: untyped): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} = when defined(nimNewTypedesc):
## Builtin 'type' operator for accessing the type of an expression. type
## Cannot be overloaded. `static`* {.magic: "Static".}[T]
discard ## meta type representing all values that can be evaluated at compile-time.
##
## The type coercion ``static(x)`` can be used to force the compile-time
## evaluation of the given expression ``x``.
`type`* {.magic: "Type".}[T]
## meta type representing the type of all type values.
##
## The coercion ``type(x)`` can be used to obtain the type of the given
## expression ``x``.
else:
proc `type`*(x: untyped): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} =
## Builtin 'type' operator for accessing the type of an expression.
## Cannot be overloaded.
discard
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
## Boolean not; returns true iff ``x == false``. ## Boolean not; returns true iff ``x == false``.

View file

@ -4,7 +4,7 @@ discard """
errormsg: "invalid indentation" errormsg: "invalid indentation"
""" """
import strutils var s: seq[int] = @[0, 1, 2, 3, 4, 5, 6] import strutils let s: seq[int] = @[0, 1, 2, 3, 4, 5, 6]
#s[1..3] = @[] #s[1..3] = @[]

View file

@ -53,25 +53,33 @@ StmtList
Par Par
Ident "a" Ident "a"
Ident "b" Ident "b"
TypeDef
Ident "BareStatic"
Empty
Ident "static"
TypeDef TypeDef
Ident "GenericStatic" Ident "GenericStatic"
Empty Empty
StaticTy BracketExpr
Ident "static"
Ident "int" Ident "int"
TypeDef TypeDef
Ident "PrefixStatic" Ident "PrefixStatic"
Empty Empty
StaticExpr Command
Ident "static"
Ident "int" Ident "int"
TypeDef TypeDef
Ident "StaticTupleCl" Ident "StaticTupleCl"
Empty Empty
StaticExpr Command
Ident "static"
TupleClassTy TupleClassTy
TypeDef TypeDef
Ident "StaticTuple" Ident "StaticTuple"
Empty Empty
StaticExpr Command
Ident "static"
Par Par
Ident "int" Ident "int"
Ident "string" Ident "string"
@ -91,6 +99,12 @@ StmtList
BracketExpr BracketExpr
Ident "type" Ident "type"
TupleClassTy TupleClassTy
TypeDef
Ident "TypeTupleCl"
Empty
Command
Ident "type"
TupleClassTy
TypeDef TypeDef
Ident "TypeInstance" Ident "TypeInstance"
Empty Empty
@ -109,6 +123,13 @@ StmtList
Call Call
Ident "type" Ident "type"
Ident "a" Ident "a"
TypeDef
Ident "TypeOfVarAlt"
Empty
Command
Ident "type"
Par
Ident "a"
TypeDef TypeDef
Ident "TypeOfTuple1" Ident "TypeOfTuple1"
Empty Empty
@ -122,6 +143,29 @@ StmtList
Ident "type" Ident "type"
Ident "a" Ident "a"
Ident "b" Ident "b"
TypeDef
Ident "TypeOfTuple1A"
Empty
Command
Ident "type"
TupleConstr
Ident "a"
TypeDef
Ident "TypeOfTuple2A"
Empty
Command
Ident "type"
Par
Ident "a"
Ident "b"
TypeDef
Ident "TypeTuple"
Empty
Command
Ident "type"
Par
Ident "int"
Ident "string"
TypeDef TypeDef
Ident "GenericTypedesc" Ident "GenericTypedesc"
Empty Empty
@ -172,32 +216,52 @@ StmtList
Ident "foo" Ident "foo"
Ident "type" Ident "type"
Empty Empty
IdentDefs
Ident "typeTupleCl"
Command
Ident "type"
TupleClassTy
Empty
IdentDefs
Ident "bareStatic"
Ident "static"
Empty
IdentDefs IdentDefs
Ident "genStatic" Ident "genStatic"
StaticTy BracketExpr
Ident "static"
Ident "int" Ident "int"
Empty Empty
IdentDefs IdentDefs
Ident "staticInt" Ident "staticInt"
StaticExpr Command
Ident "static"
Ident "int" Ident "int"
Empty Empty
IdentDefs IdentDefs
Ident "staticVal1" Ident "staticVal1"
StaticExpr Command
Ident "static"
IntLit 10 IntLit 10
Empty Empty
IdentDefs IdentDefs
Ident "staticVal2" Ident "staticVal2"
StaticExpr Call
Par Ident "static"
StrLit "str" StrLit "str"
Empty Empty
IdentDefs IdentDefs
Ident "staticVal3" Ident "staticVal3"
StaticExpr Command
Ident "static"
StrLit "str" StrLit "str"
Empty Empty
IdentDefs
Ident "staticVal4"
CallStrLit
Ident "static"
RStrLit "str"
Empty
IdentDefs IdentDefs
Ident "staticDotVal" Ident "staticDotVal"
DotExpr DotExpr
@ -285,50 +349,32 @@ StmtList
StmtList StmtList
Asgn Asgn
Ident "staticTen" Ident "staticTen"
StaticExpr Command
Ident "static"
IntLit 10 IntLit 10
Asgn Asgn
Ident "staticA" Ident "staticA"
StaticExpr Call
Par Ident "static"
Ident "a" Ident "a"
Asgn
Ident "staticAspace"
StaticExpr
Par
Ident "a"
Asgn
Ident "staticAtuple"
StaticExpr
TupleConstr
Ident "a"
Asgn
Ident "staticTuple"
StaticExpr
Par
Ident "a"
Ident "b"
Asgn
Ident "staticTypeTuple"
StaticExpr
Par
Ident "int"
Ident "string"
Asgn Asgn
Ident "staticCall" Ident "staticCall"
StaticExpr Command
Ident "static"
Call Call
Ident "foo" Ident "foo"
IntLit 1 IntLit 1
Asgn Asgn
Ident "staticStrCall" Ident "staticStrCall"
StaticExpr Command
Ident "static"
CallStrLit CallStrLit
Ident "foo" Ident "foo"
RStrLit "x" RStrLit "x"
Asgn Asgn
Ident "staticChainCall" Ident "staticChainCall"
StaticExpr Command
Ident "static"
Command Command
Ident "foo" Ident "foo"
Ident "bar" Ident "bar"
@ -399,7 +445,7 @@ dumpTree:
RefTupleCl = ref tuple RefTupleCl = ref tuple
RefTupleType = ref (int, string) RefTupleType = ref (int, string)
RefTupleVars = ref (a, b) RefTupleVars = ref (a, b)
# BareStatic = static # Error: invalid indentation BareStatic = static # Used to be Error: invalid indentation
GenericStatic = static[int] GenericStatic = static[int]
PrefixStatic = static int PrefixStatic = static int
StaticTupleCl = static tuple StaticTupleCl = static tuple
@ -407,16 +453,16 @@ dumpTree:
BareType = type BareType = type
GenericType = type[float] GenericType = type[float]
TypeTupleGen = type[tuple] TypeTupleGen = type[tuple]
# TypeTupleCl = type tuple # Error: invalid indentation TypeTupleCl = type tuple # Used to be Error: invalid indentation
TypeInstance = type Foo[ref] TypeInstance = type Foo[ref]
bareTypeDesc = typedesc bareTypeDesc = typedesc
TypeOfVar = type(a) TypeOfVar = type(a)
# TypeOfVarAlt= type (a) # Error: invalid indentation TypeOfVarAlt = type (a) # Used to be Error: invalid indentation
TypeOfTuple1 = type(a,) TypeOfTuple1 = type(a,)
TypeOfTuple2 = type(a,b) TypeOfTuple2 = type(a,b)
# TypeOfTuple1A = type (a,) # Error: invalid indentation TypeOfTuple1A = type (a,) # Used to be Error: invalid indentation
# TypeOfTuple2A = type (a,b) # Error: invalid indentation TypeOfTuple2A = type (a,b) # Used to be Error: invalid indentation
# TypeTuple = type (int, string) # Error: invalid indentation TypeTuple = type (int, string) # Used to be Error: invalid indentation
GenericTypedesc = typedesc[int] GenericTypedesc = typedesc[int]
T = type T = type
@ -427,14 +473,14 @@ dumpTree:
typeIntAlt : type(int), typeIntAlt : type(int),
typeOfVar : type(a), typeOfVar : type(a),
typeDotType : foo.type, typeDotType : foo.type,
# typeTupleCl : type tuple, # Error: ')' expected typeTupleCl : type tuple, # Used to be Error: ')' expected
# bareStatic : static, # Error: expression expected, but found ',' bareStatic : static, # Used to be Error: expression expected, but found ','
genStatic : static[int], genStatic : static[int],
staticInt : static int, staticInt : static int,
staticVal1 : static 10, staticVal1 : static 10,
staticVal2 : static("str"), staticVal2 : static("str"),
staticVal3 : static "str", staticVal3 : static "str",
# staticVal4 : static"str", # Error: expression expected, but found 'str' staticVal4 : static"str", # Used to be Error: expression expected, but found 'str'
staticDotVal : 10.static, staticDotVal : 10.static,
bareRef : ref, bareRef : ref,
refTuple1 : ref (int), refTuple1 : ref (int),
@ -451,10 +497,10 @@ dumpTree:
): type = ): type =
staticTen = static 10 staticTen = static 10
staticA = static(a) staticA = static(a)
staticAspace = static (a) # staticAspace = static (a) # With newTypedesc: Error: invalid indentation
staticAtuple = static (a,) # staticAtuple = static (a,) # With newTypedesc: Error: invalid indentation
staticTuple = static (a,b) # staticTuple = static (a,b) # With newTypedesc: Error: invalid indentation
staticTypeTuple = static (int,string) # staticTypeTuple = static (int,string) # With newTypedesc: Error: invalid indentation
staticCall = static foo(1) staticCall = static foo(1)
staticStrCall = static foo"x" staticStrCall = static foo"x"
staticChainCall = static foo bar staticChainCall = static foo bar