kit

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

sem.c (3914B)


      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                                  CSemAssignContext ctx) {
     48   const Type* lu;
     49   const Type* ru;
     50   (void)ctx;
     51   if (!lhs || !rhs) return sem_ok();
     52   lu = type_unqual(p, lhs);
     53   ru = type_unqual(p, rhs);
     54   if (lu->kind == TY_VOID)
     55     return sem_bad("assignment to an object with void type");
     56   if (lu->kind == TY_ARRAY) return sem_bad("assignment to array type");
     57   if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     58   if ((lu->kind == TY_STRUCT || lu->kind == TY_UNION) &&
     59       type_compatible(lu, ru)) {
     60     return sem_ok();
     61   }
     62   if (type_is_ptr(lu)) {
     63     if (type_is_ptr(ru)) {
     64       if (pointer_pointees_assignable(p, lu, ru)) {
     65         return sem_ok();
     66       }
     67       return sem_bad("assignment between incompatible pointer types");
     68     }
     69     if (type_is_int(ru)) return sem_ok();
     70     return sem_bad("incompatible assignment to pointer");
     71   }
     72   if (type_is_ptr(ru) && type_is_arith(lu))
     73     return sem_bad("incompatible assignment from pointer to integer");
     74   return sem_bad("incompatible assignment");
     75 }
     76 
     77 CSemCheck c_sem_check_compound_assignment(Pool* p, const Type* lhs,
     78                                           const Type* rhs, int op) {
     79   const Type* lu;
     80   const Type* ru;
     81   if (!lhs || !rhs) return sem_ok();
     82   lu = type_unqual(p, lhs);
     83   ru = type_unqual(p, rhs);
     84   switch (op) {
     85     case '+':
     86     case '-':
     87       if (type_is_ptr(lu)) {
     88         if (type_is_int(ru)) return sem_ok();
     89         return sem_bad("pointer compound assignment requires integer rhs");
     90       }
     91       if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     92       return sem_bad("compound assignment requires arithmetic operands");
     93     case '*':
     94     case '/':
     95       if (type_is_arith(lu) && type_is_arith(ru)) return sem_ok();
     96       return sem_bad("compound assignment requires arithmetic operands");
     97     case '%':
     98     case '&':
     99     case '|':
    100     case '^':
    101     case '<':
    102     case '>':
    103       if (type_is_int(lu) && type_is_int(ru)) return sem_ok();
    104       return sem_bad("compound assignment requires integer operands");
    105     default:
    106       return sem_bad("unsupported compound assignment");
    107   }
    108 }
    109 
    110 CSemCheck c_sem_check_redeclaration(Pool* p, const Type* old_type,
    111                                     const Type* new_type,
    112                                     const Type** composite_out) {
    113   const Type* composite;
    114   if (composite_out) *composite_out = old_type;
    115   if (!old_type || !new_type) return sem_ok();
    116   composite = type_composite(p, old_type, new_type);
    117   if (!composite) return sem_bad("conflicting types for declaration");
    118   if (composite_out) *composite_out = composite;
    119   return sem_ok();
    120 }