mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
@@ -143,7 +143,7 @@ type
|
||||
nkPragma, # a pragma statement
|
||||
nkPragmaBlock, # a pragma with a block
|
||||
nkIfStmt, # an if statement
|
||||
nkWhenStmt, # a when statement
|
||||
nkWhenStmt, # a when expression or statement
|
||||
nkForStmt, # a for statement
|
||||
nkWhileStmt, # a while statement
|
||||
nkCaseStmt, # a case statement
|
||||
@@ -243,8 +243,18 @@ const
|
||||
sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
|
||||
sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
|
||||
sfNoInit* = sfMainModule # don't generate code to init the variable
|
||||
|
||||
sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded
|
||||
# without considering any possible overloads
|
||||
|
||||
sfAnon* = sfCompilerProc # symbol name that was generated by the compiler
|
||||
# the compiler will avoid printing such names
|
||||
# in user messages.
|
||||
|
||||
const
|
||||
# getting ready for the future expr/stmt merge
|
||||
nkWhen* = nkWhenStmt
|
||||
nkWhenExpr* = nkWhenStmt
|
||||
|
||||
type
|
||||
TTypeKind* = enum # order is important!
|
||||
@@ -353,7 +363,8 @@ const
|
||||
|
||||
type
|
||||
TMagic* = enum # symbols that require compiler magic:
|
||||
mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||
mNone,
|
||||
mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf,
|
||||
mEcho, mShallowCopy, mSlurp,
|
||||
mParseExprToAst, mParseStmtToAst, mExpandToAst,
|
||||
mUnaryLt, mSucc,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# included from cgen.nim
|
||||
|
||||
const
|
||||
RangeExpandLimit = 256 # do not generate ranges
|
||||
# over 'RangeExpandLimit' elements
|
||||
@@ -48,16 +50,20 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||
proc genSingleVar(p: BProc, a: PNode) =
|
||||
var v = a.sons[0].sym
|
||||
if sfCompileTime in v.flags: return
|
||||
var targetProc = p
|
||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||
if sfGlobal in v.flags:
|
||||
assignGlobalVar(p, v)
|
||||
genObjectInit(p, cpsInit, v.typ, v.loc, true)
|
||||
if v.owner.kind != skModule:
|
||||
targetProc = p.module.preInitProc
|
||||
assignGlobalVar(targetProc, v)
|
||||
genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
|
||||
else:
|
||||
assignLocalVar(p, v)
|
||||
initLocalVar(p, v, immediateAsgn)
|
||||
|
||||
if immediateAsgn:
|
||||
genLineDir(p, a)
|
||||
loadInto(p, a.sons[0], a.sons[2], v.loc)
|
||||
genLineDir(targetProc, a)
|
||||
loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
|
||||
|
||||
proc genClosureVar(p: BProc, a: PNode) =
|
||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||
|
||||
@@ -859,6 +859,7 @@ proc genInitCode(m: BModule) =
|
||||
|
||||
app(prc, genSectionStart(cpsLocals))
|
||||
app(prc, m.initProc.s[cpsLocals])
|
||||
app(prc, m.preInitProc.s[cpsLocals])
|
||||
app(prc, genSectionEnd(cpsLocals))
|
||||
|
||||
app(prc, genSectionStart(cfsTypeInit1))
|
||||
@@ -875,10 +876,12 @@ proc genInitCode(m: BModule) =
|
||||
app(prc, genSectionEnd(i))
|
||||
|
||||
app(prc, genSectionStart(cpsInit))
|
||||
app(prc, m.preInitProc.s[cpsInit])
|
||||
app(prc, m.initProc.s[cpsInit])
|
||||
app(prc, genSectionEnd(cpsInit))
|
||||
|
||||
app(prc, genSectionStart(cpsStmts))
|
||||
app(prc, genSectionStart(cpsStmts))
|
||||
app(prc, m.preInitProc.s[cpsStmts])
|
||||
app(prc, m.initProc.s[cpsStmts])
|
||||
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||
app(prc, deinitFrame(m.initProc))
|
||||
@@ -916,6 +919,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
result.typeInfoMarker = initIntSet()
|
||||
result.initProc = newProc(nil, result)
|
||||
result.initProc.options = gOptions
|
||||
result.preInitProc = newProc(nil, result)
|
||||
initNodeTable(result.dataCache)
|
||||
result.typeStack = @[]
|
||||
result.forwardedProcs = @[]
|
||||
|
||||
@@ -93,6 +93,10 @@ type
|
||||
headerFiles*: TLinkedList # needed headers to include
|
||||
typeInfoMarker*: TIntSet # needed for generating type information
|
||||
initProc*: BProc # code for init procedure
|
||||
preInitProc*: BProc # code executed before the init proc
|
||||
# used for initialization code for
|
||||
# .global. variables
|
||||
# (or instantiated generic variables)
|
||||
typeStack*: TTypeSeq # used for type generation
|
||||
dataCache*: TNodeTable
|
||||
forwardedProcs*: TSymSeq # keep forwarded procs here
|
||||
|
||||
@@ -490,7 +490,7 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode =
|
||||
proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
var s = n.sym
|
||||
case s.kind
|
||||
of skProc, skConverter, skMacro:
|
||||
of skProc, skConverter, skMacro, skType:
|
||||
result = n
|
||||
#result = s.getBody
|
||||
of skVar, skLet, skForVar, skTemp, skResult:
|
||||
@@ -891,7 +891,24 @@ proc evalTemplate*(n: PNode, sym: PSym): PNode =
|
||||
result = evalTemplateAux(sym.getBody, args, sym)
|
||||
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
proc evalTypeTrait*(n: PNode, context: PSym): PNode =
|
||||
## XXX: This should be pretty much guaranteed to be true
|
||||
# by the type traits procs' signitures, but until the
|
||||
# code is more mature it doesn't hurt to be extra safe
|
||||
internalAssert n.sons.len >= 2 and
|
||||
n.sons[1].sym.typ.kind == tyTypeDesc
|
||||
|
||||
let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc})
|
||||
case n.sons[0].sym.name.s
|
||||
of "name":
|
||||
result = newStrNode(nkStrLit, typ.typeToString)
|
||||
result.typ = newType(tyString, context)
|
||||
result.info = n.info
|
||||
|
||||
else:
|
||||
internalAssert false
|
||||
|
||||
proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
||||
var
|
||||
n = original.copyTree
|
||||
@@ -941,6 +958,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
of mParseExprToAst: result = evalParseExpr(c, n)
|
||||
of mParseStmtToAst: result = evalParseStmt(c, n)
|
||||
of mExpandToAst: result = evalExpandToAst(c, n)
|
||||
of mTypeTrait: result = evalTypeTrait(n, c.module)
|
||||
of mNLen:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
|
||||
@@ -72,7 +72,7 @@ type
|
||||
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
|
||||
errInvalidParamKindX, errDefaultArgumentInvalid, errNamedParamHasToBeIdent,
|
||||
errNoReturnTypeForX, errConvNeedsOneArg, errInvalidPragmaX,
|
||||
errXNotAllowedHere, errInvalidControlFlowX, errATypeHasNoValue,
|
||||
errXNotAllowedHere, errInvalidControlFlowX,
|
||||
errXisNoType, errCircumNeedsPointer, errInvalidExpression,
|
||||
errInvalidExpressionX, errEnumHasNoValueX, errNamedExprExpected,
|
||||
errNamedExprNotAllowed, errXExpectsOneTypeParam,
|
||||
@@ -275,7 +275,6 @@ const
|
||||
errInvalidPragmaX: "invalid pragma: $1",
|
||||
errXNotAllowedHere: "$1 not allowed here",
|
||||
errInvalidControlFlowX: "invalid control flow: $1",
|
||||
errATypeHasNoValue: "a type has no value",
|
||||
errXisNoType: "invalid type: \'$1\'",
|
||||
errCircumNeedsPointer: "'[]' needs a pointer or reference type",
|
||||
errInvalidExpression: "invalid expression",
|
||||
@@ -667,3 +666,6 @@ template AssertNotNil*(e: expr): expr =
|
||||
if(e == nil): InternalError($InstantiationInfo())
|
||||
e
|
||||
|
||||
template InternalAssert*(e: bool): stmt =
|
||||
if not e: InternalError($InstantiationInfo())
|
||||
|
||||
|
||||
@@ -221,4 +221,4 @@ proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||
|
||||
# Can we keep this? I'm using it all the time
|
||||
template nimdbg*: expr = c.filename.endsWith"nimdbg.nim"
|
||||
|
||||
template cnimdbg*: expr = p.module.filename.endsWith"nimdbg.nim"
|
||||
|
||||
@@ -264,16 +264,26 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
||||
optInd(p, a)
|
||||
eat(p, endTok)
|
||||
|
||||
proc newDotExpr(p: var TParser, a: PNode): PNode =
|
||||
proc dotExpr(p: var TParser, a: PNode): PNode =
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
result = newNodeI(nkDotExpr, a.info)
|
||||
addSon(result, a)
|
||||
addSon(result, parseSymbol(p))
|
||||
case p.tok.tokType
|
||||
of tkType:
|
||||
result = newNodeP(nkTypeOfExpr, p)
|
||||
getTok(p)
|
||||
addSon(result, a)
|
||||
of tkAddr:
|
||||
result = newNodeP(nkAddr, p)
|
||||
getTok(p)
|
||||
addSon(result, a)
|
||||
else:
|
||||
result = newNodeI(nkDotExpr, a.info)
|
||||
addSon(result, a)
|
||||
addSon(result, parseSymbol(p))
|
||||
|
||||
proc qualifiedIdent(p: var TParser): PNode =
|
||||
result = parseSymbol(p) #optInd(p, result);
|
||||
if p.tok.tokType == tkDot: result = newDotExpr(p, result)
|
||||
if p.tok.tokType == tkDot: result = dotExpr(p, result)
|
||||
|
||||
proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||
getTok(p)
|
||||
@@ -477,7 +487,7 @@ proc primary(p: var TParser): PNode =
|
||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
||||
parseDoBlocks(p, result)
|
||||
of tkDot:
|
||||
result = newDotExpr(p, result)
|
||||
result = dotExpr(p, result)
|
||||
result = parseGStrLit(p, result)
|
||||
of tkBracketLe:
|
||||
result = indexExprList(p, result, nkBracketExpr, tkBracketRi)
|
||||
@@ -506,8 +516,8 @@ proc lowestExprAux(p: var TParser, limit: int): PNode =
|
||||
proc lowestExpr(p: var TParser): PNode =
|
||||
result = lowestExprAux(p, -1)
|
||||
|
||||
proc parseIfExpr(p: var TParser): PNode =
|
||||
result = newNodeP(nkIfExpr, p)
|
||||
proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
while true:
|
||||
getTok(p) # skip `if`, `elif`
|
||||
var branch = newNodeP(nkElifExpr, p)
|
||||
@@ -707,7 +717,8 @@ proc parseExpr(p: var TParser): PNode =
|
||||
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
|
||||
of tkTuple: result = parseTuple(p)
|
||||
of tkProc: result = parseProcExpr(p, true)
|
||||
of tkIf: result = parseIfExpr(p)
|
||||
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
||||
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
||||
else: result = lowestExpr(p)
|
||||
|
||||
proc parseTypeDesc(p: var TParser): PNode =
|
||||
@@ -718,7 +729,7 @@ proc isExprStart(p: TParser): bool =
|
||||
case p.tok.tokType
|
||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkBind,
|
||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
||||
tkTuple, tkType:
|
||||
tkTuple, tkType, tkWhen:
|
||||
result = true
|
||||
else: result = false
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ const
|
||||
wImportcpp, wImportobjc, wError}
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
|
||||
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime}
|
||||
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal}
|
||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||
wExtern, wImportcpp, wImportobjc, wError}
|
||||
letPragmas* = varPragmas
|
||||
@@ -494,6 +494,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
noVal(it)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
incl(sym.loc.Flags, lfNoDecl)
|
||||
of wGlobal:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfGlobal)
|
||||
of wMerge:
|
||||
noval(it)
|
||||
incl(sym.flags, sfMerge)
|
||||
|
||||
@@ -349,7 +349,8 @@ proc lsub(n: PNode): int =
|
||||
of nkBind: result = lsons(n) + len("bind_")
|
||||
of nkBindStmt: result = lcomma(n) + len("bind_")
|
||||
of nkCheckedFieldExpr: result = lsub(n.sons[0])
|
||||
of nkLambda, nkDo: result = lsons(n) + len("lambda__=_") # XXX: render nkDo
|
||||
of nkLambda: result = lsons(n) + len("proc__=_")
|
||||
of nkDo: result = lsons(n) + len("do__:_")
|
||||
of nkConstDef, nkIdentDefs:
|
||||
result = lcomma(n, 0, - 3)
|
||||
var L = sonsLen(n)
|
||||
@@ -677,7 +678,17 @@ proc gident(g: var TSrcGen, n: PNode) =
|
||||
t = tkOpr
|
||||
put(g, t, s)
|
||||
if n.kind == nkSym and renderIds in g.flags: put(g, tkIntLit, $n.sym.id)
|
||||
|
||||
proc doParamsAux(g: var TSrcGen, params: PNode) =
|
||||
if params.len > 1:
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, params, 1)
|
||||
put(g, tkParRi, ")")
|
||||
|
||||
if params.sons[0].kind != nkEmpty:
|
||||
putWithSpace(g, tkOpr, "->")
|
||||
gsub(g, params.sons[0])
|
||||
|
||||
proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
if isNil(n): return
|
||||
var
|
||||
@@ -804,14 +815,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
gsub(g, n.sons[0])
|
||||
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
|
||||
gsub(g, n.sons[0])
|
||||
of nkLambda, nkDo: # XXX: nkDo is rendered as regular lambda
|
||||
assert(n.sons[genericParamsPos].kind == nkEmpty)
|
||||
putWithSpace(g, tkLambda, "lambda")
|
||||
of nkLambda:
|
||||
putWithSpace(g, tkLambda, "proc")
|
||||
gsub(g, n.sons[paramsPos])
|
||||
gsub(g, n.sons[pragmasPos])
|
||||
put(g, tkSpaces, Space)
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
gsub(g, n.sons[bodyPos])
|
||||
of nkDo:
|
||||
putWithSpace(g, tkDo, "do")
|
||||
doParamsAux(g, n.sons[paramsPos])
|
||||
gsub(g, n.sons[pragmasPos])
|
||||
put(g, tkColon, ":")
|
||||
gsub(g, n.sons[bodyPos])
|
||||
of nkConstDef, nkIdentDefs:
|
||||
gcomma(g, n, 0, - 3)
|
||||
var L = sonsLen(n)
|
||||
@@ -960,7 +976,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
of nkIfStmt:
|
||||
putWithSpace(g, tkIf, "if")
|
||||
gif(g, n)
|
||||
of nkWhenStmt, nkRecWhen:
|
||||
of nkWhen, nkRecWhen:
|
||||
putWithSpace(g, tkWhen, "when")
|
||||
gif(g, n)
|
||||
of nkWhileStmt: gwhile(g, n)
|
||||
|
||||
@@ -21,7 +21,7 @@ proc semPass*(): TPass
|
||||
|
||||
type
|
||||
TExprFlag = enum
|
||||
efAllowType, efLValue, efWantIterator, efInTypeof
|
||||
efLValue, efWantIterator, efInTypeof
|
||||
TExprFlags = set[TExprFlag]
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
|
||||
@@ -10,7 +10,16 @@
|
||||
# this module does the semantic checking for expressions
|
||||
# included from sem.nim
|
||||
|
||||
proc semExprOrTypedesc(c: PContext, n: PNode): PNode
|
||||
proc restoreOldStyleType(n: PNode) =
|
||||
# XXX: semExprWithType used to return the same type
|
||||
# for nodes such as (100) or (int).
|
||||
# This is inappropriate. The type of the first expression
|
||||
# should be "int", while the type of the second one should
|
||||
# be typedesc(int).
|
||||
#
|
||||
# This is strictly for backward compatibility until
|
||||
# the transition to types as first-class values is complete.
|
||||
n.typ = n.typ.skipTypes({tyTypeDesc})
|
||||
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||
markUsed(n, s)
|
||||
@@ -108,10 +117,9 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
if s.ast == nil: InternalError(n.info, "no default for")
|
||||
result = semExpr(c, s.ast)
|
||||
of skType:
|
||||
if efAllowType notin flags:
|
||||
GlobalError(n.info, errATypeHasNoValue)
|
||||
markUsed(n, s)
|
||||
result = newSymNode(s, n.info)
|
||||
result.typ = makeTypeDesc(c, s.typ)
|
||||
else:
|
||||
markUsed(n, s)
|
||||
result = newSymNode(s, n.info)
|
||||
@@ -206,7 +214,8 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
if sonsLen(n) != 2:
|
||||
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
restoreOldStyleType(n.sons[1])
|
||||
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
case typ.Kind
|
||||
of tySequence, tyString, tyOpenArray:
|
||||
@@ -219,15 +228,21 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
result = n
|
||||
|
||||
proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) != 2: GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||
else: n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
if sonsLen(n) != 2:
|
||||
GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
restoreOldStyleType(n.sons[1])
|
||||
|
||||
n.typ = getSysType(tyInt)
|
||||
result = n
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efAllowType})
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2])
|
||||
restoreOldStyleType(n.sons[1])
|
||||
restoreOldStyleType(n.sons[2])
|
||||
var a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
var b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
if b.kind != tyObject or a.kind != tyObject:
|
||||
@@ -251,31 +266,16 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
GlobalError(n.info, errXExpectsTwoArguments, "is")
|
||||
|
||||
proc semExprOrTypedesc(c: PContext, n: PNode): PNode =
|
||||
# XXX: Currently, semExprWithType will return the same type
|
||||
# for nodes such as (100) or (int).
|
||||
# This is inappropriate. The type of the first expression
|
||||
# should be "int", while the type of the second one should
|
||||
# be typeDesc(int).
|
||||
# Ideally, this should be fixed in semExpr, but right now
|
||||
# there are probably users that depend on the present behavior.
|
||||
# XXX: Investigate current uses of efAllowType and fix them to
|
||||
# work with tyTypeDesc.
|
||||
result = semExprWithType(c, n, {efAllowType})
|
||||
if result.kind == nkSym and result.sym.kind == skType and
|
||||
result.typ.kind != tyTypeDesc:
|
||||
result.typ = makeTypeDesc(c, result.typ)
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||
var info = a.sons[0].info
|
||||
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
|
||||
a.sons[1] = semExprOrTypedesc(c, a.sons[1])
|
||||
a.sons[1] = semExprWithType(c, a.sons[1])
|
||||
a.typ = a.sons[1].typ
|
||||
else:
|
||||
n.sons[i] = semExprOrTypedesc(c, a)
|
||||
n.sons[i] = semExprWithType(c, a)
|
||||
|
||||
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||
# quick check if there is *any* () operator overloaded:
|
||||
@@ -409,8 +409,10 @@ proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||
of nkSym:
|
||||
# don't list 'skLet' here:
|
||||
if n.sym.kind in {skVar, skResult, skTemp}:
|
||||
if c.p.owner.id == n.sym.owner.id: result = arLocalLValue
|
||||
else: result = arLValue
|
||||
if c.p.owner.id == n.sym.owner.id and sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
else:
|
||||
result = arLValue
|
||||
of nkDotExpr:
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
@@ -752,13 +754,15 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
return semSym(c, n, s, flags)
|
||||
|
||||
checkSonsLen(n, 2)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0], {efAllowType} + flags)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0], flags)
|
||||
restoreOldStyleType(n.sons[0])
|
||||
var i = considerAcc(n.sons[1])
|
||||
var ty = n.sons[0].Typ
|
||||
var ty = n.sons[0].typ
|
||||
var f: PSym = nil
|
||||
result = nil
|
||||
if isTypeExpr(n.sons[0]):
|
||||
if ty.kind == tyEnum:
|
||||
case ty.kind
|
||||
of tyEnum:
|
||||
# look up if the identifier belongs to the enum:
|
||||
while ty != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
@@ -769,10 +773,22 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.info = n.info
|
||||
result.typ = ty
|
||||
markUsed(n, f)
|
||||
return
|
||||
elif efAllowType notin flags:
|
||||
GlobalError(n.sons[0].info, errATypeHasNoValue)
|
||||
return
|
||||
of tyGenericInst:
|
||||
assert ty.sons[0].kind == tyGenericBody
|
||||
let tbody = ty.sons[0]
|
||||
for s in countup(0, tbody.len-2):
|
||||
let tParam = tbody.sons[s]
|
||||
assert tParam.kind == tyGenericParam
|
||||
if tParam.sym.name == i:
|
||||
let foundTyp = makeTypeDesc(c, ty.sons[s + 1])
|
||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), n.info)
|
||||
return
|
||||
else:
|
||||
# echo "TYPE FIELD ACCESS"
|
||||
# debug ty
|
||||
return
|
||||
# XXX: This is probably not relevant any more
|
||||
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
||||
ty = n.sons[0].Typ
|
||||
|
||||
@@ -852,14 +868,14 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.add(x[0])
|
||||
return
|
||||
checkMinSonsLen(n, 2)
|
||||
n.sons[0] = semExprOrTypedesc(c, n.sons[0])
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||
case arr.kind
|
||||
of tyArray, tyOpenArray, tyArrayConstr, tySequence, tyString, tyCString:
|
||||
checkSonsLen(n, 2)
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i], flags - {efAllowType})
|
||||
n.sons[i] = semExprWithType(c, n.sons[i], flags)
|
||||
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||
if arg != nil:
|
||||
@@ -1280,9 +1296,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
nil
|
||||
of nkNilLit:
|
||||
result.typ = getSysType(tyNil)
|
||||
of nkType:
|
||||
if not (efAllowType in flags): GlobalError(n.info, errATypeHasNoValue)
|
||||
n.typ = semTypeNode(c, n, nil)
|
||||
of nkIntLit:
|
||||
if result.typ == nil: result.typ = getSysType(tyInt)
|
||||
of nkInt8Lit:
|
||||
@@ -1312,11 +1325,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
Message(n.info, warnDeprecated, "bind")
|
||||
result = semExpr(c, n.sons[0], flags)
|
||||
of nkTypeOfExpr:
|
||||
var typ = semTypeNode(c, n, nil)
|
||||
if typ.sym == nil:
|
||||
typ = copyType(typ, typ.owner, true)
|
||||
typ.linkTo(newSym(skType, getIdent"typedesc", typ.owner))
|
||||
result = newSymNode(typ.sym, n.info)
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
typ = makeTypedesc(c, typ)
|
||||
var sym = newSym(skType, getIdent"TypeOfExpr", typ.owner).linkTo(typ)
|
||||
sym.flags.incl(sfAnon)
|
||||
result = newSymNode(sym, n.info)
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
# check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1)
|
||||
@@ -1354,6 +1367,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semIndirectOp(c, n, flags)
|
||||
of nkMacroStmt:
|
||||
result = semMacroStmt(c, n)
|
||||
of nkWhenExpr:
|
||||
result = semWhen(c, n, false)
|
||||
result = semExpr(c, result)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1)
|
||||
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
|
||||
|
||||
@@ -206,7 +206,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
of mNewString, mNewStringOfCap,
|
||||
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
|
||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||
mParseExprToAst, mParseStmtToAst, mExpandToAst,
|
||||
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait,
|
||||
mNLen..mNError, mEqRef:
|
||||
nil
|
||||
of mRand:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#
|
||||
|
||||
# This include file implements the semantic checking for magics.
|
||||
# included from sem.nim
|
||||
|
||||
proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var r = isPartOf(n[1], n[2])
|
||||
@@ -43,11 +44,21 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
||||
result.add(filename)
|
||||
result.add(line)
|
||||
|
||||
proc semTypeTraits(c: PContext, n: PNode): PNode =
|
||||
checkMinSonsLen(n, 2)
|
||||
internalAssert n.sons[1].kind == nkSym
|
||||
if n.sons[1].sym.kind == skType:
|
||||
result = evalTypeTrait(n, GetCurrOwner())
|
||||
else:
|
||||
# pass unmodified to evals
|
||||
result = n
|
||||
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
case n[0].sym.magic
|
||||
of mSlurp: result = semSlurp(c, n, flags)
|
||||
of mIsPartOf: result = semIsPartOf(c, n, flags)
|
||||
of mTypeTrait: result = semTypeTraits(c, n)
|
||||
of mAstToStr:
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
||||
result.typ = getSysType(tyString)
|
||||
|
||||
@@ -25,13 +25,13 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
of nkElifBranch, nkElifExpr:
|
||||
checkSonsLen(it, 2)
|
||||
var e = semAndEvalConstExpr(c, it.sons[0])
|
||||
if e.kind != nkIntLit: InternalError(n.info, "semWhen")
|
||||
if e.intVal != 0 and result == nil:
|
||||
setResult(it.sons[1])
|
||||
of nkElse:
|
||||
of nkElse, nkElseExpr:
|
||||
checkSonsLen(it, 1)
|
||||
if result == nil:
|
||||
setResult(it.sons[0])
|
||||
|
||||
@@ -181,7 +181,12 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
if result != nil:
|
||||
markUsed(n, result)
|
||||
if result.kind == skParam and result.typ.kind == tyTypeDesc:
|
||||
return result.typ.sons[0].sym
|
||||
# This is a typedesc param. is it already bound?
|
||||
# it's not bound when it's also used as return type for example
|
||||
if result.typ.sonsLen > 0:
|
||||
return result.typ.sons[0].sym
|
||||
else:
|
||||
return result.typ.sym
|
||||
if result.kind != skType: GlobalError(n.info, errTypeExpected)
|
||||
if result.typ.kind != tyGenericParam:
|
||||
# XXX get rid of this hack!
|
||||
@@ -583,8 +588,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
break addImplicitGeneric
|
||||
|
||||
var s = newSym(skType, paramTypId, getCurrOwner())
|
||||
s.typ = typeClass
|
||||
s.typ.sym = s
|
||||
s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
endingType = typeClass
|
||||
|
||||
@@ -372,6 +372,13 @@ proc rangeToStr(n: PNode): string =
|
||||
assert(n.kind == nkRange)
|
||||
result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
|
||||
|
||||
proc constraintsToStr(t: PType): string =
|
||||
let sep = if tfAny in t.flags: " or " else: " and "
|
||||
result = ""
|
||||
for i in countup(0, t.sons.len - 1):
|
||||
if i > 0: result.add(sep)
|
||||
result.add(t.sons[i].typeToString)
|
||||
|
||||
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
const
|
||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||
@@ -387,7 +394,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
var t = typ
|
||||
result = ""
|
||||
if t == nil: return
|
||||
if prefer == preferName and t.sym != nil:
|
||||
if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags:
|
||||
return t.sym.Name.s
|
||||
case t.Kind
|
||||
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
||||
@@ -396,6 +403,14 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
if i > 1: add(result, ", ")
|
||||
add(result, typeToString(t.sons[i]))
|
||||
add(result, ']')
|
||||
of tyTypeDesc:
|
||||
if t.sons.len == 0: result = "typedesc"
|
||||
else: result = "typedesc{" & constraintsToStr(t) & "}"
|
||||
of tyTypeClass:
|
||||
result = constraintsToStr(t)
|
||||
of tyExpr:
|
||||
if t.sons.len == 0: result = "expr"
|
||||
else: result = "expr{" & constraintsToStr(t) & "}"
|
||||
of tyArray:
|
||||
if t.sons[0].kind == tyRange:
|
||||
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
||||
|
||||
@@ -58,7 +58,7 @@ type
|
||||
wWatchPoint, wSubsChar,
|
||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wNoStackFrame,
|
||||
wImplicitStatic
|
||||
wImplicitStatic, wGlobal
|
||||
|
||||
TSpecialWords* = set[TSpecialWord]
|
||||
|
||||
@@ -107,7 +107,7 @@ const
|
||||
"watchpoint",
|
||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||
"nostackframe", "implicitstatic"]
|
||||
"nostackframe", "implicitstatic", "global"]
|
||||
|
||||
proc findStr*(a: openarray[string], s: string): int =
|
||||
for i in countup(low(a), high(a)):
|
||||
|
||||
@@ -3267,7 +3267,7 @@ but are used to override the settings temporarily. Example:
|
||||
{.pop.} # restore old settings
|
||||
|
||||
|
||||
Register pragma
|
||||
register pragma
|
||||
---------------
|
||||
The `register`:idx: pragma is for variables only. It declares the variable as
|
||||
``register``, giving the compiler a hint that the variable should be placed
|
||||
@@ -3277,6 +3277,22 @@ though and for good reasons: Often they do a better job without it anyway.
|
||||
In highly specific cases (a dispatch loop of an bytecode interpreter for
|
||||
example) it may provide benefits, though.
|
||||
|
||||
global pragma
|
||||
---------------
|
||||
The `global`:idx pragma can be applied to a variable within a proc to instruct
|
||||
the compiler to store it in a global location and initialize it once at program
|
||||
startup.
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isHexNumber(s: string): bool =
|
||||
var pattern {.global.} = re"[0-9a-fA-F]+"
|
||||
result = s.match(pattern)
|
||||
|
||||
When used within a generic proc, a separate unique global variable will be
|
||||
created for each instantiation of the proc. The order of initialization of
|
||||
the created global variables within a module is not defined, but all of them
|
||||
will be initialized after any top-level variables in their originating module
|
||||
and before any variable in a module that imports it.
|
||||
|
||||
DeadCodeElim pragma
|
||||
-------------------
|
||||
|
||||
15
lib/pure/typetraits.nim
Normal file
15
lib/pure/typetraits.nim
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Nimrod Contributors
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module defines compile-time reflection procs for
|
||||
## working with types
|
||||
|
||||
proc name*(t: typedesc): string {.magic: "TypeTrait".}
|
||||
## Returns the name of the given type
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
discard """
|
||||
file: "ttypenoval.nim"
|
||||
line: 38
|
||||
errormsg: "a type has no value"
|
||||
errormsg: "type mismatch: got (typedesc{int}) but expected 'int'"
|
||||
"""
|
||||
|
||||
# A min-heap.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
discard """
|
||||
disabled: true
|
||||
output: '''derived class
|
||||
base class
|
||||
'''
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
discard """
|
||||
disabled: true
|
||||
output: '''derived class 2
|
||||
base class
|
||||
'''
|
||||
|
||||
15
tests/run/globalaux.nim
Normal file
15
tests/run/globalaux.nim
Normal file
@@ -0,0 +1,15 @@
|
||||
type
|
||||
TObj*[T] = object
|
||||
val*: T
|
||||
|
||||
var
|
||||
totalGlobals* = 0
|
||||
|
||||
proc makeObj[T](x: T): TObj[T] =
|
||||
totalGlobals += 1
|
||||
result.val = x
|
||||
|
||||
proc globalInstance*[T]: var TObj[T] =
|
||||
var g {.global.} = when T is int: makeObj(10) else: makeObj("hello")
|
||||
result = g
|
||||
|
||||
4
tests/run/globalaux2.nim
Normal file
4
tests/run/globalaux2.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
import globalaux
|
||||
|
||||
echo "in globalaux2: ", globalInstance[int]().val
|
||||
|
||||
14
tests/run/tenumitems.nim
Normal file
14
tests/run/tenumitems.nim
Normal file
@@ -0,0 +1,14 @@
|
||||
discard """
|
||||
output: "A\nB\nC"
|
||||
"""
|
||||
|
||||
type TAlphabet = enum
|
||||
A, B, C
|
||||
|
||||
iterator items(E: typedesc): E =
|
||||
for v in low(E)..high(E):
|
||||
yield v
|
||||
|
||||
for c in TAlphabet:
|
||||
echo($c)
|
||||
|
||||
16
tests/run/tglobal.nim
Normal file
16
tests/run/tglobal.nim
Normal file
@@ -0,0 +1,16 @@
|
||||
discard """
|
||||
file: "toop1.nim"
|
||||
output: "in globalaux2: 10\ntotal globals: 2\nint value: 100\nstring value: second"
|
||||
"""
|
||||
|
||||
import globalaux, globalaux2
|
||||
|
||||
echo "total globals: ", totalGlobals
|
||||
|
||||
globalInstance[int]().val = 100
|
||||
echo "int value: ", globalInstance[int]().val
|
||||
|
||||
globalInstance[string]().val = "first"
|
||||
globalInstance[string]().val = "second"
|
||||
echo "string value: ", globalInstance[string]().val
|
||||
|
||||
24
tests/run/ttypetraits.nim
Normal file
24
tests/run/ttypetraits.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
discard """
|
||||
msg: "int\nstring\nTBar[int]"
|
||||
output: "int\nstring\nTBar[int]"
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
proc foo(x) =
|
||||
static:
|
||||
var t = type(x)
|
||||
echo t.name
|
||||
|
||||
echo x.type.name
|
||||
|
||||
type
|
||||
TBar[U] = object
|
||||
x: U
|
||||
|
||||
var bar: TBar[int]
|
||||
|
||||
foo 10
|
||||
foo "test"
|
||||
foo bar
|
||||
|
||||
@@ -22,7 +22,8 @@ proc delNimCache() =
|
||||
except EOS:
|
||||
echo "[Warning] could not delete: ", dir
|
||||
|
||||
proc plusCache(options: string): string = return options & " --symbolFiles:on"
|
||||
proc plusCache(options: string): string = return options &
|
||||
" --symbolFiles:on --nimcache:./nimcache"
|
||||
|
||||
proc runRodFiles(r: var TResults, options: string) =
|
||||
template test(filename: expr): stmt =
|
||||
|
||||
@@ -3,9 +3,30 @@
|
||||
# result = "#! /bin/sh\n# Generated from niminst\n" &
|
||||
# "# Template is in tools/buildsh.tmpl\n" &
|
||||
# "# To regenerate run ``niminst csource`` or ``koch csource``\n"
|
||||
while :
|
||||
do
|
||||
case "$1" in
|
||||
--extraBuildArgs)
|
||||
extraBuildArgs=" $2"
|
||||
shift 2
|
||||
;;
|
||||
--) # End of all options
|
||||
shift
|
||||
break;
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*) # No more options
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
CC="gcc"
|
||||
LINKER="gcc"
|
||||
COMP_FLAGS="?{c.ccompiler.flags}"
|
||||
COMP_FLAGS="?{c.ccompiler.flags}$extraBuildArgs"
|
||||
LINK_FLAGS="?{c.linker.flags}"
|
||||
# add(result, "# platform detection\n")
|
||||
ucpu=`uname -m`
|
||||
|
||||
@@ -71,6 +71,9 @@ Language Additions
|
||||
- Added explicit ``static`` sections for enforced compile time evaluation.
|
||||
- Added an alternative notation for lambdas with ``do``.
|
||||
- ``addr`` is now treated like a prefix operator syntactically.
|
||||
- Added ``global`` pragma that can be used to introduce new global variables
|
||||
from within procs.
|
||||
- when expressions are now allowed just like if expressions
|
||||
|
||||
|
||||
2012-02-09 Version 0.8.14 released
|
||||
|
||||
Reference in New Issue
Block a user