summary refs log tree commit diff stats
path: root/compiler/ast.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ast.nim')
-rw-r--r--compiler/ast.nim55
1 files changed, 44 insertions, 11 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 26305cf3b..49ca1c5e0 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -252,6 +252,7 @@ type
     sfProcvar,        # proc can be passed to a proc var
     sfDiscriminant,   # field is a discriminant in a record/object
     sfDeprecated,     # symbol is deprecated
+    sfExplain,        # provide more diagnostics when this symbol is used
     sfError,          # usage of symbol should trigger a compile-time error
     sfShadowed,       # a symbol that was shadowed in some inner scope
     sfThread,         # proc will run as a thread
@@ -354,44 +355,52 @@ type
     tyUnused,
     tyProxy # used as errornous type (for idetools)
 
-    tyBuiltInTypeClass #\
+    tyBuiltInTypeClass
       # Type such as the catch-all object, tuple, seq, etc
 
-    tyUserTypeClass #\
+    tyUserTypeClass
       # the body of a user-defined type class
 
-    tyUserTypeClassInst #\
+    tyUserTypeClassInst
       # Instance of a parametric user-defined type class.
       # Structured similarly to tyGenericInst.
       # tyGenericInst represents concrete types, while
       # this is still a "generic param" that will bind types
       # and resolves them during sigmatch and instantiation.
 
-    tyCompositeTypeClass #\
+    tyCompositeTypeClass
       # Type such as seq[Number]
       # The notes for tyUserTypeClassInst apply here as well
       # sons[0]: the original expression used by the user.
       # sons[1]: fully expanded and instantiated meta type
       # (potentially following aliases)
 
-    tyAnd, tyOr, tyNot #\
+    tyInferred
+      # In the initial state `base` stores a type class constraining
+      # the types that can be inferred. After a candidate type is
+      # selected, it's stored in `lastSon`. Between `base` and `lastSon`
+      # there may be 0, 2 or more types that were also considered as
+      # possible candidates in the inference process (i.e. lastSon will
+      # be updated to store a type best conforming to all candidates)
+
+    tyAnd, tyOr, tyNot
       # boolean type classes such as `string|int`,`not seq`,
       # `Sortable and Enumable`, etc
 
-    tyAnything #\
+    tyAnything
       # a type class matching any type
 
-    tyStatic #\
+    tyStatic
       # a value known at compile type (the underlying type is .base)
 
-    tyFromExpr #\
+    tyFromExpr
       # This is a type representing an expression that depends
       # on generic parameters (the expression is stored in t.n)
       # It will be converted to a real type only during generic
       # instantiation and prior to this it has the potential to
       # be any type.
 
-    tyFieldAccessor #\
+    tyFieldAccessor
       # Expressions such as Type.field (valid in contexts such
       # as the `is` operator and magics like `high` and `low`).
       # Could be lifted to a single argument proc returning the
@@ -400,7 +409,7 @@ type
       # sons[1]: field type
       # .n: nkDotExpr storing the field name
 
-    tyVoid #\
+    tyVoid
       # now different from tyEmpty, hurray!
 
 static:
@@ -420,6 +429,7 @@ const
                     tyAnd, tyOr, tyNot, tyAnything}
 
   tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
+  tyUserTypeClasses* = {tyUserTypeClass, tyUserTypeClassInst}
 
 type
   TTypeKinds* = set[TTypeKind]
@@ -463,6 +473,8 @@ type
                       # can be attached to generic procs with free standing
                       # type parameters: e.g. proc foo[T]()
                       # depends on unresolved static params.
+    tfResolved        # marks a user type class, after it has been bound to a
+                      # concrete type (lastSon becomes the concrete type)
     tfRetType,        # marks return types in proc (used to detect type classes
                       # used as return types for return type inference)
     tfCapturesEnv,    # whether proc really captures some environment
@@ -482,6 +494,9 @@ type
     tfHasStatic
     tfGenericTypeParam
     tfImplicitTypeParam
+    tfInferrableStatic
+    tfExplicit        # for typedescs, marks types explicitly prefixed with the
+                      # `type` operator (e.g. type int)
     tfWildcard        # consider a proc like foo[T, I](x: Type[T, I])
                       # T and I here can bind to both typedesc and static types
                       # before this is determined, we'll consider them to be a
@@ -1036,6 +1051,9 @@ proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
   result = newNode(kind)
   result.strVal = strVal
 
+template previouslyInferred*(t: PType): PType =
+  if t.sons.len > 1: t.lastSon else: nil
+
 proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
              info: TLineInfo): PSym =
   # generates a symbol and initializes the hash field too
@@ -1062,6 +1080,9 @@ proc isMetaType*(t: PType): bool =
          (t.kind == tyStatic and t.n == nil) or
          tfHasMeta in t.flags
 
+proc isUnresolvedStatic*(t: PType): bool =
+  return t.kind == tyStatic and t.n == nil
+
 proc linkTo*(t: PType, s: PSym): PType {.discardable.} =
   t.sym = s
   s.typ = t
@@ -1278,6 +1299,8 @@ proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
     when debugIds: registerId(result)
   result.sym = t.sym          # backend-info should not be copied
 
+proc exactReplica*(t: PType): PType = copyType(t, t.owner, true)
+
 proc copySym*(s: PSym, keepId: bool = false): PSym =
   result = newSym(s.kind, s.name, s.owner, s.info)
   #result.ast = nil            # BUGFIX; was: s.ast which made problems
@@ -1561,7 +1584,7 @@ proc hasPattern*(s: PSym): bool {.inline.} =
   result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
 
 iterator items*(n: PNode): PNode =
-  for i in 0.. <n.len: yield n.sons[i]
+  for i in 0.. <n.safeLen: yield n.sons[i]
 
 iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
   for i in 0.. <n.len: yield (i, n.sons[i])
@@ -1604,6 +1627,16 @@ proc toObject*(typ: PType): PType =
   if result.kind == tyRef:
     result = result.lastSon
 
+proc findUnresolvedStatic*(n: PNode): PNode =
+  if n.kind == nkSym and n.typ.kind == tyStatic and n.typ.n == nil:
+    return n
+
+  for son in n:
+    let n = son.findUnresolvedStatic
+    if n != nil: return n
+
+  return nil
+
 when false:
   proc containsNil*(n: PNode): bool =
     # only for debugging