From 8ef66b973d86a75c8dfa4c6761d322d94c54efad Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 12 Sep 2015 10:55:28 +0200 Subject: [PATCH] first attempt to fix 'a[i]' handling in generics --- compiler/cgen.nim | 2 +- compiler/condsyms.nim | 1 + compiler/semcall.nim | 5 ++++- compiler/semexprs.nim | 13 ++++++++--- compiler/semgnrc.nim | 23 +++++++++++++++++++ compiler/semmagic.nim | 34 +++++++++++++++++++++++++++++ compiler/semstmts.nim | 1 + compiler/semtempl.nim | 51 +++++++++++++++++++++++++++++++++++++++++++ compiler/semtypes.nim | 12 +++++++++- compiler/sigmatch.nim | 6 +++++ lib/system.nim | 8 +++++++ todo.txt | 1 - web/news.txt | 3 +++ 13 files changed, 153 insertions(+), 7 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 3f88e63ee4..f63134b66b 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1110,7 +1110,7 @@ proc rawNewModule(module: PSym, filename: string): BModule = proc nullify[T](arr: var T) = for i in low(arr)..high(arr): - arr[i] = nil + arr[i] = Rope(nil) proc resetModule*(m: BModule) = # between two compilations in CAAS mode, we can throw diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 31bd85a067..60e8f28262 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -92,3 +92,4 @@ proc initDefines*() = defineSymbol("nimvarargstyped") defineSymbol("nimtypedescfixed") defineSymbol("nimKnowsNimvm") + defineSymbol("nimArrIdx") diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 2f181b5f37..6787afe27f 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -308,7 +308,10 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = let gp = finalCallee.ast.sons[genericParamsPos] if gp.kind != nkEmpty: if x.calleeSym.kind notin {skMacro, skTemplate}: - finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) + if x.calleeSym.magic == mArrPut: + finalCallee = x.calleeSym + else: + finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) else: # For macros and templates, the resolved generic params # are added as normal params. diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 3ff04a4fc0..20b6775a56 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1250,7 +1250,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} = template resultTypeIsInferrable(typ: PType): expr = typ.isMetaType and typ.kind != tyTypeDesc -proc semAsgn(c: PContext, n: PNode): PNode = +proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = checkSonsLen(n, 2) var a = n.sons[0] case a.kind @@ -1273,12 +1273,15 @@ proc semAsgn(c: PContext, n: PNode): PNode = # --> `[]=`(a, i, x) let oldBracketExpr = c.p.bracketExpr a = semSubscript(c, a, {efLValue}) - if a == nil: + if a == nil and mode != noOverloadedSubscript: result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=") add(result, n[1]) result = semExprNoType(c, result) c.p.bracketExpr = oldBracketExpr return result + elif a == nil: + localError(n.info, "could not resolve: " & $n[0]) + return n c.p.bracketExpr = oldBracketExpr of nkCurlyExpr: # a{i} = x --> `{}=`(a, i, x) @@ -1323,7 +1326,8 @@ proc semAsgn(c: PContext, n: PNode): PNode = typeMismatch(n, lhs.typ, rhs.typ) n.sons[1] = fitNode(c, le, rhs) - if tfHasAsgn in lhs.typ.flags and not lhsIsResult: + if tfHasAsgn in lhs.typ.flags and not lhsIsResult and + mode != noOverloadedAsgn: return overloadedAsgn(c, lhs, n.sons[1]) fixAbstractType(c, n) @@ -1715,6 +1719,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = of mTypeOf: checkSonsLen(n, 2) result = semTypeOf(c, n.sons[1]) + #of mArrGet: result = semArrGet(c, n, flags) + #of mArrPut: result = semArrPut(c, n, flags) + #of mAsgn: result = semAsgnOpr(c, n) of mDefined: result = semDefined(c, setMs(n, s), false) of mDefinedInScope: result = semDefined(c, setMs(n, s), true) of mCompiles: result = semCompiles(c, setMs(n, s), flags) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index e3b5989192..ed0244b0c6 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -251,6 +251,29 @@ proc semGenericStmt(c: PContext, n: PNode, let flags = if mixinContext: flags+{withinMixin} else: flags for i in countup(first, sonsLen(result) - 1): result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx) + of nkBracketExpr, nkCurlyExpr: + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"), + n.info) + for i in 0 ..< n.len: result.add(n[i]) + result = semGenericStmt(c, result, flags, ctx) + of nkAsgn, nkFastAsgn: + checkSonsLen(n, 2) + let a = n.sons[0] + let b = n.sons[1] + + let k = a.kind + case k + of nkBracketExpr, nkCurlyExpr: + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="), + n.info) + for i in 0 ..< a.len: result.add(a[i]) + result.add(b) + result = semGenericStmt(c, result, flags, ctx) + else: + for i in countup(0, sonsLen(n) - 1): + result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) of nkIfStmt: for i in countup(0, sonsLen(n)-1): n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 5d16470b0b..65185f762a 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -26,6 +26,37 @@ proc semTypeOf(c: PContext; n: PNode): PNode = result.add typExpr result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter})) +type + SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn + +proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode +proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode + +proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode = + result = newNodeI(nkBracketExpr, n.info) + for i in 1.. requires 'mixin' annotation for procs! - split docgen into separate tool -- special rule for ``[]=``, items, pairs - BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info) - make 'nil' work for 'add': - resizeString diff --git a/web/news.txt b/web/news.txt index c786d7d5a0..fd0cf8d8a0 100644 --- a/web/news.txt +++ b/web/news.txt @@ -95,6 +95,9 @@ News - The compiler now supports a new configuration system based on `NimScript `_. + - The compiler finally considers symbol binding rules in templates and + generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators + (issue `#2599 `_). Language Additions