diff options
Diffstat (limited to 'compiler/ast.nim')
-rw-r--r-- | compiler/ast.nim | 55 |
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 |