diff options
-rwxr-xr-x | compiler/condsyms.nim | 1 | ||||
-rwxr-xr-x | compiler/semgnrc.nim | 119 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 23 | ||||
-rwxr-xr-x | lib/system/arithm.nim | 2 | ||||
-rwxr-xr-x | lib/system/assign.nim | 16 | ||||
-rwxr-xr-x | todo.txt | 3 |
6 files changed, 84 insertions, 80 deletions
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 8c8d02612..f8f3c9dee 100755 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -58,6 +58,7 @@ proc InitDefines*() = # for bootstrapping purposes and old code: DefineSymbol("nimhygiene") DefineSymbol("niminheritable") + DefineSymbol("nimmixin") # add platform specific symbols: case targetCPU diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 4b0c81433..dc0be54cb 100755 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -32,12 +32,12 @@ proc getIdentNode(n: PNode): PNode = result = n proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags, - toBind: var TIntSet): PNode + ctx: var TIntSet): PNode proc semGenericStmtScope(c: PContext, n: PNode, flags: TSemGenericFlags, - toBind: var TIntSet): PNode = + ctx: var TIntSet): PNode = openScope(c.tab) - result = semGenericStmt(c, n, flags, toBind) + result = semGenericStmt(c, n, flags, ctx) closeScope(c.tab) template macroToExpand(s: expr): expr = @@ -73,20 +73,35 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = result = n else: result = newSymNode(s, n.info) +proc semMixinStmt(c: PContext, n: PNode, toMixin: var TIntSet): PNode = + for i in 0 .. < n.len: + toMixin.incl(considerAcc(n.sons[i]).id) + result = newNodeI(nkNilLit, n.info) + +proc Lookup(c: PContext, n: PNode, flags: TSemGenericFlags, + ctx: var TIntSet): PNode = + result = n + let ident = considerAcc(n) + var s = SymtabGet(c.Tab, ident) + if s == nil: + if ident.id notin ctx and withinMixin notin flags: + localError(n.info, errUndeclaredIdentifier, ident.s) + else: + if withinMixin in flags: + result = symChoice(c, n, s, scClosed) + elif s.name.id in ctx: + result = symChoice(c, n, s, scForceOpen) + else: + result = semGenericStmtSymbol(c, n, s) + # else: leave as nkIdent + proc semGenericStmt(c: PContext, n: PNode, - flags: TSemGenericFlags, toBind: var TIntSet): PNode = + flags: TSemGenericFlags, ctx: var TIntSet): PNode = result = n if gCmd == cmdIdeTools: suggestStmt(c, n) case n.kind of nkIdent, nkAccQuoted: - var s = SymtabGet(c.Tab, n.ident) - if s == nil: - if withinMixin notin flags: - localError(n.info, errUndeclaredIdentifier, n.ident.s) - else: - if withinBind in flags or s.id in toBind: - result = symChoice(c, n, s, scClosed) - else: result = semGenericStmtSymbol(c, n, s) + result = Lookup(c, n, flags, ctx) of nkDotExpr: let luf = if withinMixin notin flags: {checkUndeclared} else: {} var s = QualifiedLookUp(c, n, luf) @@ -101,15 +116,19 @@ proc semGenericStmt(c: PContext, n: PNode, # the owner of the symbol! What we need to do is to copy the symbol # in the generic instantiation process... nil - of nkBind: - result = semGenericStmt(c, n.sons[0], flags+{withinBind}, toBind) - of nkBindStmt: - result = semBindStmt(c, n, toBind) + of nkBind: + result = semGenericStmt(c, n.sons[0], flags+{withinBind}, ctx) + of nkMixinStmt: + result = semMixinStmt(c, n, ctx) of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: # check if it is an expression macro: checkMinSonsLen(n, 1) - let luf = if withinMixin notin flags: {checkUndeclared} else: {} - var s = qualifiedLookup(c, n.sons[0], luf) + let fn = n.sons[0] + var s = qualifiedLookup(c, fn, {}) + if s == nil and withinMixin notin flags and + fn.kind in {nkIdent, nkAccQuoted} and considerAcc(fn).id notin ctx: + localError(n.info, errUndeclaredIdentifier, fn.renderTree) + var first = 0 var isDefinedMagic = false if s != nil: @@ -152,54 +171,54 @@ proc semGenericStmt(c: PContext, n: PNode, # is not exported and yet the generic 'threadProcWrapper' works correctly. let flags = if isDefinedMagic: flags+{withinMixin} else: flags for i in countup(first, sonsLen(result) - 1): - result.sons[i] = semGenericStmt(c, result.sons[i], flags, toBind) + result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx) of nkIfStmt: for i in countup(0, sonsLen(n)-1): - n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, toBind) + n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx) of nkWhenStmt: for i in countup(0, sonsLen(n)-1): - n.sons[i] = semGenericStmt(c, n.sons[i], flags+{withinMixin}, toBind) + n.sons[i] = semGenericStmt(c, n.sons[i], flags+{withinMixin}, ctx) of nkWhileStmt: openScope(c.tab) for i in countup(0, sonsLen(n)-1): - n.sons[i] = semGenericStmt(c, n.sons[i], flags, toBind) + n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) closeScope(c.tab) of nkCaseStmt: openScope(c.tab) - n.sons[0] = semGenericStmt(c, n.sons[0], flags, toBind) + n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx) for i in countup(1, sonsLen(n)-1): var a = n.sons[i] checkMinSonsLen(a, 1) var L = sonsLen(a) for j in countup(0, L-2): - a.sons[j] = semGenericStmt(c, a.sons[j], flags, toBind) - a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind) + a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx) + a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx) closeScope(c.tab) of nkForStmt, nkParForStmt: var L = sonsLen(n) openScope(c.tab) - n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, toBind) + n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx) for i in countup(0, L - 3): addPrelimDecl(c, newSymS(skUnknown, n.sons[i], c)) - n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, toBind) + n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx) closeScope(c.tab) of nkBlockStmt, nkBlockExpr, nkBlockType: checkSonsLen(n, 2) openScope(c.tab) if n.sons[0].kind != nkEmpty: addPrelimDecl(c, newSymS(skUnknown, n.sons[0], c)) - n.sons[1] = semGenericStmt(c, n.sons[1], flags, toBind) + n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx) closeScope(c.tab) of nkTryStmt: checkMinSonsLen(n, 2) - n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, toBind) + n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx) for i in countup(1, sonsLen(n)-1): var a = n.sons[i] checkMinSonsLen(a, 1) var L = sonsLen(a) for j in countup(0, L-2): - a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, toBind) - a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind) + a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx) + a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx) of nkVarSection, nkLetSection: for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] @@ -208,8 +227,8 @@ proc semGenericStmt(c: PContext, n: PNode, checkMinSonsLen(a, 3) var L = sonsLen(a) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, - toBind) - a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, toBind) + ctx) + a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx) for j in countup(0, L-3): addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) of nkGenericParams: @@ -219,7 +238,7 @@ proc semGenericStmt(c: PContext, n: PNode, checkMinSonsLen(a, 3) var L = sonsLen(a) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, - toBind) + ctx) # do not perform symbol lookup for default expressions for j in countup(0, L-3): addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) @@ -230,8 +249,8 @@ proc semGenericStmt(c: PContext, n: PNode, if (a.kind != nkConstDef): IllFormedAst(a) checkSonsLen(a, 3) addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c)) - a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, toBind) - a.sons[2] = semGenericStmt(c, a.sons[2], flags, toBind) + a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx) + a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx) of nkTypeSection: for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] @@ -246,15 +265,15 @@ proc semGenericStmt(c: PContext, n: PNode, checkSonsLen(a, 3) if a.sons[1].kind != nkEmpty: openScope(c.tab) - a.sons[1] = semGenericStmt(c, a.sons[1], flags, toBind) - a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, toBind) + a.sons[1] = semGenericStmt(c, a.sons[1], flags, ctx) + a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx) closeScope(c.tab) else: - a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, toBind) + a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx) of nkEnumTy: if n.sonsLen > 0: if n.sons[0].kind != nkEmpty: - n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, toBind) + n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx) for i in countup(1, sonsLen(n) - 1): var a: PNode case n.sons[i].kind @@ -267,15 +286,15 @@ proc semGenericStmt(c: PContext, n: PNode, of nkFormalParams: checkMinSonsLen(n, 1) if n.sons[0].kind != nkEmpty: - n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, toBind) + n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx) for i in countup(1, sonsLen(n) - 1): var a = n.sons[i] if (a.kind != nkIdentDefs): IllFormedAst(a) checkMinSonsLen(a, 3) var L = sonsLen(a) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, - toBind) - a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, toBind) + ctx) + a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx) for j in countup(0, L-3): addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, @@ -285,22 +304,22 @@ proc semGenericStmt(c: PContext, n: PNode, addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c)) openScope(c.tab) n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos], - flags, toBind) + flags, ctx) if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].sons[0].kind != nkEmpty: addPrelimDecl(c, newSym(skUnknown, getIdent("result"), nil, n.info)) - n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, toBind) - n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, toBind) + n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, ctx) + n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, ctx) var body: PNode if n.sons[namePos].kind == nkSym: body = n.sons[namePos].sym.getBody else: body = n.sons[bodyPos] - n.sons[bodyPos] = semGenericStmtScope(c, body, flags, toBind) + n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx) closeScope(c.tab) of nkPragma, nkPragmaExpr: nil of nkExprColonExpr: checkMinSonsLen(n, 2) - result.sons[1] = semGenericStmt(c, n.sons[1], flags, toBind) - else: + result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx) + else: for i in countup(0, sonsLen(n) - 1): - result.sons[i] = semGenericStmt(c, n.sons[i], flags, toBind) + result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index de103310b..6b4af2a94 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -90,29 +90,6 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode = else: illFormedAst(a) result = newNodeI(nkNilLit, n.info) - -when false: - # not active before 0.9.0 is out - proc semMixinStmt(c: PContext, n: PNode, toMixin: var TIntSet): PNode = - for i in 0 .. < n.len: - var a = n.sons[i] - # If 'a' is an overloaded symbol, we used to use the first symbol - # as a 'witness' and use the fact that subsequent lookups will yield - # the same symbol! - # This is however not true anymore for hygienic templates as semantic - # processing for them changes the symbol table... - let s = QualifiedLookUp(c, a) - if s != nil: - # we need to mark all symbols: - let sc = symChoice(c, n, s, scForceOpen) - if sc.kind == nkSym: - toMixin.incl(sc.sym.id) - else: - for x in items(sc): toMixin.incl(x.sym.id) - else: - # do nothing: identifiers are already not bound: - nil - result = newNodeI(nkNilLit, n.info) proc replaceIdentBySym(n: var PNode, s: PNode) = case n.kind diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim index 8f036caa5..3efbfa7bb 100755 --- a/lib/system/arithm.nim +++ b/lib/system/arithm.nim @@ -240,7 +240,7 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)): :"%edx" """ -# Platform independant versions of the above (slower!) +# Platform independent versions of the above (slower!) when not defined(addInt): proc addInt(a, b: int): int {.compilerProc, inline.} = result = a +% b diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 895a7f9fd..cd4a34f6c 100755 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -144,11 +144,17 @@ proc objectInit(dest: Pointer, typ: PNimType) = # ---------------------- assign zero ----------------------------------------- -# dummy declaration; XXX we need 'mixin' here -proc destroy(x: int) = nil -proc nimDestroyRange*[T](r: T) = - # internal proc used for destroying sequences and arrays - for i in countup(0, r.len - 1): destroy(r[i]) +when not defined(nimmixin): + proc destroy(x: int) = nil + proc nimDestroyRange*[T](r: T) = + # internal proc used for destroying sequences and arrays + for i in countup(0, r.len - 1): destroy(r[i]) +else: + # XXX Why is this exported and no compilerproc? + proc nimDestroyRange*[T](r: T) = + # internal proc used for destroying sequences and arrays + mixin destroy + for i in countup(0, r.len - 1): destroy(r[i]) proc genericReset(dest: Pointer, mt: PNimType) {.compilerProc.} proc genericResetAux(dest: Pointer, n: ptr TNimNode) = diff --git a/todo.txt b/todo.txt index 605782f2c..b5afff4f9 100755 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,8 @@ version 0.9.2 ============= +- document 'mixin' for generics and symbol lookup rules; special rule + for ``[]=`` - implement the compiler as a service - implement for loop transformation for first class iterators - ``=`` should be overloadable; requires specialization for ``=`` @@ -65,7 +67,6 @@ version 0.9.XX - proc specialization in the code gen for write barrier specialization - tlastmod returns wrong results on BSD (Linux, MacOS X: works) - nested tuple unpacking; tuple unpacking in non-var-context -- test branch coverage - make pegs support a compile-time option and make c2nim use regexes instead per default? - 'const' objects including case objects |