kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

sem.c (3845B)


      1 #include "sem/sem.h"
      2 
      3 static int is_void_pointer(const Type* t) {
      4   return t && t->kind == TY_PTR && t->ptr.pointee &&
      5          t->ptr.pointee->kind == TY_VOID;
      6 }
      7 
      8 static int is_builtin_va_list_record(Pool* p, const Type* t) {
      9   KitSlice s;
     10   if (!t || t->kind != TY_STRUCT || !t->rec.tag) return 0;
     11   s = kit_sym_str(p->c, t->rec.tag);
     12   if (!s.s) return 0;
     13   return kit_slice_eq_cstr(s, "__va_list") ||
     14          kit_slice_eq_cstr(s, "__va_list_tag");
     15 }
     16 
     17 static int pointer_pointees_assignable(Pool* p, const Type* lhs,
     18                                        const Type* rhs) {
     19   const Type* lp;
     20   const Type* rp;
     21   if (!lhs || !rhs || lhs->kind != TY_PTR || rhs->kind != TY_PTR) return 0;
     22   lp = lhs->ptr.pointee;
     23   rp = rhs->ptr.pointee;
     24   if (!lp || !rp) return 0;
     25   if (is_void_pointer(lhs) || is_void_pointer(rhs)) return 1;
     26   if (is_builtin_va_list_record(p, lp) && is_builtin_va_list_record(p, rp))
     27     return 1;
     28   if ((rp->qual & (u16)~lp->qual) != 0) return 0;
     29   return type_compatible(type_unqual(p, lp), type_unqual(p, rp));
     30 }
     31 
     32 static CSemCheck sem_ok(void) {
     33   CSemCheck c;
     34   c.ok = 1;
     35   c.message = NULL;
     36   return c;
     37 }
     38 
     39 static CSemCheck sem_bad(const char* msg) {
     40   CSemCheck c;
     41   c.ok = 0;
     42   c.message = msg;
     43   return c;
     44 }
     45 
     46 CSemCheck c_sem_check_assignment(Pool* p, const Type* lhs, const Type* rhs) {
     47   const Type* lu;
     48   const Type* ru;
     49   if (!lhs || !rhs) return sem_ok();
     50   lu = type_unqual(p, lhs);
     51   ru = type_unqual(p, rhs);
     52   if (lu->kind == TY_VOID)
     53     return sem_bad("assignment to an object with void type");
     54   if (lu->kind == TY_ARRAY) return sem_bad("assignment to array type");
     55   if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     56   if ((lu->kind == TY_STRUCT || lu->kind == TY_UNION) &&
     57       type_compatible(lu, ru)) {
     58     return sem_ok();
     59   }
     60   if (type_is_ptr(lu)) {
     61     if (type_is_ptr(ru)) {
     62       if (pointer_pointees_assignable(p, lu, ru)) {
     63         return sem_ok();
     64       }
     65       return sem_bad("assignment between incompatible pointer types");
     66     }
     67     if (type_is_int(ru)) return sem_ok();
     68     return sem_bad("incompatible assignment to pointer");
     69   }
     70   if (type_is_ptr(ru) && type_is_arith(lu))
     71     return sem_bad("incompatible assignment from pointer to integer");
     72   return sem_bad("incompatible assignment");
     73 }
     74 
     75 CSemCheck c_sem_check_compound_assignment(Pool* p, const Type* lhs,
     76                                           const Type* rhs, int op) {
     77   const Type* lu;
     78   const Type* ru;
     79   if (!lhs || !rhs) return sem_ok();
     80   lu = type_unqual(p, lhs);
     81   ru = type_unqual(p, rhs);
     82   switch (op) {
     83     case '+':
     84     case '-':
     85       if (type_is_ptr(lu)) {
     86         if (type_is_int(ru)) return sem_ok();
     87         return sem_bad("pointer compound assignment requires integer rhs");
     88       }
     89       if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     90       return sem_bad("compound assignment requires arithmetic operands");
     91     case '*':
     92     case '/':
     93       if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     94       return sem_bad("compound assignment requires arithmetic operands");
     95     case '%':
     96     case '&':
     97     case '|':
     98     case '^':
     99     case '<':
    100     case '>':
    101       if (type_is_int(lu) && type_is_int(ru)) return sem_ok();
    102       return sem_bad("compound assignment requires integer operands");
    103     default:
    104       return sem_bad("unsupported compound assignment");
    105   }
    106 }
    107 
    108 CSemCheck c_sem_check_redeclaration(Pool* p, const Type* old_type,
    109                                     const Type* new_type,
    110                                     const Type** composite_out) {
    111   const Type* composite;
    112   if (composite_out) *composite_out = old_type;
    113   if (!old_type || !new_type) return sem_ok();
    114   composite = type_composite(p, old_type, new_type);
    115   if (!composite) return sem_bad("conflicting types for declaration");
    116   if (composite_out) *composite_out = composite;
    117   return sem_ok();
    118 }