summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-08-04 23:34:58 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-08-04 23:34:58 +0200
commitbaeec118088fa3c40e12271f9ee89a2d701db818 (patch)
tree1d6091fd3507e58db3e16d7c37ba9e00f627ca4b /compiler
parent7ea318a05369a3b0847f7137a173df57b0ad0596 (diff)
downloadNim-baeec118088fa3c40e12271f9ee89a2d701db818.tar.gz
fixes #4354
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgexprs.nim34
-rw-r--r--compiler/trees.nim19
2 files changed, 30 insertions, 23 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 75a7cb3bb..a86409e50 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1151,7 +1151,25 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
               genTypeInfo(p.module, seqtype), a.rdLoc]))
   gcUsage(e)
 
+proc genConstExpr(p: BProc, n: PNode): Rope
+proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
+  if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
+    var t = getUniqueType(n.typ)
+    discard getTypeDesc(p.module, t) # so that any fields are initialized
+    let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
+    fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic)
+    if id == p.module.labels:
+      # expression not found in the cache:
+      inc(p.module.labels)
+      addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
+           [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
+    result = true
+  else:
+    result = false
+
 proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
+  if handleConstExpr(p, e, d): return
+  #echo rendertree e, " ", e.isDeepConstExpr
   var tmp: TLoc
   var t = e.typ.skipTypes(abstractInst)
   getTemp(p, t, tmp)
@@ -1769,22 +1787,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mDotDot, mEqCString: genCall(p, e, d)
   else: internalError(e.info, "genMagicExpr: " & $op)
 
-proc genConstExpr(p: BProc, n: PNode): Rope
-proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
-  if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr:
-    var t = getUniqueType(n.typ)
-    discard getTypeDesc(p.module, t) # so that any fields are initialized
-    let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
-    fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic)
-    if id == p.module.labels:
-      # expression not found in the cache:
-      inc(p.module.labels)
-      addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
-           [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
-    result = true
-  else:
-    result = false
-
 proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
   # example: { a..b, c, d, e, f..g }
   # we have to emit an expression of the form:
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 659df334b..fdd88c348 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -103,14 +103,16 @@ proc getMagic*(op: PNode): TMagic =
     else: result = mNone
   else: result = mNone
 
-proc treeToSym*(t: PNode): PSym =
-  result = t.sym
-
 proc isConstExpr*(n: PNode): bool =
   result = (n.kind in
       {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
        nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags)
 
+proc isCaseObj*(n: PNode): bool =
+  if n.kind == nkRecCase: return true
+  for i in 0..<safeLen(n):
+    if n[i].isCaseObj: return true
+
 proc isDeepConstExpr*(n: PNode): bool =
   case n.kind
   of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
@@ -119,11 +121,14 @@ proc isDeepConstExpr*(n: PNode): bool =
   of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
     result = isDeepConstExpr(n.sons[1])
   of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure:
-    for i in 0 .. <n.len:
+    for i in ord(n.kind == nkObjConstr) .. <n.len:
       if not isDeepConstExpr(n.sons[i]): return false
-    # XXX once constant objects are supported by the codegen this needs to be
-    # weakened:
-    result = n.typ.isNil or n.typ.skipTypes({tyGenericInst, tyDistinct}).kind != tyObject
+    if n.typ.isNil: result = true
+    else:
+      let t = n.typ.skipTypes({tyGenericInst, tyDistinct})
+      if t.kind in {tyRef, tyPtr}: return false
+      if t.kind != tyObject or not isCaseObj(t.n):
+        result = true
   else: discard
 
 proc flattenTreeAux(d, a: PNode, op: TMagic) =