Vczh Library++3.0之ManagedX语言检查类型的可见性

Vczh Library++3.0之ManagedX语言检查类型的可见性

    Vczh Library++3.0的山寨C#的ManagedX今天完成了一个功能,就是编译器检查一个类型在他上下文里面是否可用。这个过程足够复杂,我写了足足3个小时。

    ManagedX的符号表里面的类型已经被大大简化了。函数指针是类,基本数字类型也是类,所以归根结底只有
    1:子类型
    2:类
    3:模板类型

    因为某些关系,对于类型别名没有直接在符号表里面体现出来。举个例子:

 1  generic < inout T >
 2  class  A
 3  {
 4      generic < inout U >
 5       public   using  S  =  B < T, U > ;
 6  }
 7 
 8  generic < inout T, inout U >
 9  class  B
10  {
11       public   using  T  =  Dictionary < T, U > ;
12  }

    下面的类型与符号表中类型结构的展开后关系是:

 1  ================================================
 2  A < int >   ->
 3      TypeSymbol(A < int > )
 4      {
 5          GetSymbol()  =  A
 6          GetParentType()  =   0
 7          GetGenericDeclaration()  =  TypeSymbol(A)
 8          {
 9              GetSymbol()  =  A
10              GetParentType()  =   0
11              GetGenericDeclaration()  =   0
12              GetGenericArguments()  =  []
13          }
14          GetGenericArguments()  =  [ int ]
15      }
16  ================================================
17  A < int > .S < string >   ->
18      TypeSymbol(A < int > .S < string > )
19      {
20          GetSymbol()  =  A.S
21          GetParentType()  =   0
22          GetGenericDeclaration()  =  TypeSymbol(A < int > .S)
23          {
24              GetSymbol()  =  A.S
25              GetParentType()  =  TypeSymbol(A < int > )
26              GetGenericDeclaration()  =   0
27              GetGenericArguments()  =  []
28          }
29          GetGenericArguments()  =  [ string ]
30      }
31  ================================================
32  A < int > .S < string > .T  ->
33      TypeSymbol(Dictionary < int string > )
34      {
35          GetSymbol()  =  Dictionary
36          GetParentType()  =   0
37          GetGenericDeclaration()  =  TypeSymbol(Dictionary)
38          GetGenericArguments()  =  [ int string ]
39      }
40  ================================================

    对于展开前的类型结构,A<int>.S<string>.T其实上是指向了GetSymbol()是A<T>.S<U>.T,而ParentType()是A<int>.S<string>的这样一个结构。然后再经过符号表把所有类型别名的目标类型(譬如A.S就是B<T,U>)拿出来,替换掉必要的模板参数,最后获得展开后的类型。

    因为有了继承关系、父子类型和类型别名,所以在判断他们的accessor(也就是public、protected、private、internal和protected internal)是否可见的时候,就非常复杂。代码已经上传到Vczh Library++3.0的主页了,下面是核心函数的代码:

  1               void  EnsureTypeVisibility(
  2                  ManagedLanguageElement *  languageElement,
  3                  ManagedTypeSymbol *  type,
  4                   const  MAP &  argument,
  5                  List < ManagedTypeSymbol *>&  thisTypes,
  6                  List < ManagedTypeSymbol *>&  baseTypes
  7                  )
  8              {
  9                  List < ManagedTypeSymbol *>  typeLevels;
 10                  {
 11                      ManagedTypeSymbol *  currentType = type;
 12                       while (currentType)
 13                      {
 14                          typeLevels.Add(currentType);
 15                          currentType = currentType -> GetGenericDeclaration()
 16                               ? currentType -> GetGenericDeclaration() -> GetParentType()
 17                              :currentType -> GetParentType()
 18                              ;
 19                      }
 20                  }
 21 
 22                  ManagedTypeSymbol *  parentType = 0 ;
 23                   for (vint i = typeLevels.Count() - 1 ;i >= 0 ;i -- )
 24                  {
 25                      ManagedTypeSymbol *  currentType = typeLevels[i];
 26                      ManagedTypeSymbol *  currentDeclaration = currentType -> GetGenericDeclaration()
 27                           ? currentType -> GetGenericDeclaration()
 28                          :currentType
 29                          ;
 30                       if (currentType -> GetGenericDeclaration())
 31                      {
 32                          FOREACH(ManagedTypeSymbol * , genericArgument, currentType -> GetGenericArguments())
 33                          {
 34                              EnsureTypeVisibility(languageElement, genericArgument, argument, thisTypes, baseTypes);
 35                          }
 36                      }
 37 
 38                      ManagedSymbolItem *  currentSymbol = currentDeclaration -> GetSymbol();
 39                      declatt::Accessor currentAccessor = declatt::Public;
 40                       switch (currentSymbol -> GetSymbolType())
 41                      {
 42                       case  ManagedSymbolItem::Class:
 43                       case  ManagedSymbolItem::Structure:
 44                       case  ManagedSymbolItem::Interface:
 45                          {
 46                              ManagedSymbolDeclaration *  symbol = dynamic_cast < ManagedSymbolDeclaration *> (currentSymbol);
 47                              currentAccessor = symbol -> accessor;
 48                          }
 49                           break ;
 50                       case  ManagedSymbolItem::TypeRename:
 51                          {
 52                              ManagedSymbolTypeRename *  symbol = dynamic_cast < ManagedSymbolTypeRename *> (currentSymbol);
 53                              currentAccessor = symbol -> accessor;
 54                          }
 55                           break ;
 56                       case  ManagedSymbolItem::GenericParameter:
 57                           break ;
 58                       default :
 59                          argument.errors.Add(ManagedLanguageCodeException::GetTypeInvisible(languageElement, currentType));
 60                           return ;
 61                      }
 62 
 63                       if ( ! parentType)
 64                      {
 65                          ManagedSymbolItem *  parentSymbol = currentSymbol -> GetParentItem();
 66                           switch (parentSymbol -> GetSymbolType())
 67                          {
 68                           case  ManagedSymbolItem::Class:
 69                           case  ManagedSymbolItem::Structure:
 70                           case  ManagedSymbolItem::Interface:
 71                              {
 72                                  ManagedSymbolDeclaration *  parentDeclaration = dynamic_cast < ManagedSymbolDeclaration *> (parentSymbol);
 73                                  parentType = argument.symbolManager -> GetThisType(parentDeclaration);
 74                              }
 75                               break ;
 76                          }
 77                      }
 78                       if (parentType  &&   ! thisTypes.Contains(parentType))
 79                      {
 80                           if (baseTypes.Contains(parentType))
 81                          {
 82                               switch (currentAccessor)
 83                              {
 84                               case  declatt::Public:
 85                               case  declatt::Protected:
 86                               case  declatt::Internal:
 87                               case  declatt::ProtectedInternal:
 88                                   break ;
 89                               default :
 90                                  argument.errors.Add(ManagedLanguageCodeException::GetTypeInvisible(languageElement, currentType));
 91                                   return ;
 92                              }
 93                          }
 94                           else
 95                          {
 96                               switch (currentAccessor)
 97                              {
 98                               case  declatt::Public:
 99                               case  declatt::Internal:
100                               case  declatt::ProtectedInternal:
101                                   break ;
102                               default :
103                                  argument.errors.Add(ManagedLanguageCodeException::GetTypeInvisible(languageElement, currentType));
104                                   return ;
105                              }
106                          }
107                      }
108 
109                       if (currentSymbol -> GetSymbolType() == ManagedSymbolItem::TypeRename)
110                      {
111                          ManagedSymbolTypeRename *  symbol = dynamic_cast < ManagedSymbolTypeRename *> (currentSymbol);
112                           if (currentType -> GetGenericDeclaration())
113                          {
114                              Dictionary < ManagedTypeSymbol * , ManagedTypeSymbol *>  replacement;
115                               for (vint i = 0 ;i < symbol -> orderedGenericParameterNames.Count();i ++ )
116                              {
117                                  ManagedTypeSymbol *  key = argument.symbolManager -> GetType(symbol -> ItemGroup(symbol -> orderedGenericParameterNames[i]) -> Items()[ 0 ]);
118                                  ManagedTypeSymbol *  value = currentType -> GetGenericArguments()[i];
119                                  replacement.Add(key, value);
120                              }
121                              parentType = argument.symbolManager -> ReplaceGenericArguments(currentType, replacement.Wrap());
122                          }
123                           else
124                          {
125                              parentType = symbol -> type;
126                          }
127                      }
128                       else
129                      {
130                          parentType = currentType;
131                      }
132                  }
133              }
134 
135               void  CollectBaseTypes(ManagedTypeSymbol *  thisType, List < ManagedTypeSymbol *>&  baseTypes,  const  MAP &  argument)
136              {
137                  vint oldCount = baseTypes.Count();
138                   if (thisType -> GetGenericDeclaration())
139                  {
140                      ManagedSymbolDeclaration *  symbol = dynamic_cast < ManagedSymbolDeclaration *> (thisType -> GetGenericDeclaration() -> GetSymbol());
141 
142                      Dictionary < ManagedTypeSymbol * , ManagedTypeSymbol *>  replacement;
143                       for (vint i = 0 ;i < symbol -> orderedGenericParameterNames.Count();i ++ )
144                      {
145                          ManagedTypeSymbol *  key = argument.symbolManager -> GetType(symbol -> ItemGroup(symbol -> orderedGenericParameterNames[i]) -> Items()[ 0 ]);
146                          ManagedTypeSymbol *  value = thisType -> GetGenericArguments()[i];
147                          replacement.Add(key, value);
148                      }
149 
150                      FOREACH(ManagedTypeSymbol * , baseType, symbol -> baseTypes.Wrap())
151                      {
152                          ManagedTypeSymbol *  translatedBaseType = argument.symbolManager -> ReplaceGenericArguments(baseType, replacement.Wrap());
153                           if ( ! baseTypes.Contains(translatedBaseType))
154                          {
155                              baseTypes.Add(translatedBaseType);
156                          }
157                      }
158                  }
159                   else
160                  {
161                      ManagedSymbolDeclaration *  symbol = dynamic_cast < ManagedSymbolDeclaration *> (thisType -> GetSymbol());
162                      FOREACH(ManagedTypeSymbol * , baseType, symbol -> baseTypes.Wrap())
163                      {
164                           if ( ! baseTypes.Contains(baseType))
165                          {
166                              baseTypes.Add(baseType);
167                          }
168                      }
169                  }
170                   for (vint i = oldCount;i < baseTypes.Count();i ++ )
171                  {
172                      CollectBaseTypes(baseTypes[i], baseTypes, argument);
173                  }
174              }
175 
176               void  EnsureTypeVisibility(ManagedLanguageElement *  languageElement, ManagedTypeSymbol *  type, ManagedSymbolItem *  scopeItem,  const  MAP &  argument)
177              {
178                  CHECK_ERROR(
179                       ! scopeItem
180                       ||  scopeItem -> GetSymbolType() == ManagedSymbolItem::Class
181                       ||  scopeItem -> GetSymbolType() == ManagedSymbolItem::Structure
182                       ||  scopeItem -> GetSymbolType() == ManagedSymbolItem::Interface,
183                      L " EnsureTypeVisibility(ManagedLanguageElement*, ManagedTypeSymbol*, ManagedSymbolItem*, const MAP&)#scopeItem内容非法。 "
184                      );
185 
186                  List < ManagedTypeSymbol *>  thisTypes, baseTypes;
187                  {
188                      ManagedSymbolDeclaration *  currentDeclaration = dynamic_cast < ManagedSymbolDeclaration *> (scopeItem);
189                       while (currentDeclaration)
190                      {
191                          thisTypes.Add(argument.symbolManager -> GetThisType(currentDeclaration));
192                          currentDeclaration = dynamic_cast < ManagedSymbolDeclaration *> (currentDeclaration -> GetParentItem());
193                      }
194                  }
195                  FOREACH(ManagedTypeSymbol * , thisType, thisTypes.Wrap())
196                  {
197                      CollectBaseTypes(thisType, baseTypes, argument);
198                  }
199                  EnsureTypeVisibility(languageElement, type, argument, thisTypes, baseTypes);
200              }

    主要方法就是,判断A<int>.S<string>.T是否可见有下面两个判断:
    1:A<int>.S<string>是否可见
    2:A<int>.S<string>扩展后的类型是B<int, string>,判断B<int, string>.T是否可见。
    至于为什么这里不需要判断B<int, string>是否可见,是因为在using S=xxx这条声明的语义分析里面已经查过了,如果不可见就会有错误信息产生。因此这里可以当B<int, string>是可见的,减少多余的错误信息。

    然后判断A<int>.S<string>是否可见比较简单,主要就是判断A<int>.S和string是否可见。

    一直这么递归下去,就把整个类型都检查完了。

你可能感兴趣的:(Vczh Library++3.0之ManagedX语言检查类型的可见性)