diff options
author | Zahary Karadjov <zahary@gmail.com> | 2017-04-28 17:07:54 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2017-04-28 17:07:54 +0300 |
commit | bc01835091df93d8d278a55c62338e96be646e46 (patch) | |
tree | c1ba8add6ba97953e15346b0369f068324175e02 | |
parent | 3e52bb6535a70339cf4a15123be09916ef0c31f6 (diff) | |
download | Nim-bc01835091df93d8d278a55c62338e96be646e46.tar.gz |
Allow tyOr,tyAnd and tyNot to be constructed in more contexts
-rw-r--r-- | compiler/semdata.nim | 4 | ||||
-rw-r--r-- | compiler/semmagic.nim | 48 | ||||
-rw-r--r-- | lib/system.nim | 19 |
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 |