"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.0/src/libponyc/ast/symtab.c" (1 Nov 2019, 9068 Bytes) of package /linux/misc/ponyc-0.33.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "symtab.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.29.0_vs_0.30.0.

    1 #include "symtab.h"
    2 #include "stringtab.h"
    3 #include "ast.h"
    4 #include "id.h"
    5 #include "../../libponyrt/gc/serialise.h"
    6 #include "../../libponyrt/mem/pool.h"
    7 #include "ponyassert.h"
    8 #include <stdlib.h>
    9 #include <stdio.h>
   10 #include <string.h>
   11 #include <ctype.h>
   12 
   13 static size_t sym_hash(symbol_t* sym)
   14 {
   15   return ponyint_hash_ptr(sym->name);
   16 }
   17 
   18 static bool sym_cmp(symbol_t* a, symbol_t* b)
   19 {
   20   return a->name == b->name;
   21 }
   22 
   23 static symbol_t* sym_dup(symbol_t* sym)
   24 {
   25   symbol_t* s = POOL_ALLOC(symbol_t);
   26   memcpy(s, sym, sizeof(symbol_t));
   27   return s;
   28 }
   29 
   30 static void sym_free(symbol_t* sym)
   31 {
   32   POOL_FREE(symbol_t, sym);
   33 }
   34 
   35 DEFINE_HASHMAP_SERIALISE(symtab, symtab_t, symbol_t, sym_hash, sym_cmp,
   36   sym_free, symbol_pony_type());
   37 
   38 static const char* name_without_case(const char* name)
   39 {
   40   size_t len = strlen(name) + 1;
   41   char* buf = (char*)ponyint_pool_alloc_size(len);
   42 
   43   if(is_name_type(name))
   44   {
   45     for(size_t i = 0; i < len; i++)
   46       buf[i] = (char)toupper(name[i]);
   47   } else {
   48     for(size_t i = 0; i < len; i++)
   49       buf[i] = (char)tolower(name[i]);
   50   }
   51 
   52   return stringtab_consume(buf, len);
   53 }
   54 
   55 symtab_t* symtab_new()
   56 {
   57   symtab_t* symtab = POOL_ALLOC(symtab_t);
   58   symtab_init(symtab, 8);
   59   return symtab;
   60 }
   61 
   62 symtab_t* symtab_dup(symtab_t* symtab)
   63 {
   64   symtab_t* n = POOL_ALLOC(symtab_t);
   65   symtab_init(n, symtab_size(symtab));
   66 
   67   size_t i = HASHMAP_BEGIN;
   68   symbol_t* sym;
   69 
   70   while((sym = symtab_next(symtab, &i)) != NULL)
   71     symtab_put(n, sym_dup(sym));
   72 
   73   return n;
   74 }
   75 
   76 void symtab_free(symtab_t* symtab)
   77 {
   78   if(symtab == NULL)
   79     return;
   80 
   81   symtab_destroy(symtab);
   82   POOL_FREE(symtab_t, symtab);
   83 }
   84 
   85 bool symtab_add(symtab_t* symtab, const char* name, ast_t* def,
   86   sym_status_t status)
   87 {
   88   const char* no_case = name_without_case(name);
   89 
   90   if(no_case != name)
   91   {
   92     symbol_t s1 = {no_case, def, SYM_NOCASE, 0};
   93     size_t index = HASHMAP_UNKNOWN;
   94     symbol_t* s2 = symtab_get(symtab, &s1, &index);
   95 
   96     if(s2 != NULL)
   97       return false;
   98 
   99     // didn't find it in the map but index is where we can put the
  100     // new one without another search
  101     symtab_putindex(symtab, sym_dup(&s1), index);
  102   }
  103 
  104   symbol_t s1 = {name, def, status, 0};
  105   size_t index = HASHMAP_UNKNOWN;
  106   symbol_t* s2 = symtab_get(symtab, &s1, &index);
  107 
  108   if(s2 != NULL)
  109     return false;
  110 
  111   // didn't find it in the map but index is where we can put the
  112   // new one without another search
  113   symtab_putindex(symtab, sym_dup(&s1), index);
  114   return true;
  115 }
  116 
  117 ast_t* symtab_find(symtab_t* symtab, const char* name, sym_status_t* status)
  118 {
  119   symbol_t s1 = {name, NULL, SYM_NONE, 0};
  120   size_t index = HASHMAP_UNKNOWN;
  121   symbol_t* s2 = symtab_get(symtab, &s1, &index);
  122 
  123   if(s2 != NULL)
  124   {
  125     if(status != NULL)
  126       *status = s2->status;
  127 
  128     if(s2->status == SYM_NOCASE)
  129       return NULL;
  130 
  131     return s2->def;
  132   }
  133 
  134   if(status != NULL)
  135     *status = SYM_NONE;
  136 
  137   return NULL;
  138 }
  139 
  140 ast_t* symtab_find_case(symtab_t* symtab, const char* name,
  141   sym_status_t* status)
  142 {
  143   // Same as symtab_get, but is partially case insensitive. That is, type names
  144   // are compared as uppercase and other symbols are compared as lowercase.
  145   symbol_t s1 = {name, NULL, SYM_NONE, 0};
  146   size_t index = HASHMAP_UNKNOWN;
  147   symbol_t* s2 = symtab_get(symtab, &s1, &index);
  148 
  149   if(s2 != NULL)
  150   {
  151     if(status != NULL)
  152       *status = s2->status;
  153 
  154     return s2->def;
  155   }
  156 
  157   const char* no_case = name_without_case(name);
  158 
  159   if(no_case != name)
  160     return symtab_find_case(symtab, no_case, status);
  161 
  162   if(status != NULL)
  163     *status = SYM_NONE;
  164 
  165   return NULL;
  166 }
  167 
  168 void symtab_set_status(symtab_t* symtab, const char* name, sym_status_t status)
  169 {
  170   symbol_t s1 = {name, NULL, status, 0};
  171   size_t index = HASHMAP_UNKNOWN;
  172   symbol_t* s2 = symtab_get(symtab, &s1, &index);
  173 
  174   if(s2 != NULL)
  175     s2->status = status;
  176   else
  177   {
  178     // didn't find it in the map but index is where we can put the
  179     // new one without another search
  180     symtab_putindex(symtab, sym_dup(&s1), index);
  181   }
  182 }
  183 
  184 void symtab_inherit_status(symtab_t* dst, symtab_t* src)
  185 {
  186   size_t i = HASHMAP_BEGIN;
  187   symbol_t* sym;
  188   size_t index = HASHMAP_UNKNOWN;
  189 
  190   while((sym = symtab_next(src, &i)) != NULL)
  191   {
  192     // Only inherit symbols that were declared in an outer scope.
  193     if(sym->def != NULL)
  194       continue;
  195 
  196     symbol_t* dsym = symtab_get(dst, sym, &index);
  197 
  198     if(dsym != NULL)
  199     {
  200       // Copy the source status the the destination.
  201       dsym->status = sym->status;
  202     } else {
  203       // Add this symbol to the destination.
  204       // didn't find it in the map but index is where we can put the
  205       // new one without another search
  206       symtab_putindex(dst, sym_dup(sym), index);
  207     }
  208   }
  209 }
  210 
  211 void symtab_inherit_branch(symtab_t* dst, symtab_t* src)
  212 {
  213   size_t i = HASHMAP_BEGIN;
  214   symbol_t* sym;
  215   size_t index = HASHMAP_UNKNOWN;
  216 
  217   while((sym = symtab_next(src, &i)) != NULL)
  218   {
  219     // Only inherit symbols that were declared in an outer scope.
  220     if(sym->def != NULL)
  221       continue;
  222 
  223     symbol_t* dsym = symtab_get(dst, sym, &index);
  224 
  225     if(dsym != NULL)
  226     {
  227       if(sym->status == SYM_DEFINED)
  228       {
  229         // Treat defined as adding one to the undefined branch count.
  230         if(dsym->status == SYM_UNDEFINED)
  231           dsym->branch_count++;
  232       } else if(sym->status == SYM_CONSUMED) {
  233         // Consumed overrides everything.
  234         dsym->status = SYM_CONSUMED;
  235         dsym->branch_count = 0;
  236       } else if(sym->status == SYM_CONSUMED_SAME_EXPR) {
  237         // Consumed overrides everything.
  238         dsym->status = SYM_CONSUMED_SAME_EXPR;
  239         dsym->branch_count = 0;
  240       }
  241     } else {
  242       // Add this symbol to the destination.
  243       dsym = sym_dup(sym);
  244 
  245       if(dsym->status == SYM_DEFINED)
  246       {
  247         // Treat defined as undefined with a branch count of one.
  248         dsym->status = SYM_UNDEFINED;
  249         dsym->branch_count = 1;
  250       }
  251 
  252       // didn't find it in the map but index is where we can put the
  253       // new one without another search
  254       symtab_putindex(dst, dsym, index);
  255     }
  256   }
  257 }
  258 
  259 bool symtab_can_merge_public(symtab_t* dst, symtab_t* src)
  260 {
  261   size_t i = HASHMAP_BEGIN;
  262   symbol_t* sym;
  263 
  264   while((sym = symtab_next(src, &i)) != NULL)
  265   {
  266     if(is_name_private(sym->name) ||
  267       (sym->status == SYM_NOCASE) ||
  268       !strcmp(sym->name, "Main"))
  269       continue;
  270 
  271     if(symtab_find_case(dst, sym->name, NULL) != NULL)
  272       return false;
  273   }
  274 
  275   return true;
  276 }
  277 
  278 bool symtab_merge_public(symtab_t* dst, symtab_t* src)
  279 {
  280   size_t i = HASHMAP_BEGIN;
  281   symbol_t* sym;
  282 
  283   while((sym = symtab_next(src, &i)) != NULL)
  284   {
  285     if(is_name_private(sym->name) ||
  286       (sym->status == SYM_NOCASE) ||
  287       !strcmp(sym->name, "Main"))
  288       continue;
  289 
  290     if(!symtab_add(dst, sym->name, sym->def, sym->status))
  291       return false;
  292   }
  293 
  294   return true;
  295 }
  296 
  297 bool symtab_check_all_defined(symtab_t* symtab, errors_t* errors)
  298 {
  299   bool r = true;
  300   size_t i = HASHMAP_BEGIN;
  301   symbol_t* sym;
  302 
  303   while((sym = symtab_next(symtab, &i)) != NULL)
  304   {
  305     // Ignore entries with a NULL def field, that means it was not declared in
  306     // this scope
  307     if(sym->def != NULL && sym->status == SYM_UNDEFINED)
  308     {
  309       ast_error(errors, sym->def,
  310         "Local variable %s is not assigned a value in all code paths", sym->name);
  311       r = false;
  312     }
  313   }
  314 
  315   return r;
  316 }
  317 
  318 void symtab_print(symtab_t* symtab)
  319 {
  320   size_t i = HASHMAP_BEGIN;
  321   symbol_t* sym;
  322 
  323   while((sym = symtab_next(symtab, &i)) != NULL)
  324   {
  325     printf("%s", sym->name);
  326 
  327     switch(sym->status)
  328     {
  329       case SYM_UNDEFINED:
  330         printf(": undefined\n");
  331         break;
  332 
  333       case SYM_DEFINED:
  334         printf(": defined\n");
  335         break;
  336 
  337       case SYM_CONSUMED:
  338         printf(": consumed\n");
  339         break;
  340 
  341       case SYM_CONSUMED_SAME_EXPR:
  342         printf(": consumed same expression\n");
  343         break;
  344 
  345       default:
  346         printf(": UNKNOWN\n");
  347         break;
  348     }
  349   }
  350 }
  351 
  352 static void symbol_serialise_trace(pony_ctx_t* ctx, void* object)
  353 {
  354   symbol_t* sym = (symbol_t*)object;
  355 
  356   string_trace(ctx, (char*)sym->name);
  357 
  358   if(sym->def != NULL)
  359     pony_traceknown(ctx, sym->def, ast_pony_type(), PONY_TRACE_MUTABLE);
  360 }
  361 
  362 static void symbol_serialise(pony_ctx_t* ctx, void* object, void* buf,
  363   size_t offset, int mutability)
  364 {
  365   (void)mutability;
  366 
  367   symbol_t* sym = (symbol_t*)object;
  368   symbol_t* dst = (symbol_t*)((uintptr_t)buf + offset);
  369 
  370   dst->name = (const char*)pony_serialise_offset(ctx, (char*)sym->name);
  371   dst->def = (ast_t*)pony_serialise_offset(ctx, sym->def);
  372   dst->status = sym->status;
  373   dst->branch_count = sym->branch_count;
  374 }
  375 
  376 static void symbol_deserialise(pony_ctx_t* ctx, void* object)
  377 {
  378   (void)ctx;
  379   symbol_t* sym = (symbol_t*)object;
  380 
  381   sym->name = string_deserialise_offset(ctx, (uintptr_t)sym->name);
  382   sym->def = (ast_t*)pony_deserialise_offset(ctx, ast_pony_type(),
  383     (uintptr_t)sym->def);
  384 }
  385 
  386 static pony_type_t symbol_pony =
  387 {
  388   0,
  389   sizeof(symbol_t),
  390   0,
  391   0,
  392   NULL,
  393   NULL,
  394   symbol_serialise_trace,
  395   symbol_serialise,
  396   symbol_deserialise,
  397   NULL,
  398   NULL,
  399   NULL,
  400   NULL,
  401   0,
  402   NULL,
  403   NULL,
  404   NULL
  405 };
  406 
  407 pony_type_t* symbol_pony_type()
  408 {
  409   return &symbol_pony;
  410 }