summary refs log tree commit diff stats
path: root/compiler/semmacrosanity.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semmacrosanity.nim')
-rw-r--r--compiler/semmacrosanity.nim91
1 files changed, 61 insertions, 30 deletions
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
index a6024a42f..727f36470 100644
--- a/compiler/semmacrosanity.nim
+++ b/compiler/semmacrosanity.nim
@@ -10,31 +10,40 @@
 ## Implements type sanity checking for ASTs resulting from macros. Lots of
 ## room for improvement here.
 
-import ast, astalgo, msgs, types
+import ast, msgs, types, options
 
 proc ithField(n: PNode, field: var int): PSym =
   result = nil
   case n.kind
   of nkRecList:
-    for i in countup(0, sonsLen(n) - 1):
-      result = ithField(n.sons[i], field)
+    for i in 0..<n.len:
+      result = ithField(n[i], field)
       if result != nil: return
   of nkRecCase:
-    if n.sons[0].kind != nkSym: internalError(n.info, "ithField")
-    result = ithField(n.sons[0], field)
+    if n[0].kind != nkSym: return
+    result = ithField(n[0], field)
     if result != nil: return
-    for i in countup(1, sonsLen(n) - 1):
-      case n.sons[i].kind
+    for i in 1..<n.len:
+      case n[i].kind
       of nkOfBranch, nkElse:
-        result = ithField(lastSon(n.sons[i]), field)
+        result = ithField(lastSon(n[i]), field)
         if result != nil: return
-      else: internalError(n.info, "ithField(record case branch)")
+      else: discard
   of nkSym:
     if field == 0: result = n.sym
     else: dec(field)
   else: discard
 
-proc annotateType*(n: PNode, t: PType) =
+proc ithField(t: PType, field: var int): PSym =
+  var base = t.baseClass
+  while base != nil:
+    let b = skipTypes(base, skipPtrs)
+    result = ithField(b.n, field)
+    if result != nil: return result
+    base = b.baseClass
+  result = ithField(t.n, field)
+
+proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
   let x = t.skipTypes(abstractInst+{tyRange})
   # Note: x can be unequal to t and we need to be careful to use 't'
   # to not to skip tyGenericInst
@@ -42,54 +51,76 @@ proc annotateType*(n: PNode, t: PType) =
   of nkObjConstr:
     let x = t.skipTypes(abstractPtrs)
     n.typ = t
-    for i in 1 .. <n.len:
+    n[0].typ = t
+    for i in 1..<n.len:
       var j = i-1
-      let field = x.n.ithField(j)
+      let field = x.ithField(j)
       if field.isNil:
-        globalError n.info, "invalid field at index " & $i
+        globalError conf, n.info, "invalid field at index " & $i
       else:
-        internalAssert(n.sons[i].kind == nkExprColonExpr)
-        annotateType(n.sons[i].sons[1], field.typ)
-  of nkPar:
+        internalAssert(conf, n[i].kind == nkExprColonExpr)
+        annotateType(n[i][1], field.typ, conf)
+  of nkPar, nkTupleConstr:
     if x.kind == tyTuple:
       n.typ = t
-      for i in 0 .. <n.len:
-        if i >= x.len: globalError n.info, "invalid field at index " & $i
-        else: annotateType(n.sons[i], x.sons[i])
+      for i in 0..<n.len:
+        if i >= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i
+        else: annotateType(n[i], x[i], conf)
     elif x.kind == tyProc and x.callConv == ccClosure:
       n.typ = t
+    elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples
+      if n.kind == nkTupleConstr:
+        let
+          bracketExpr = newNodeI(nkBracket, n.info)
+          left = int n[1].intVal
+          right = int n[2].intVal
+        bracketExpr.flags = n.flags
+        case n[0].kind # is this a string slice or a array slice
+        of nkStrKinds:
+          for i in left..right:
+            bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i])
+            annotateType(bracketExpr[^1], x.elementType, conf)
+        of nkBracket:
+          for i in left..right:
+            bracketExpr.add n[0][i]
+            annotateType(bracketExpr[^1], x.elementType, conf)
+        else:
+          globalError(conf, n.info, "Incorrectly generated tuple constr")
+        n[] = bracketExpr[]
+
+      n.typ = t
     else:
-      globalError(n.info, "() must have a tuple type")
+      globalError(conf, n.info, "() must have a tuple type")
   of nkBracket:
     if x.kind in {tyArray, tySequence, tyOpenArray}:
       n.typ = t
-      for m in n: annotateType(m, x.elemType)
+      for m in n: annotateType(m, x.elemType, conf)
     else:
-      globalError(n.info, "[] must have some form of array type")
+      globalError(conf, n.info, "[] must have some form of array type")
   of nkCurly:
     if x.kind in {tySet}:
       n.typ = t
-      for m in n: annotateType(m, x.elemType)
+      for m in n: annotateType(m, x.elemType, conf)
     else:
-      globalError(n.info, "{} must have the set type")
+      globalError(conf, n.info, "{} must have the set type")
   of nkFloatLit..nkFloat128Lit:
     if x.kind in {tyFloat..tyFloat128}:
       n.typ = t
     else:
-      globalError(n.info, "float literal must have some float type")
+      globalError(conf, n.info, "float literal must have some float type")
   of nkCharLit..nkUInt64Lit:
     if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
       n.typ = t
     else:
-      globalError(n.info, "integer literal must have some int type")
+      globalError(conf, n.info, "integer literal must have some int type")
   of nkStrLit..nkTripleStrLit:
-    if x.kind in {tyString, tyCString}:
+    if x.kind in {tyString, tyCstring}:
       n.typ = t
     else:
-      globalError(n.info, "string literal must be of some string type")
+      globalError(conf, n.info, "string literal must be of some string type")
   of nkNilLit:
-    if x.kind in NilableTypes:
+    if x.kind in NilableTypes+{tyString, tySequence}:
       n.typ = t
     else:
-      globalError(n.info, "nil literal must be of some pointer type")
+      globalError(conf, n.info, "nil literal must be of some pointer type")
   else: discard