summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2017-04-28 17:07:54 +0300
committerZahary Karadjov <zahary@gmail.com>2017-04-28 17:07:54 +0300
commitbc01835091df93d8d278a55c62338e96be646e46 (patch)
treec1ba8add6ba97953e15346b0369f068324175e02
parent3e52bb6535a70339cf4a15123be09916ef0c31f6 (diff)
downloadNim-bc01835091df93d8d278a55c62338e96be646e46.tar.gz
Allow tyOr,tyAnd and tyNot to be constructed in more contexts
-rw-r--r--compiler/semdata.nim4
-rw-r--r--compiler/semmagic.nim48
-rw-r--r--lib/system.nim19
3 files changed, 53 insertions, 18 deletions
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 8f2c802de..5da2b70fa 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -277,6 +277,10 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
   assert n != nil
   result.n = n
 
+proc newTypeWithSons2*(kind: TTypeKind, owner: PSym, sons: seq[PType]): PType =
+  result = newType(kind, owner)
+  result.sons = sons
+
 proc newTypeWithSons*(c: PContext, kind: TTypeKind,
                       sons: seq[PType]): PType =
   result = newType(kind, getCurrOwner(c))
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 3e1989eaf..eb6259df0 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -89,9 +89,9 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
 proc toNode(t: PType, i: TLineInfo): PNode =
   result = newNodeIT(nkType, i, t)
 
-const 
+const
   # these are types that use the bracket syntax for instantiation
-  # they can be subjected to the type traits `genericHead` and 
+  # they can be subjected to the type traits `genericHead` and
   # `Uninstantiated`
   tyUserDefinedGenerics* = {tyGenericInst, tyGenericInvocation,
                             tyUserTypeClassInst}
@@ -109,27 +109,43 @@ proc uninstantiate(t: PType): PType =
     of tyCompositeTypeClass: uninstantiate t.sons[1]
     else: t
 
-proc evalTypeTrait(trait: PNode, operand: PType, context: PSym): PNode =
-  var typ = operand.skipTypes({tyTypeDesc})
+proc evalTypeTrait(traitCall: PNode, operand: PType, context: PSym): PNode =
+  const skippedTypes = {tyTypeDesc}
+  let trait = traitCall[0]
+  internalAssert trait.kind == nkSym
+  var operand = operand.skipTypes(skippedTypes)
+
+  template operand2: PType =
+    traitCall.sons[2].typ.skipTypes({tyTypeDesc})
+
+  template typeWithSonsResult(kind, sons): PNode =
+    newTypeWithSons2(kind, context, sons).toNode(traitCall.info)
+
   case trait.sym.name.s
+  of "or", "|":
+    return typeWithSonsResult(tyOr, @[operand, operand2])
+  of "and":
+    return typeWithSonsResult(tyAnd, @[operand, operand2])
+  of "not":
+    return typeWithSonsResult(tyNot, @[operand])
   of "name":
-    result = newStrNode(nkStrLit, typ.typeToString(preferName))
+    result = newStrNode(nkStrLit, operand.typeToString(preferName))
     result.typ = newType(tyString, context)
-    result.info = trait.info
+    result.info = traitCall.info
   of "arity":
-    result = newIntNode(nkIntLit, typ.len - ord(typ.kind==tyProc))
+    result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc))
     result.typ = newType(tyInt, context)
-    result.info = trait.info
+    result.info = traitCall.info
   of "genericHead":
-    var res = uninstantiate(typ)
-    if res == typ and res.kind notin tyMagicGenerics:
-      localError(trait.info,
+    var res = uninstantiate(operand)
+    if res == operand and res.kind notin tyMagicGenerics:
+      localError(traitCall.info,
         "genericHead expects a generic type. The given type was " &
-        typeToString(typ))
-      return newType(tyError, context).toNode(trait.info)
-    result = res.base.toNode(trait.info)
+        typeToString(operand))
+      return newType(tyError, context).toNode(traitCall.info)
+    result = res.base.toNode(traitCall.info)
   of "stripGenericParams":
-    result = uninstantiate(typ).toNode(trait.info)
+    result = uninstantiate(operand).toNode(traitCall.info)
   else:
     internalAssert false
 
@@ -140,7 +156,7 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
   if t.sonsLen > 0:
     # This is either a type known to sem or a typedesc
     # param to a regular proc (again, known at instantiation)
-    result = evalTypeTrait(n[0], t, getCurrOwner(c))
+    result = evalTypeTrait(n, t, getCurrOwner(c))
   else:
     # a typedesc variable, pass unmodified to evals
     result = n
diff --git a/lib/system.nim b/lib/system.nim
index 82d3bb7f7..f9ae5b552 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -49,6 +49,9 @@ type
   cstring* {.magic: Cstring.} ## built-in cstring (*compatible string*) type
   pointer* {.magic: Pointer.} ## built-in pointer type, use the ``addr``
                               ## operator to get a pointer to a variable
+
+  typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
+
 const
   on* = true    ## alias for ``true``
   off* = false  ## alias for ``false``
@@ -56,6 +59,18 @@ const
 {.push warning[GcMem]: off, warning[Uninit]: off.}
 {.push hints: off.}
 
+proc `|` *(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
+  ## Constructs an `or` meta class
+
+proc `or` *(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
+  ## Constructs an `or` meta class
+
+proc `and` *(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
+  ## Constructs an `and` meta class
+
+proc `not` *(a: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
+  ## Constructs an `not` meta class
+
 type
   Ordinal* {.magic: Ordinal.}[T] ## Generic ordinal type. Includes integer,
                                  ## bool, character, and enumeration types
@@ -66,11 +81,11 @@ type
   `ref`* {.magic: Pointer.}[T] ## built-in generic traced pointer type
 
   `nil` {.magic: "Nil".}
+
   expr* {.magic: Expr, deprecated.} ## meta type to denote an expression (for templates)
-                        ## **Deprecated** since version 0.15. Use ``untyped`` instead.
+    ## **Deprecated** since version 0.15. Use ``untyped`` instead.
   stmt* {.magic: Stmt, deprecated.} ## meta type to denote a statement (for templates)
     ## **Deprecated** since version 0.15. Use ``typed`` instead.
-  typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
   void* {.magic: "VoidType".}   ## meta type to denote the absence of any type
   auto* {.magic: Expr.} ## meta type for automatic type determination
   any* = distinct auto ## meta type for any supported type