next steps to hygienic templates
This commit is contained in:
parent
5e15dec175
commit
da190876de
17 changed files with 97 additions and 76 deletions
|
|
@ -259,7 +259,10 @@ const
|
||||||
sfImmediate* = sfDeadCodeElim
|
sfImmediate* = sfDeadCodeElim
|
||||||
# macro or template is immediately expanded
|
# macro or template is immediately expanded
|
||||||
# without considering any possible overloads
|
# without considering any possible overloads
|
||||||
|
|
||||||
|
sfDirty* = sfPure
|
||||||
|
# template is not hygienic (old styled template)
|
||||||
|
|
||||||
sfAnon* = sfDiscardable
|
sfAnon* = sfDiscardable
|
||||||
# symbol name that was generated by the compiler
|
# symbol name that was generated by the compiler
|
||||||
# the compiler will avoid printing such names
|
# the compiler will avoid printing such names
|
||||||
|
|
@ -691,7 +694,8 @@ const
|
||||||
|
|
||||||
|
|
||||||
# creator procs:
|
# creator procs:
|
||||||
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym
|
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym,
|
||||||
|
info: TLineInfo): PSym
|
||||||
proc NewType*(kind: TTypeKind, owner: PSym): PType
|
proc NewType*(kind: TTypeKind, owner: PSym): PType
|
||||||
proc newNode*(kind: TNodeKind): PNode
|
proc newNode*(kind: TNodeKind): PNode
|
||||||
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode
|
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode
|
||||||
|
|
@ -922,11 +926,10 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
|
||||||
result.sym = t.sym # backend-info should not be copied
|
result.sym = t.sym # backend-info should not be copied
|
||||||
|
|
||||||
proc copySym(s: PSym, keepId: bool = false): PSym =
|
proc copySym(s: PSym, keepId: bool = false): PSym =
|
||||||
result = newSym(s.kind, s.name, s.owner)
|
result = newSym(s.kind, s.name, s.owner, s.info)
|
||||||
result.ast = nil # BUGFIX; was: s.ast which made problems
|
result.ast = nil # BUGFIX; was: s.ast which made problems
|
||||||
result.info = s.info
|
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
if keepId:
|
if keepId:
|
||||||
result.id = s.id
|
result.id = s.id
|
||||||
else:
|
else:
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
|
|
@ -939,13 +942,14 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
|
||||||
result.loc = s.loc
|
result.loc = s.loc
|
||||||
result.annex = s.annex # BUGFIX
|
result.annex = s.annex # BUGFIX
|
||||||
|
|
||||||
proc NewSym(symKind: TSymKind, Name: PIdent, owner: PSym): PSym =
|
proc NewSym(symKind: TSymKind, Name: PIdent, owner: PSym,
|
||||||
|
info: TLineInfo): PSym =
|
||||||
# generates a symbol and initializes the hash field too
|
# generates a symbol and initializes the hash field too
|
||||||
new(result)
|
new(result)
|
||||||
result.Name = Name
|
result.Name = Name
|
||||||
result.Kind = symKind
|
result.Kind = symKind
|
||||||
result.flags = {}
|
result.flags = {}
|
||||||
result.info = UnknownLineInfo()
|
result.info = info
|
||||||
result.options = gOptions
|
result.options = gOptions
|
||||||
result.owner = owner
|
result.owner = owner
|
||||||
result.offset = - 1
|
result.offset = - 1
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
||||||
var field = if t.n != nil: t.n.sons[i].sym else: newSym(
|
var field = if t.n != nil: t.n.sons[i].sym else: newSym(
|
||||||
skField, getIdent(":tmp" & $i), t.owner)
|
skField, getIdent(":tmp" & $i), t.owner, info)
|
||||||
addSon(p, newSymNode(field, info))
|
addSon(p, newSymNode(field, info))
|
||||||
addSon(p, getNullValue(t.sons[i], info))
|
addSon(p, getNullValue(t.sons[i], info))
|
||||||
addSon(result, p)
|
addSon(result, p)
|
||||||
|
|
@ -1358,7 +1358,7 @@ proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
|
||||||
if evalTemplateCounter > 100:
|
if evalTemplateCounter > 100:
|
||||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||||
|
|
||||||
inc genSymBaseId
|
#inc genSymBaseId
|
||||||
var s = newStackFrame()
|
var s = newStackFrame()
|
||||||
s.call = n
|
s.call = n
|
||||||
setlen(s.params, 2)
|
setlen(s.params, 2)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import idents, strutils, os, options
|
import idents, strutils, os, options
|
||||||
|
|
||||||
var gFrontEndId, gBackendId*, genSymBaseId*: int
|
var gFrontEndId, gBackendId*: int
|
||||||
|
|
||||||
const
|
const
|
||||||
debugIds* = false
|
debugIds* = false
|
||||||
|
|
@ -34,9 +34,6 @@ proc backendId*(): int {.inline.} =
|
||||||
result = gBackendId
|
result = gBackendId
|
||||||
inc(gBackendId)
|
inc(gBackendId)
|
||||||
|
|
||||||
proc genSym*(basename: string): PIdent =
|
|
||||||
result = getIdent(basename & $genSymBaseId)
|
|
||||||
|
|
||||||
proc setId*(id: int) {.inline.} =
|
proc setId*(id: int) {.inline.} =
|
||||||
gFrontEndId = max(gFrontEndId, id + 1)
|
gFrontEndId = max(gFrontEndId, id + 1)
|
||||||
|
|
||||||
|
|
@ -66,4 +63,3 @@ proc loadMaxIds*(project: string) =
|
||||||
gFrontEndId = max(gFrontEndId, frontEndId)
|
gFrontEndId = max(gFrontEndId, frontEndId)
|
||||||
gBackEndId = max(gBackEndId, backEndId)
|
gBackEndId = max(gBackEndId, backEndId)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ proc newEnv(outerProc: PSym, up: PEnv, n: PNode): PEnv =
|
||||||
result.attachedNode = n
|
result.attachedNode = n
|
||||||
|
|
||||||
proc addField(tup: PType, s: PSym) =
|
proc addField(tup: PType, s: PSym) =
|
||||||
var field = newSym(skField, s.name, s.owner)
|
var field = newSym(skField, s.name, s.owner, s.info)
|
||||||
let t = skipIntLit(s.typ)
|
let t = skipIntLit(s.typ)
|
||||||
field.typ = t
|
field.typ = t
|
||||||
field.position = sonsLen(tup)
|
field.position = sonsLen(tup)
|
||||||
|
|
@ -179,7 +179,7 @@ proc addDep(e, d: PEnv, owner: PSym): PSym =
|
||||||
for x, field in items(e.deps):
|
for x, field in items(e.deps):
|
||||||
if x == d: return field
|
if x == d: return field
|
||||||
var pos = sonsLen(e.tup)
|
var pos = sonsLen(e.tup)
|
||||||
result = newSym(skField, getIdent(upName & $pos), owner)
|
result = newSym(skField, getIdent(upName & $pos), owner, owner.info)
|
||||||
result.typ = newType(tyRef, owner)
|
result.typ = newType(tyRef, owner)
|
||||||
result.position = pos
|
result.position = pos
|
||||||
assert d.tup != nil
|
assert d.tup != nil
|
||||||
|
|
@ -220,8 +220,7 @@ proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
|
||||||
#s.typ.callConv == ccClosure
|
#s.typ.callConv == ccClosure
|
||||||
|
|
||||||
proc addClosureParam(i: PInnerContext, e: PEnv) =
|
proc addClosureParam(i: PInnerContext, e: PEnv) =
|
||||||
var cp = newSym(skParam, getIdent(paramname), i.fn)
|
var cp = newSym(skParam, getIdent(paramname), i.fn, i.fn.info)
|
||||||
cp.info = i.fn.info
|
|
||||||
incl(cp.flags, sfFromGeneric)
|
incl(cp.flags, sfFromGeneric)
|
||||||
cp.typ = newType(tyRef, i.fn)
|
cp.typ = newType(tyRef, i.fn)
|
||||||
rawAddSon(cp.typ, e.tup)
|
rawAddSon(cp.typ, e.tup)
|
||||||
|
|
@ -449,9 +448,8 @@ proc addVar*(father, v: PNode) =
|
||||||
|
|
||||||
proc getClosureVar(o: POuterContext, e: PEnv): PSym =
|
proc getClosureVar(o: POuterContext, e: PEnv): PSym =
|
||||||
if e.closure == nil:
|
if e.closure == nil:
|
||||||
result = newSym(skVar, getIdent(envName), o.fn)
|
result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info)
|
||||||
incl(result.flags, sfShadowed)
|
incl(result.flags, sfShadowed)
|
||||||
result.info = e.attachedNode.info
|
|
||||||
result.typ = newType(tyRef, o.fn)
|
result.typ = newType(tyRef, o.fn)
|
||||||
result.typ.rawAddSon(e.tup)
|
result.typ.rawAddSon(e.tup)
|
||||||
e.closure = result
|
e.closure = result
|
||||||
|
|
@ -590,8 +588,7 @@ type
|
||||||
tup: PType
|
tup: PType
|
||||||
|
|
||||||
proc newIterResult(iter: PSym): PSym =
|
proc newIterResult(iter: PSym): PSym =
|
||||||
result = newSym(skResult, getIdent":result", iter)
|
result = newSym(skResult, getIdent":result", iter, iter.info)
|
||||||
result.info = iter.info
|
|
||||||
result.typ = iter.typ.sons[0]
|
result.typ = iter.typ.sons[0]
|
||||||
incl(result.flags, sfUsed)
|
incl(result.flags, sfUsed)
|
||||||
|
|
||||||
|
|
@ -650,15 +647,14 @@ proc liftIterator*(iter: PSym, body: PNode): PNode =
|
||||||
c.tup = newType(tyTuple, iter)
|
c.tup = newType(tyTuple, iter)
|
||||||
c.tup.n = newNodeI(nkRecList, iter.info)
|
c.tup.n = newNodeI(nkRecList, iter.info)
|
||||||
|
|
||||||
var cp = newSym(skParam, getIdent(paramname), iter)
|
var cp = newSym(skParam, getIdent(paramname), iter, iter.info)
|
||||||
cp.info = iter.info
|
|
||||||
incl(cp.flags, sfFromGeneric)
|
incl(cp.flags, sfFromGeneric)
|
||||||
cp.typ = newType(tyRef, iter)
|
cp.typ = newType(tyRef, iter)
|
||||||
rawAddSon(cp.typ, c.tup)
|
rawAddSon(cp.typ, c.tup)
|
||||||
c.closureParam = cp
|
c.closureParam = cp
|
||||||
addHiddenParam(iter, cp)
|
addHiddenParam(iter, cp)
|
||||||
|
|
||||||
c.state = newSym(skField, getIdent(":state"), iter)
|
c.state = newSym(skField, getIdent(":state"), iter, iter.info)
|
||||||
c.state.typ = getStateType(iter)
|
c.state.typ = getStateType(iter)
|
||||||
addField(c.tup, c.state)
|
addField(c.tup, c.state)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,14 @@ proc considerAcc*(n: PNode): PIdent =
|
||||||
of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
of 1: result = considerAcc(n.sons[0])
|
of 1: result = considerAcc(n.sons[0])
|
||||||
else:
|
else:
|
||||||
if n.len == 2 and n[0].kind == nkIdent and n[0].ident.id == ord(wStar):
|
var id = ""
|
||||||
# XXX find a better way instead of `*x` for 'genSym'
|
for i in 0.. <n.len:
|
||||||
result = genSym(n[1].ident.s)
|
let x = n.sons[i]
|
||||||
else:
|
case x.kind
|
||||||
var id = ""
|
of nkIdent: id.add(x.ident.s)
|
||||||
for i in 0.. <n.len:
|
of nkSym: id.add(x.sym.name.s)
|
||||||
let x = n.sons[i]
|
else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
case x.kind
|
result = getIdent(id)
|
||||||
of nkIdent: id.add(x.ident.s)
|
|
||||||
of nkSym: id.add(x.sym.name.s)
|
|
||||||
else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
|
||||||
result = getIdent(id)
|
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
|
|
||||||
|
|
@ -46,8 +42,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
|
||||||
considerAcc(m)
|
considerAcc(m)
|
||||||
else:
|
else:
|
||||||
getIdent("err:" & renderTree(m))
|
getIdent("err:" & renderTree(m))
|
||||||
result = newSym(skError, ident, getCurrOwner())
|
result = newSym(skError, ident, getCurrOwner(), n.info)
|
||||||
result.info = n.info
|
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
incl(result.flags, sfDiscardable)
|
incl(result.flags, sfDiscardable)
|
||||||
# pretend it's imported from some unknown module to prevent cascading errors:
|
# pretend it's imported from some unknown module to prevent cascading errors:
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ const
|
||||||
wGenSym, wInject}
|
wGenSym, wInject}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject}
|
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty}
|
||||||
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
||||||
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject}
|
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject}
|
||||||
|
|
@ -454,8 +454,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
|
||||||
elif it.sons[0].kind != nkIdent: invalidPragma(n)
|
elif it.sons[0].kind != nkIdent: invalidPragma(n)
|
||||||
elif it.sons[1].kind != nkIdent: invalidPragma(n)
|
elif it.sons[1].kind != nkIdent: invalidPragma(n)
|
||||||
|
|
||||||
var userPragma = NewSym(skTemplate, it.sons[1].ident, nil)
|
var userPragma = NewSym(skTemplate, it.sons[1].ident, nil, it.info)
|
||||||
userPragma.info = it.info
|
|
||||||
var body = newNodeI(nkPragma, n.info)
|
var body = newNodeI(nkPragma, n.info)
|
||||||
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
|
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
|
||||||
userPragma.ast = body
|
userPragma.ast = body
|
||||||
|
|
@ -488,6 +487,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
of wImmediate:
|
of wImmediate:
|
||||||
if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
|
if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
|
of wDirty:
|
||||||
|
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
||||||
|
else: invalidPragma(it)
|
||||||
of wImportCpp:
|
of wImportCpp:
|
||||||
processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
|
processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
|
||||||
of wImportObjC:
|
of wImportObjC:
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,7 @@ proc isTopLevel(c: PContext): bool {.inline.} =
|
||||||
result = c.tab.tos <= 2
|
result = c.tab.tos <= 2
|
||||||
|
|
||||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
result = newSym(kind, considerAcc(n), getCurrOwner())
|
result = newSym(kind, considerAcc(n), getCurrOwner(), n.info)
|
||||||
result.info = n.info
|
|
||||||
|
|
||||||
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
# like newSymS, but considers gensym'ed symbols
|
# like newSymS, but considers gensym'ed symbols
|
||||||
|
|
@ -65,8 +64,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
InternalAssert sfGenSym in result.flags
|
InternalAssert sfGenSym in result.flags
|
||||||
InternalAssert result.kind == kind
|
InternalAssert result.kind == kind
|
||||||
else:
|
else:
|
||||||
result = newSym(kind, considerAcc(n), getCurrOwner())
|
result = newSym(kind, considerAcc(n), getCurrOwner(), n.info)
|
||||||
result.info = n.info
|
|
||||||
|
|
||||||
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||||
allowed: TSymFlags): PSym
|
allowed: TSymFlags): PSym
|
||||||
|
|
|
||||||
|
|
@ -1470,7 +1470,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||||
typ = makeTypedesc(c, typ)
|
typ = makeTypedesc(c, typ)
|
||||||
var sym = newSym(skType, getIdent"TypeOfExpr", typ.owner).linkTo(typ)
|
var sym = newSym(skType, getIdent"TypeOfExpr",
|
||||||
|
typ.owner, n.info).linkTo(typ)
|
||||||
sym.flags.incl(sfAnon)
|
sym.flags.incl(sfAnon)
|
||||||
result = newSymNode(sym, n.info)
|
result = newSymNode(sym, n.info)
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
flags, toBind)
|
flags, toBind)
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
if n.sons[paramsPos].sons[0].kind != nkEmpty:
|
if n.sons[paramsPos].sons[0].kind != nkEmpty:
|
||||||
addPrelimDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
addPrelimDecl(c, newSym(skUnknown, getIdent("result"), nil, n.info))
|
||||||
n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, toBind)
|
n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, toBind)
|
||||||
n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, toBind)
|
n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, toBind)
|
||||||
var body: PNode
|
var body: PNode
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
||||||
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
||||||
var q = a.sym
|
var q = a.sym
|
||||||
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyTypeClass, tyExpr}: continue
|
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyTypeClass, tyExpr}: continue
|
||||||
var s = newSym(skType, q.name, getCurrOwner())
|
var s = newSym(skType, q.name, getCurrOwner(), q.info)
|
||||||
s.info = q.info
|
|
||||||
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
||||||
var t = PType(IdTableGet(pt, q.typ))
|
var t = PType(IdTableGet(pt, q.typ))
|
||||||
if t == nil:
|
if t == nil:
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
|
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
|
||||||
if trueSymbol == nil:
|
if trueSymbol == nil:
|
||||||
LocalError(n.info, errSystemNeeds, "true")
|
LocalError(n.info, errSystemNeeds, "true")
|
||||||
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner())
|
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
||||||
trueSymbol.typ = getSysType(tyBool)
|
trueSymbol.typ = getSysType(tyBool)
|
||||||
|
|
||||||
result.add(newSymNode(trueSymbol, n.info))
|
result.add(newSymNode(trueSymbol, n.info))
|
||||||
|
|
@ -620,10 +620,8 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
|
||||||
aa.sons[0].kind == nkObjectTy:
|
aa.sons[0].kind == nkObjectTy:
|
||||||
# give anonymous object a dummy symbol:
|
# give anonymous object a dummy symbol:
|
||||||
assert s.typ.sons[0].sym == nil
|
assert s.typ.sons[0].sym == nil
|
||||||
var anonObj = newSym(skType, getIdent(s.name.s & ":ObjectType"),
|
s.typ.sons[0].sym = newSym(skType, getIdent(s.name.s & ":ObjectType"),
|
||||||
getCurrOwner())
|
getCurrOwner(), s.info)
|
||||||
anonObj.info = s.info
|
|
||||||
s.typ.sons[0].sym = anonObj
|
|
||||||
|
|
||||||
proc SemTypeSection(c: PContext, n: PNode): PNode =
|
proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||||
typeSectionLeftSidePass(c, n)
|
typeSectionLeftSidePass(c, n)
|
||||||
|
|
@ -650,8 +648,7 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
|
||||||
|
|
||||||
proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) =
|
proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) =
|
||||||
if t != nil:
|
if t != nil:
|
||||||
var s = newSym(skResult, getIdent"result", getCurrOwner())
|
var s = newSym(skResult, getIdent"result", getCurrOwner(), info)
|
||||||
s.info = info
|
|
||||||
s.typ = t
|
s.typ = t
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
addParamOrResult(c, s, owner)
|
addParamOrResult(c, s, owner)
|
||||||
|
|
@ -697,8 +694,7 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||||
if result != nil: return result
|
if result != nil: return result
|
||||||
result = n
|
result = n
|
||||||
checkSonsLen(n, bodyPos + 1)
|
checkSonsLen(n, bodyPos + 1)
|
||||||
var s = newSym(skProc, getIdent":anonymous", getCurrOwner())
|
var s = newSym(skProc, getIdent":anonymous", getCurrOwner(), n.info)
|
||||||
s.info = n.info
|
|
||||||
s.ast = n
|
s.ast = n
|
||||||
n.sons[namePos] = newSymNode(s)
|
n.sons[namePos] = newSymNode(s)
|
||||||
pushOwner(s)
|
pushOwner(s)
|
||||||
|
|
@ -830,7 +826,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
popProcCon(c)
|
popProcCon(c)
|
||||||
else:
|
else:
|
||||||
if s.typ.sons[0] != nil and kind != skIterator:
|
if s.typ.sons[0] != nil and kind != skIterator:
|
||||||
addDecl(c, newSym(skUnknown, getIdent"result", nil))
|
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
|
||||||
var toBind = initIntSet()
|
var toBind = initIntSet()
|
||||||
n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
|
n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
|
||||||
fixupInstantiatedSymbols(c, s)
|
fixupInstantiatedSymbols(c, s)
|
||||||
|
|
|
||||||
|
|
@ -104,9 +104,9 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc isTemplParam(n: PNode): bool {.inline.} =
|
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
||||||
result = n.kind == nkSym and n.sym.kind == skParam and
|
result = n.kind == nkSym and n.sym.kind == skParam and
|
||||||
n.sym.owner.kind == skTemplate
|
n.sym.owner == c.owner
|
||||||
|
|
||||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||||
|
|
||||||
|
|
@ -119,15 +119,15 @@ proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
|
||||||
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
|
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
|
||||||
result = newSym(kind, considerAcc(n), c.owner)
|
result = newSym(kind, considerAcc(n), c.owner, n.info)
|
||||||
incl(result.flags, sfGenSym)
|
incl(result.flags, sfGenSym)
|
||||||
incl(result.flags, sfShadowed)
|
incl(result.flags, sfShadowed)
|
||||||
|
|
||||||
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||||
# locals default to 'gensym':
|
# locals default to 'gensym':
|
||||||
if n.kind != nkPragmaExpr or symBinding(n.sons[1]) != spInject:
|
if n.kind != nkPragmaExpr or symBinding(n.sons[1]) != spInject:
|
||||||
let ident = getIdentNode(c, n)
|
let ident = getIdentNode(c, n)
|
||||||
if not isTemplParam(ident):
|
if not isTemplParam(c, ident):
|
||||||
let local = newGenSym(k, ident, c)
|
let local = newGenSym(k, ident, c)
|
||||||
addPrelimDecl(c.c, local)
|
addPrelimDecl(c.c, local)
|
||||||
replaceIdentBySym(n, newSymNode(local, n.info))
|
replaceIdentBySym(n, newSymNode(local, n.info))
|
||||||
|
|
@ -142,7 +142,7 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||||
# routines default to 'inject':
|
# routines default to 'inject':
|
||||||
if n.kind notin nkLambdaKinds and symBinding(n.sons[pragmasPos]) == spGenSym:
|
if n.kind notin nkLambdaKinds and symBinding(n.sons[pragmasPos]) == spGenSym:
|
||||||
let ident = getIdentNode(c, n.sons[namePos])
|
let ident = getIdentNode(c, n.sons[namePos])
|
||||||
if not isTemplParam(ident):
|
if not isTemplParam(c, ident):
|
||||||
let s = newGenSym(k, ident, c)
|
let s = newGenSym(k, ident, c)
|
||||||
addPrelimDecl(c.c, s)
|
addPrelimDecl(c.c, s)
|
||||||
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
|
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
|
||||||
|
|
@ -164,6 +164,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
let s = QualifiedLookUp(c.c, n, {})
|
let s = QualifiedLookUp(c.c, n, {})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
if s.owner == c.owner and s.kind == skParam:
|
if s.owner == c.owner and s.kind == skParam:
|
||||||
|
incl(s.flags, sfUsed)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
elif Contains(c.toBind, s.id):
|
elif Contains(c.toBind, s.id):
|
||||||
result = symChoice(c.c, n, s)
|
result = symChoice(c.c, n, s)
|
||||||
|
|
@ -286,6 +287,33 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result.sons[i] = semTemplBody(c, n.sons[i])
|
result.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
|
|
||||||
|
proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||||
|
result = n
|
||||||
|
case n.kind
|
||||||
|
of nkIdent:
|
||||||
|
let s = QualifiedLookUp(c.c, n, {})
|
||||||
|
if s != nil:
|
||||||
|
if s.owner == c.owner and s.kind == skParam:
|
||||||
|
result = newSymNode(s, n.info)
|
||||||
|
elif Contains(c.toBind, s.id):
|
||||||
|
result = symChoice(c.c, n, s)
|
||||||
|
of nkBind:
|
||||||
|
result = semTemplBodyDirty(c, n.sons[0])
|
||||||
|
of nkBindStmt:
|
||||||
|
result = semBindStmt(c.c, n, c.toBind)
|
||||||
|
of nkEmpty, nkSym..nkNilLit:
|
||||||
|
nil
|
||||||
|
else:
|
||||||
|
# dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
|
||||||
|
# so we use the generic code for nkDotExpr too
|
||||||
|
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||||
|
let s = QualifiedLookUp(c.c, n, {})
|
||||||
|
if s != nil and Contains(c.toBind, s.id):
|
||||||
|
return symChoice(c.c, n, s)
|
||||||
|
result = n
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
||||||
|
|
||||||
proc transformToExpr(n: PNode): PNode =
|
proc transformToExpr(n: PNode): PNode =
|
||||||
var realStmt: int
|
var realStmt: int
|
||||||
|
|
@ -340,7 +368,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
ctx.toBind = initIntSet()
|
ctx.toBind = initIntSet()
|
||||||
ctx.c = c
|
ctx.c = c
|
||||||
ctx.owner = s
|
ctx.owner = s
|
||||||
n.sons[bodyPos] = semTemplBody(ctx, n.sons[bodyPos])
|
if sfDirty in s.flags:
|
||||||
|
n.sons[bodyPos] = semTemplBodyDirty(ctx, n.sons[bodyPos])
|
||||||
|
else:
|
||||||
|
n.sons[bodyPos] = semTemplBody(ctx, n.sons[bodyPos])
|
||||||
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
|
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
|
||||||
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
|
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
|
||||||
# only parameters are resolved, no type checking is performed
|
# only parameters are resolved, no type checking is performed
|
||||||
|
|
|
||||||
|
|
@ -622,7 +622,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
result = genericParams.sons[i].typ
|
result = genericParams.sons[i].typ
|
||||||
break addImplicitGeneric
|
break addImplicitGeneric
|
||||||
|
|
||||||
var s = newSym(skType, paramTypId, getCurrOwner())
|
var s = newSym(skType, paramTypId, getCurrOwner(), info)
|
||||||
if isAnon: s.flags.incl(sfAnon)
|
if isAnon: s.flags.incl(sfAnon)
|
||||||
s.linkTo(typeClass)
|
s.linkTo(typeClass)
|
||||||
s.position = genericParams.len
|
s.position = genericParams.len
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,7 @@ proc getCurrOwner(c: PTransf): PSym =
|
||||||
else: result = c.module
|
else: result = c.module
|
||||||
|
|
||||||
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym =
|
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym =
|
||||||
result = newSym(skTemp, getIdent(genPrefix), getCurrOwner(c))
|
result = newSym(skTemp, getIdent(genPrefix), getCurrOwner(c), info)
|
||||||
result.info = info
|
|
||||||
result.typ = skipTypes(typ, {tyGenericInst})
|
result.typ = skipTypes(typ, {tyGenericInst})
|
||||||
incl(result.flags, sfFromGeneric)
|
incl(result.flags, sfFromGeneric)
|
||||||
|
|
||||||
|
|
@ -205,9 +204,8 @@ proc hasContinue(n: PNode): bool =
|
||||||
if hasContinue(n.sons[i]): return true
|
if hasContinue(n.sons[i]): return true
|
||||||
|
|
||||||
proc newLabel(c: PTransf, n: PNode): PSym =
|
proc newLabel(c: PTransf, n: PNode): PSym =
|
||||||
result = newSym(skLabel, nil, getCurrOwner(c))
|
result = newSym(skLabel, nil, getCurrOwner(c), n.info)
|
||||||
result.name = getIdent(genPrefix & $result.id)
|
result.name = getIdent(genPrefix & $result.id)
|
||||||
result.info = n.info
|
|
||||||
|
|
||||||
proc transformBlock(c: PTransf, n: PNode): PTransNode =
|
proc transformBlock(c: PTransf, n: PNode): PTransNode =
|
||||||
var labl: PSym
|
var labl: PSym
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,8 @@ type
|
||||||
wFieldChecks,
|
wFieldChecks,
|
||||||
wWatchPoint, wSubsChar,
|
wWatchPoint, wSubsChar,
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||||
wWrite, wGensym, wInject, wInheritable, wThreadVar, wEmit, wNoStackFrame,
|
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
||||||
|
wNoStackFrame,
|
||||||
wImplicitStatic, wGlobal, wHoist
|
wImplicitStatic, wGlobal, wHoist
|
||||||
|
|
||||||
wAuto, wBool, wCatch, wChar, wClass,
|
wAuto, wBool, wCatch, wChar, wClass,
|
||||||
|
|
@ -138,7 +139,7 @@ const
|
||||||
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
||||||
"watchpoint",
|
"watchpoint",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
"write", "gensym", "inject", "inheritable", "threadvar", "emit",
|
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||||
"nostackframe", "implicitstatic", "global", "hoist",
|
"nostackframe", "implicitstatic", "global", "hoist",
|
||||||
|
|
||||||
"auto", "bool", "catch", "char", "class",
|
"auto", "bool", "catch", "char", "class",
|
||||||
|
|
|
||||||
|
|
@ -2290,6 +2290,9 @@ template doAssert*(cond: bool, msg = "") =
|
||||||
if not cond:
|
if not cond:
|
||||||
raiseAssert(astToStr(cond) & ' ' & msg)
|
raiseAssert(astToStr(cond) & ' ' & msg)
|
||||||
|
|
||||||
|
when not defined(nimhygiene):
|
||||||
|
{.pragma: inject.}
|
||||||
|
|
||||||
template onFailedAssert*(msg: expr, code: stmt): stmt =
|
template onFailedAssert*(msg: expr, code: stmt): stmt =
|
||||||
## Sets an assertion failure handler that will intercept any assert statements
|
## Sets an assertion failure handler that will intercept any assert statements
|
||||||
## following `onFailedAssert` in the current lexical scope.
|
## following `onFailedAssert` in the current lexical scope.
|
||||||
|
|
@ -2310,7 +2313,7 @@ template onFailedAssert*(msg: expr, code: stmt): stmt =
|
||||||
## assert(...)
|
## assert(...)
|
||||||
##
|
##
|
||||||
template raiseAssert(msgIMPL: string): stmt =
|
template raiseAssert(msgIMPL: string): stmt =
|
||||||
let `msg` = msgIMPL
|
let msg {.inject.} = msgIMPL
|
||||||
code
|
code
|
||||||
|
|
||||||
proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -1,7 +1,8 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- make templates hygienic by default: 'gensym', 'inject' pragmas
|
- make templates hygienic by default: 'gensym', 'inject' pragmas;
|
||||||
|
document 'gensym', 'inject' and 'dirty'
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
- use ``\`` for comment continuations
|
- use ``\`` for comment continuations
|
||||||
- ``final`` should be the default for objects
|
- ``final`` should be the default for objects
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue