Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
commit
82813e58c4
31 changed files with 335 additions and 86 deletions
|
|
@ -143,7 +143,7 @@ type
|
||||||
nkPragma, # a pragma statement
|
nkPragma, # a pragma statement
|
||||||
nkPragmaBlock, # a pragma with a block
|
nkPragmaBlock, # a pragma with a block
|
||||||
nkIfStmt, # an if statement
|
nkIfStmt, # an if statement
|
||||||
nkWhenStmt, # a when statement
|
nkWhenStmt, # a when expression or statement
|
||||||
nkForStmt, # a for statement
|
nkForStmt, # a for statement
|
||||||
nkWhileStmt, # a while statement
|
nkWhileStmt, # a while statement
|
||||||
nkCaseStmt, # a case statement
|
nkCaseStmt, # a case statement
|
||||||
|
|
@ -243,8 +243,18 @@ const
|
||||||
sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
|
sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
|
||||||
sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
|
sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
|
||||||
sfNoInit* = sfMainModule # don't generate code to init the variable
|
sfNoInit* = sfMainModule # don't generate code to init the variable
|
||||||
|
|
||||||
sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded
|
sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded
|
||||||
# without considering any possible overloads
|
# 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
|
type
|
||||||
TTypeKind* = enum # order is important!
|
TTypeKind* = enum # order is important!
|
||||||
|
|
@ -353,7 +363,8 @@ const
|
||||||
|
|
||||||
type
|
type
|
||||||
TMagic* = enum # symbols that require compiler magic:
|
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,
|
mEcho, mShallowCopy, mSlurp,
|
||||||
mParseExprToAst, mParseStmtToAst, mExpandToAst,
|
mParseExprToAst, mParseStmtToAst, mExpandToAst,
|
||||||
mUnaryLt, mSucc,
|
mUnaryLt, mSucc,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# included from cgen.nim
|
||||||
|
|
||||||
const
|
const
|
||||||
RangeExpandLimit = 256 # do not generate ranges
|
RangeExpandLimit = 256 # do not generate ranges
|
||||||
# over 'RangeExpandLimit' elements
|
# over 'RangeExpandLimit' elements
|
||||||
|
|
@ -48,16 +50,20 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||||
proc genSingleVar(p: BProc, a: PNode) =
|
proc genSingleVar(p: BProc, a: PNode) =
|
||||||
var v = a.sons[0].sym
|
var v = a.sons[0].sym
|
||||||
if sfCompileTime in v.flags: return
|
if sfCompileTime in v.flags: return
|
||||||
|
var targetProc = p
|
||||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
assignGlobalVar(p, v)
|
if v.owner.kind != skModule:
|
||||||
genObjectInit(p, cpsInit, v.typ, v.loc, true)
|
targetProc = p.module.preInitProc
|
||||||
|
assignGlobalVar(targetProc, v)
|
||||||
|
genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
|
||||||
else:
|
else:
|
||||||
assignLocalVar(p, v)
|
assignLocalVar(p, v)
|
||||||
initLocalVar(p, v, immediateAsgn)
|
initLocalVar(p, v, immediateAsgn)
|
||||||
|
|
||||||
if immediateAsgn:
|
if immediateAsgn:
|
||||||
genLineDir(p, a)
|
genLineDir(targetProc, a)
|
||||||
loadInto(p, a.sons[0], a.sons[2], v.loc)
|
loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
|
||||||
|
|
||||||
proc genClosureVar(p: BProc, a: PNode) =
|
proc genClosureVar(p: BProc, a: PNode) =
|
||||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||||
|
|
|
||||||
|
|
@ -859,6 +859,7 @@ proc genInitCode(m: BModule) =
|
||||||
|
|
||||||
app(prc, genSectionStart(cpsLocals))
|
app(prc, genSectionStart(cpsLocals))
|
||||||
app(prc, m.initProc.s[cpsLocals])
|
app(prc, m.initProc.s[cpsLocals])
|
||||||
|
app(prc, m.preInitProc.s[cpsLocals])
|
||||||
app(prc, genSectionEnd(cpsLocals))
|
app(prc, genSectionEnd(cpsLocals))
|
||||||
|
|
||||||
app(prc, genSectionStart(cfsTypeInit1))
|
app(prc, genSectionStart(cfsTypeInit1))
|
||||||
|
|
@ -875,10 +876,12 @@ proc genInitCode(m: BModule) =
|
||||||
app(prc, genSectionEnd(i))
|
app(prc, genSectionEnd(i))
|
||||||
|
|
||||||
app(prc, genSectionStart(cpsInit))
|
app(prc, genSectionStart(cpsInit))
|
||||||
|
app(prc, m.preInitProc.s[cpsInit])
|
||||||
app(prc, m.initProc.s[cpsInit])
|
app(prc, m.initProc.s[cpsInit])
|
||||||
app(prc, genSectionEnd(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])
|
app(prc, m.initProc.s[cpsStmts])
|
||||||
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||||
app(prc, deinitFrame(m.initProc))
|
app(prc, deinitFrame(m.initProc))
|
||||||
|
|
@ -916,6 +919,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
result.typeInfoMarker = initIntSet()
|
result.typeInfoMarker = initIntSet()
|
||||||
result.initProc = newProc(nil, result)
|
result.initProc = newProc(nil, result)
|
||||||
result.initProc.options = gOptions
|
result.initProc.options = gOptions
|
||||||
|
result.preInitProc = newProc(nil, result)
|
||||||
initNodeTable(result.dataCache)
|
initNodeTable(result.dataCache)
|
||||||
result.typeStack = @[]
|
result.typeStack = @[]
|
||||||
result.forwardedProcs = @[]
|
result.forwardedProcs = @[]
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,10 @@ type
|
||||||
headerFiles*: TLinkedList # needed headers to include
|
headerFiles*: TLinkedList # needed headers to include
|
||||||
typeInfoMarker*: TIntSet # needed for generating type information
|
typeInfoMarker*: TIntSet # needed for generating type information
|
||||||
initProc*: BProc # code for init procedure
|
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
|
typeStack*: TTypeSeq # used for type generation
|
||||||
dataCache*: TNodeTable
|
dataCache*: TNodeTable
|
||||||
forwardedProcs*: TSymSeq # keep forwarded procs here
|
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 =
|
proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skConverter, skMacro:
|
of skProc, skConverter, skMacro, skType:
|
||||||
result = n
|
result = n
|
||||||
#result = s.getBody
|
#result = s.getBody
|
||||||
of skVar, skLet, skForVar, skTemp, skResult:
|
of skVar, skLet, skForVar, skTemp, skResult:
|
||||||
|
|
@ -891,7 +891,24 @@ proc evalTemplate*(n: PNode, sym: PSym): PNode =
|
||||||
result = evalTemplateAux(sym.getBody, args, sym)
|
result = evalTemplateAux(sym.getBody, args, sym)
|
||||||
|
|
||||||
dec(evalTemplateCounter)
|
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 =
|
proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
||||||
var
|
var
|
||||||
n = original.copyTree
|
n = original.copyTree
|
||||||
|
|
@ -941,6 +958,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
of mParseExprToAst: result = evalParseExpr(c, n)
|
of mParseExprToAst: result = evalParseExpr(c, n)
|
||||||
of mParseStmtToAst: result = evalParseStmt(c, n)
|
of mParseStmtToAst: result = evalParseStmt(c, n)
|
||||||
of mExpandToAst: result = evalExpandToAst(c, n)
|
of mExpandToAst: result = evalExpandToAst(c, n)
|
||||||
|
of mTypeTrait: result = evalTypeTrait(n, c.module)
|
||||||
of mNLen:
|
of mNLen:
|
||||||
result = evalAux(c, n.sons[1], {efLValue})
|
result = evalAux(c, n.sons[1], {efLValue})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ type
|
||||||
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
|
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
|
||||||
errInvalidParamKindX, errDefaultArgumentInvalid, errNamedParamHasToBeIdent,
|
errInvalidParamKindX, errDefaultArgumentInvalid, errNamedParamHasToBeIdent,
|
||||||
errNoReturnTypeForX, errConvNeedsOneArg, errInvalidPragmaX,
|
errNoReturnTypeForX, errConvNeedsOneArg, errInvalidPragmaX,
|
||||||
errXNotAllowedHere, errInvalidControlFlowX, errATypeHasNoValue,
|
errXNotAllowedHere, errInvalidControlFlowX,
|
||||||
errXisNoType, errCircumNeedsPointer, errInvalidExpression,
|
errXisNoType, errCircumNeedsPointer, errInvalidExpression,
|
||||||
errInvalidExpressionX, errEnumHasNoValueX, errNamedExprExpected,
|
errInvalidExpressionX, errEnumHasNoValueX, errNamedExprExpected,
|
||||||
errNamedExprNotAllowed, errXExpectsOneTypeParam,
|
errNamedExprNotAllowed, errXExpectsOneTypeParam,
|
||||||
|
|
@ -275,7 +275,6 @@ const
|
||||||
errInvalidPragmaX: "invalid pragma: $1",
|
errInvalidPragmaX: "invalid pragma: $1",
|
||||||
errXNotAllowedHere: "$1 not allowed here",
|
errXNotAllowedHere: "$1 not allowed here",
|
||||||
errInvalidControlFlowX: "invalid control flow: $1",
|
errInvalidControlFlowX: "invalid control flow: $1",
|
||||||
errATypeHasNoValue: "a type has no value",
|
|
||||||
errXisNoType: "invalid type: \'$1\'",
|
errXisNoType: "invalid type: \'$1\'",
|
||||||
errCircumNeedsPointer: "'[]' needs a pointer or reference type",
|
errCircumNeedsPointer: "'[]' needs a pointer or reference type",
|
||||||
errInvalidExpression: "invalid expression",
|
errInvalidExpression: "invalid expression",
|
||||||
|
|
@ -667,3 +666,6 @@ template AssertNotNil*(e: expr): expr =
|
||||||
if(e == nil): InternalError($InstantiationInfo())
|
if(e == nil): InternalError($InstantiationInfo())
|
||||||
e
|
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
|
# Can we keep this? I'm using it all the time
|
||||||
template nimdbg*: expr = c.filename.endsWith"nimdbg.nim"
|
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)
|
optInd(p, a)
|
||||||
eat(p, endTok)
|
eat(p, endTok)
|
||||||
|
|
||||||
proc newDotExpr(p: var TParser, a: PNode): PNode =
|
proc dotExpr(p: var TParser, a: PNode): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
result = newNodeI(nkDotExpr, a.info)
|
case p.tok.tokType
|
||||||
addSon(result, a)
|
of tkType:
|
||||||
addSon(result, parseSymbol(p))
|
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 =
|
proc qualifiedIdent(p: var TParser): PNode =
|
||||||
result = parseSymbol(p) #optInd(p, result);
|
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) =
|
proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -477,7 +487,7 @@ proc primary(p: var TParser): PNode =
|
||||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
||||||
parseDoBlocks(p, result)
|
parseDoBlocks(p, result)
|
||||||
of tkDot:
|
of tkDot:
|
||||||
result = newDotExpr(p, result)
|
result = dotExpr(p, result)
|
||||||
result = parseGStrLit(p, result)
|
result = parseGStrLit(p, result)
|
||||||
of tkBracketLe:
|
of tkBracketLe:
|
||||||
result = indexExprList(p, result, nkBracketExpr, tkBracketRi)
|
result = indexExprList(p, result, nkBracketExpr, tkBracketRi)
|
||||||
|
|
@ -506,8 +516,8 @@ proc lowestExprAux(p: var TParser, limit: int): PNode =
|
||||||
proc lowestExpr(p: var TParser): PNode =
|
proc lowestExpr(p: var TParser): PNode =
|
||||||
result = lowestExprAux(p, -1)
|
result = lowestExprAux(p, -1)
|
||||||
|
|
||||||
proc parseIfExpr(p: var TParser): PNode =
|
proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||||
result = newNodeP(nkIfExpr, p)
|
result = newNodeP(kind, p)
|
||||||
while true:
|
while true:
|
||||||
getTok(p) # skip `if`, `elif`
|
getTok(p) # skip `if`, `elif`
|
||||||
var branch = newNodeP(nkElifExpr, p)
|
var branch = newNodeP(nkElifExpr, p)
|
||||||
|
|
@ -707,7 +717,8 @@ proc parseExpr(p: var TParser): PNode =
|
||||||
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
|
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
|
||||||
of tkTuple: result = parseTuple(p)
|
of tkTuple: result = parseTuple(p)
|
||||||
of tkProc: result = parseProcExpr(p, true)
|
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)
|
else: result = lowestExpr(p)
|
||||||
|
|
||||||
proc parseTypeDesc(p: var TParser): PNode =
|
proc parseTypeDesc(p: var TParser): PNode =
|
||||||
|
|
@ -718,7 +729,7 @@ proc isExprStart(p: TParser): bool =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkBind,
|
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkBind,
|
||||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
||||||
tkTuple, tkType:
|
tkTuple, tkType, tkWhen:
|
||||||
result = true
|
result = true
|
||||||
else: result = false
|
else: result = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ const
|
||||||
wImportcpp, wImportobjc, wError}
|
wImportcpp, wImportobjc, wError}
|
||||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||||
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
|
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime}
|
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal}
|
||||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||||
wExtern, wImportcpp, wImportobjc, wError}
|
wExtern, wImportcpp, wImportobjc, wError}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
|
|
@ -494,6 +494,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
noVal(it)
|
noVal(it)
|
||||||
incl(sym.flags, sfCompileTime)
|
incl(sym.flags, sfCompileTime)
|
||||||
incl(sym.loc.Flags, lfNoDecl)
|
incl(sym.loc.Flags, lfNoDecl)
|
||||||
|
of wGlobal:
|
||||||
|
noVal(it)
|
||||||
|
incl(sym.flags, sfGlobal)
|
||||||
of wMerge:
|
of wMerge:
|
||||||
noval(it)
|
noval(it)
|
||||||
incl(sym.flags, sfMerge)
|
incl(sym.flags, sfMerge)
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,8 @@ proc lsub(n: PNode): int =
|
||||||
of nkBind: result = lsons(n) + len("bind_")
|
of nkBind: result = lsons(n) + len("bind_")
|
||||||
of nkBindStmt: result = lcomma(n) + len("bind_")
|
of nkBindStmt: result = lcomma(n) + len("bind_")
|
||||||
of nkCheckedFieldExpr: result = lsub(n.sons[0])
|
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:
|
of nkConstDef, nkIdentDefs:
|
||||||
result = lcomma(n, 0, - 3)
|
result = lcomma(n, 0, - 3)
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
|
|
@ -677,7 +678,17 @@ proc gident(g: var TSrcGen, n: PNode) =
|
||||||
t = tkOpr
|
t = tkOpr
|
||||||
put(g, t, s)
|
put(g, t, s)
|
||||||
if n.kind == nkSym and renderIds in g.flags: put(g, tkIntLit, $n.sym.id)
|
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) =
|
proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
if isNil(n): return
|
if isNil(n): return
|
||||||
var
|
var
|
||||||
|
|
@ -804,14 +815,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
|
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
of nkLambda, nkDo: # XXX: nkDo is rendered as regular lambda
|
of nkLambda:
|
||||||
assert(n.sons[genericParamsPos].kind == nkEmpty)
|
putWithSpace(g, tkLambda, "proc")
|
||||||
putWithSpace(g, tkLambda, "lambda")
|
|
||||||
gsub(g, n.sons[paramsPos])
|
gsub(g, n.sons[paramsPos])
|
||||||
gsub(g, n.sons[pragmasPos])
|
gsub(g, n.sons[pragmasPos])
|
||||||
put(g, tkSpaces, Space)
|
put(g, tkSpaces, Space)
|
||||||
putWithSpace(g, tkEquals, "=")
|
putWithSpace(g, tkEquals, "=")
|
||||||
gsub(g, n.sons[bodyPos])
|
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:
|
of nkConstDef, nkIdentDefs:
|
||||||
gcomma(g, n, 0, - 3)
|
gcomma(g, n, 0, - 3)
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
|
|
@ -960,7 +976,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkIfStmt:
|
of nkIfStmt:
|
||||||
putWithSpace(g, tkIf, "if")
|
putWithSpace(g, tkIf, "if")
|
||||||
gif(g, n)
|
gif(g, n)
|
||||||
of nkWhenStmt, nkRecWhen:
|
of nkWhen, nkRecWhen:
|
||||||
putWithSpace(g, tkWhen, "when")
|
putWithSpace(g, tkWhen, "when")
|
||||||
gif(g, n)
|
gif(g, n)
|
||||||
of nkWhileStmt: gwhile(g, n)
|
of nkWhileStmt: gwhile(g, n)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ proc semPass*(): TPass
|
||||||
|
|
||||||
type
|
type
|
||||||
TExprFlag = enum
|
TExprFlag = enum
|
||||||
efAllowType, efLValue, efWantIterator, efInTypeof
|
efLValue, efWantIterator, efInTypeof
|
||||||
TExprFlags = set[TExprFlag]
|
TExprFlags = set[TExprFlag]
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,16 @@
|
||||||
# this module does the semantic checking for expressions
|
# this module does the semantic checking for expressions
|
||||||
# included from sem.nim
|
# 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 =
|
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||||
markUsed(n, s)
|
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")
|
if s.ast == nil: InternalError(n.info, "no default for")
|
||||||
result = semExpr(c, s.ast)
|
result = semExpr(c, s.ast)
|
||||||
of skType:
|
of skType:
|
||||||
if efAllowType notin flags:
|
|
||||||
GlobalError(n.info, errATypeHasNoValue)
|
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
|
result.typ = makeTypeDesc(c, s.typ)
|
||||||
else:
|
else:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
|
|
@ -206,7 +214,8 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
if sonsLen(n) != 2:
|
if sonsLen(n) != 2:
|
||||||
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||||
else:
|
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)
|
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
case typ.Kind
|
case typ.Kind
|
||||||
of tySequence, tyString, tyOpenArray:
|
of tySequence, tyString, tyOpenArray:
|
||||||
|
|
@ -219,15 +228,21 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc semSizeof(c: PContext, n: PNode): PNode =
|
proc semSizeof(c: PContext, n: PNode): PNode =
|
||||||
if sonsLen(n) != 2: GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
if sonsLen(n) != 2:
|
||||||
else: n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||||
|
else:
|
||||||
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
|
restoreOldStyleType(n.sons[1])
|
||||||
|
|
||||||
n.typ = getSysType(tyInt)
|
n.typ = getSysType(tyInt)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc semOf(c: PContext, n: PNode): PNode =
|
proc semOf(c: PContext, n: PNode): PNode =
|
||||||
if sonsLen(n) == 3:
|
if sonsLen(n) == 3:
|
||||||
n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
n.sons[2] = semExprWithType(c, n.sons[2], {efAllowType})
|
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 a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||||
var b = skipTypes(n.sons[2].typ, abstractPtrs)
|
var b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||||
if b.kind != tyObject or a.kind != tyObject:
|
if b.kind != tyObject or a.kind != tyObject:
|
||||||
|
|
@ -251,31 +266,16 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errXExpectsTwoArguments, "is")
|
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) =
|
proc semOpAux(c: PContext, n: PNode) =
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||||
var info = a.sons[0].info
|
var info = a.sons[0].info
|
||||||
a.sons[0] = newIdentNode(considerAcc(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
|
a.typ = a.sons[1].typ
|
||||||
else:
|
else:
|
||||||
n.sons[i] = semExprOrTypedesc(c, a)
|
n.sons[i] = semExprWithType(c, a)
|
||||||
|
|
||||||
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||||
# quick check if there is *any* () operator overloaded:
|
# quick check if there is *any* () operator overloaded:
|
||||||
|
|
@ -409,8 +409,10 @@ proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||||
of nkSym:
|
of nkSym:
|
||||||
# don't list 'skLet' here:
|
# don't list 'skLet' here:
|
||||||
if n.sym.kind in {skVar, skResult, skTemp}:
|
if n.sym.kind in {skVar, skResult, skTemp}:
|
||||||
if c.p.owner.id == n.sym.owner.id: result = arLocalLValue
|
if c.p.owner.id == n.sym.owner.id and sfGlobal notin n.sym.flags:
|
||||||
else: result = arLValue
|
result = arLocalLValue
|
||||||
|
else:
|
||||||
|
result = arLValue
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
|
|
@ -752,13 +754,15 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return semSym(c, n, s, flags)
|
return semSym(c, n, s, flags)
|
||||||
|
|
||||||
checkSonsLen(n, 2)
|
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 i = considerAcc(n.sons[1])
|
||||||
var ty = n.sons[0].Typ
|
var ty = n.sons[0].typ
|
||||||
var f: PSym = nil
|
var f: PSym = nil
|
||||||
result = nil
|
result = nil
|
||||||
if isTypeExpr(n.sons[0]):
|
if isTypeExpr(n.sons[0]):
|
||||||
if ty.kind == tyEnum:
|
case ty.kind
|
||||||
|
of tyEnum:
|
||||||
# look up if the identifier belongs to the enum:
|
# look up if the identifier belongs to the enum:
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
f = getSymFromList(ty.n, i)
|
f = getSymFromList(ty.n, i)
|
||||||
|
|
@ -769,10 +773,22 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
result.typ = ty
|
result.typ = ty
|
||||||
markUsed(n, f)
|
markUsed(n, f)
|
||||||
return
|
return
|
||||||
elif efAllowType notin flags:
|
of tyGenericInst:
|
||||||
GlobalError(n.sons[0].info, errATypeHasNoValue)
|
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
|
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":
|
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
||||||
ty = n.sons[0].Typ
|
ty = n.sons[0].Typ
|
||||||
|
|
||||||
|
|
@ -852,14 +868,14 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result.add(x[0])
|
result.add(x[0])
|
||||||
return
|
return
|
||||||
checkMinSonsLen(n, 2)
|
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})
|
var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||||
case arr.kind
|
case arr.kind
|
||||||
of tyArray, tyOpenArray, tyArrayConstr, tySequence, tyString, tyCString:
|
of tyArray, tyOpenArray, tyArrayConstr, tySequence, tyString, tyCString:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
n.sons[0] = makeDeref(n.sons[0])
|
n.sons[0] = makeDeref(n.sons[0])
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
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 indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||||
if arg != nil:
|
if arg != nil:
|
||||||
|
|
@ -1280,9 +1296,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
nil
|
nil
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
result.typ = getSysType(tyNil)
|
result.typ = getSysType(tyNil)
|
||||||
of nkType:
|
|
||||||
if not (efAllowType in flags): GlobalError(n.info, errATypeHasNoValue)
|
|
||||||
n.typ = semTypeNode(c, n, nil)
|
|
||||||
of nkIntLit:
|
of nkIntLit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyInt)
|
if result.typ == nil: result.typ = getSysType(tyInt)
|
||||||
of nkInt8Lit:
|
of nkInt8Lit:
|
||||||
|
|
@ -1312,11 +1325,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
Message(n.info, warnDeprecated, "bind")
|
Message(n.info, warnDeprecated, "bind")
|
||||||
result = semExpr(c, n.sons[0], flags)
|
result = semExpr(c, n.sons[0], flags)
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
var typ = semTypeNode(c, n, nil)
|
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||||
if typ.sym == nil:
|
typ = makeTypedesc(c, typ)
|
||||||
typ = copyType(typ, typ.owner, true)
|
var sym = newSym(skType, getIdent"TypeOfExpr", typ.owner).linkTo(typ)
|
||||||
typ.linkTo(newSym(skType, getIdent"typedesc", typ.owner))
|
sym.flags.incl(sfAnon)
|
||||||
result = newSymNode(typ.sym, n.info)
|
result = newSymNode(sym, n.info)
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||||
# check if it is an expression macro:
|
# check if it is an expression macro:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -1354,6 +1367,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
of nkMacroStmt:
|
of nkMacroStmt:
|
||||||
result = semMacroStmt(c, n)
|
result = semMacroStmt(c, n)
|
||||||
|
of nkWhenExpr:
|
||||||
|
result = semWhen(c, n, false)
|
||||||
|
result = semExpr(c, result)
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
|
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,
|
of mNewString, mNewStringOfCap,
|
||||||
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
|
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
|
||||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||||
mParseExprToAst, mParseStmtToAst, mExpandToAst,
|
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait,
|
||||||
mNLen..mNError, mEqRef:
|
mNLen..mNError, mEqRef:
|
||||||
nil
|
nil
|
||||||
of mRand:
|
of mRand:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# This include file implements the semantic checking for magics.
|
# This include file implements the semantic checking for magics.
|
||||||
|
# included from sem.nim
|
||||||
|
|
||||||
proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
var r = isPartOf(n[1], n[2])
|
var r = isPartOf(n[1], n[2])
|
||||||
|
|
@ -43,11 +44,21 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
||||||
result.add(filename)
|
result.add(filename)
|
||||||
result.add(line)
|
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,
|
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
case n[0].sym.magic
|
case n[0].sym.magic
|
||||||
of mSlurp: result = semSlurp(c, n, flags)
|
of mSlurp: result = semSlurp(c, n, flags)
|
||||||
of mIsPartOf: result = semIsPartOf(c, n, flags)
|
of mIsPartOf: result = semIsPartOf(c, n, flags)
|
||||||
|
of mTypeTrait: result = semTypeTraits(c, n)
|
||||||
of mAstToStr:
|
of mAstToStr:
|
||||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
||||||
result.typ = getSysType(tyString)
|
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):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
case it.kind
|
case it.kind
|
||||||
of nkElifBranch:
|
of nkElifBranch, nkElifExpr:
|
||||||
checkSonsLen(it, 2)
|
checkSonsLen(it, 2)
|
||||||
var e = semAndEvalConstExpr(c, it.sons[0])
|
var e = semAndEvalConstExpr(c, it.sons[0])
|
||||||
if e.kind != nkIntLit: InternalError(n.info, "semWhen")
|
if e.kind != nkIntLit: InternalError(n.info, "semWhen")
|
||||||
if e.intVal != 0 and result == nil:
|
if e.intVal != 0 and result == nil:
|
||||||
setResult(it.sons[1])
|
setResult(it.sons[1])
|
||||||
of nkElse:
|
of nkElse, nkElseExpr:
|
||||||
checkSonsLen(it, 1)
|
checkSonsLen(it, 1)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
setResult(it.sons[0])
|
setResult(it.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,12 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
if result != nil:
|
if result != nil:
|
||||||
markUsed(n, result)
|
markUsed(n, result)
|
||||||
if result.kind == skParam and result.typ.kind == tyTypeDesc:
|
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.kind != skType: GlobalError(n.info, errTypeExpected)
|
||||||
if result.typ.kind != tyGenericParam:
|
if result.typ.kind != tyGenericParam:
|
||||||
# XXX get rid of this hack!
|
# XXX get rid of this hack!
|
||||||
|
|
@ -583,8 +588,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
break addImplicitGeneric
|
break addImplicitGeneric
|
||||||
|
|
||||||
var s = newSym(skType, paramTypId, getCurrOwner())
|
var s = newSym(skType, paramTypId, getCurrOwner())
|
||||||
s.typ = typeClass
|
s.flags.incl(sfAnon)
|
||||||
s.typ.sym = s
|
s.linkTo(typeClass)
|
||||||
s.position = genericParams.len
|
s.position = genericParams.len
|
||||||
genericParams.addSon(newSymNode(s))
|
genericParams.addSon(newSymNode(s))
|
||||||
endingType = typeClass
|
endingType = typeClass
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,13 @@ proc rangeToStr(n: PNode): string =
|
||||||
assert(n.kind == nkRange)
|
assert(n.kind == nkRange)
|
||||||
result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
|
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 =
|
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
const
|
const
|
||||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||||
|
|
@ -387,7 +394,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
var t = typ
|
var t = typ
|
||||||
result = ""
|
result = ""
|
||||||
if t == nil: return
|
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
|
return t.sym.Name.s
|
||||||
case t.Kind
|
case t.Kind
|
||||||
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
||||||
|
|
@ -396,6 +403,14 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
if i > 1: add(result, ", ")
|
if i > 1: add(result, ", ")
|
||||||
add(result, typeToString(t.sons[i]))
|
add(result, typeToString(t.sons[i]))
|
||||||
add(result, ']')
|
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:
|
of tyArray:
|
||||||
if t.sons[0].kind == tyRange:
|
if t.sons[0].kind == tyRange:
|
||||||
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type
|
||||||
wWatchPoint, wSubsChar,
|
wWatchPoint, wSubsChar,
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wNoStackFrame,
|
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wNoStackFrame,
|
||||||
wImplicitStatic
|
wImplicitStatic, wGlobal
|
||||||
|
|
||||||
TSpecialWords* = set[TSpecialWord]
|
TSpecialWords* = set[TSpecialWord]
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ const
|
||||||
"watchpoint",
|
"watchpoint",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||||
"nostackframe", "implicitstatic"]
|
"nostackframe", "implicitstatic", "global"]
|
||||||
|
|
||||||
proc findStr*(a: openarray[string], s: string): int =
|
proc findStr*(a: openarray[string], s: string): int =
|
||||||
for i in countup(low(a), high(a)):
|
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
|
{.pop.} # restore old settings
|
||||||
|
|
||||||
|
|
||||||
Register pragma
|
register pragma
|
||||||
---------------
|
---------------
|
||||||
The `register`:idx: pragma is for variables only. It declares the variable as
|
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
|
``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
|
In highly specific cases (a dispatch loop of an bytecode interpreter for
|
||||||
example) it may provide benefits, though.
|
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
|
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 """
|
discard """
|
||||||
file: "ttypenoval.nim"
|
file: "ttypenoval.nim"
|
||||||
line: 38
|
line: 38
|
||||||
errormsg: "a type has no value"
|
errormsg: "type mismatch: got (typedesc{int}) but expected 'int'"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# A min-heap.
|
# A min-heap.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
discard """
|
discard """
|
||||||
disabled: true
|
|
||||||
output: '''derived class
|
output: '''derived class
|
||||||
base class
|
base class
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
discard """
|
discard """
|
||||||
disabled: true
|
|
||||||
output: '''derived class 2
|
output: '''derived class 2
|
||||||
base class
|
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:
|
except EOS:
|
||||||
echo "[Warning] could not delete: ", dir
|
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) =
|
proc runRodFiles(r: var TResults, options: string) =
|
||||||
template test(filename: expr): stmt =
|
template test(filename: expr): stmt =
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,30 @@
|
||||||
# result = "#! /bin/sh\n# Generated from niminst\n" &
|
# result = "#! /bin/sh\n# Generated from niminst\n" &
|
||||||
# "# Template is in tools/buildsh.tmpl\n" &
|
# "# Template is in tools/buildsh.tmpl\n" &
|
||||||
# "# To regenerate run ``niminst csource`` or ``koch csource``\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"
|
CC="gcc"
|
||||||
LINKER="gcc"
|
LINKER="gcc"
|
||||||
COMP_FLAGS="?{c.ccompiler.flags}"
|
COMP_FLAGS="?{c.ccompiler.flags}$extraBuildArgs"
|
||||||
LINK_FLAGS="?{c.linker.flags}"
|
LINK_FLAGS="?{c.linker.flags}"
|
||||||
# add(result, "# platform detection\n")
|
# add(result, "# platform detection\n")
|
||||||
ucpu=`uname -m`
|
ucpu=`uname -m`
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,9 @@ Language Additions
|
||||||
- Added explicit ``static`` sections for enforced compile time evaluation.
|
- Added explicit ``static`` sections for enforced compile time evaluation.
|
||||||
- Added an alternative notation for lambdas with ``do``.
|
- Added an alternative notation for lambdas with ``do``.
|
||||||
- ``addr`` is now treated like a prefix operator syntactically.
|
- ``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
|
2012-02-09 Version 0.8.14 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue