Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/sbi/src/stype.c

    r38aaacc2 r051bc69a  
    3838#include <stdlib.h>
    3939#include <assert.h>
     40#include "cspan.h"
    4041#include "debug.h"
    4142#include "intmap.h"
     
    5253
    5354static void stype_csi(stype_t *stype, stree_csi_t *csi);
     55static void stype_ctor(stype_t *stype, stree_ctor_t *ctor);
     56static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor);
    5457static void stype_fun(stype_t *stype, stree_fun_t *fun);
    5558static void stype_var(stype_t *stype, stree_var_t *var);
     
    6669static void stype_for(stype_t *stype, stree_for_t *for_s);
    6770static void stype_raise(stype_t *stype, stree_raise_t *raise_s);
     71static void stype_break(stype_t *stype, stree_break_t *break_s);
    6872static void stype_return(stype_t *stype, stree_return_t *return_s);
    6973static void stype_exps(stype_t *stype, stree_exps_t *exp_s, bool_t want_value);
     
    8084static stree_expr_t *stype_convert_tdeleg(stype_t *stype, stree_expr_t *expr,
    8185    tdata_item_t *dest);
     86static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
     87    tdata_item_t *dest);
    8288static stree_expr_t *stype_convert_tfun_tdeleg(stype_t *stype,
    8389    stree_expr_t *expr, tdata_item_t *dest);
    8490static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
    8591    tdata_item_t *dest);
    86 static void stype_convert_failure(stype_t *stype, tdata_item_t *src,
     92static void stype_convert_failure(stype_t *stype, stree_expr_t *expr,
    8793    tdata_item_t *dest);
    8894
     
    112118        while (mbr_n != NULL) {
    113119                mbr = list_node_data(mbr_n, stree_modm_t *);
    114                 assert(mbr->mc == mc_csi);
    115 
    116                 stype_csi(stype, mbr->u.csi);
     120
     121                switch (mbr->mc) {
     122                case mc_csi:
     123                        stype_csi(stype, mbr->u.csi);
     124                        break;
     125                case mc_enum:
     126                        stype_enum(stype, mbr->u.enum_d);
     127                        break;
     128                }
    117129
    118130                mbr_n = list_next(&module->members, mbr_n);
     
    145157                switch (csimbr->cc) {
    146158                case csimbr_csi: stype_csi(stype, csimbr->u.csi); break;
     159                case csimbr_ctor: stype_ctor(stype, csimbr->u.ctor); break;
    147160                case csimbr_deleg: stype_deleg(stype, csimbr->u.deleg); break;
     161                case csimbr_enum: stype_enum(stype, csimbr->u.enum_d); break;
    148162                case csimbr_fun: stype_fun(stype, csimbr->u.fun); break;
    149163                case csimbr_var: stype_var(stype, csimbr->u.var); break;
     
    155169
    156170        stype->current_csi = prev_ctx;
     171}
     172
     173/** Type a constructor.
     174 *
     175 * @param stype         Static typing object.
     176 * @param ctor          Constructor to type.
     177 */
     178static void stype_ctor(stype_t *stype, stree_ctor_t *ctor)
     179{
     180#ifdef DEBUG_TYPE_TRACE
     181        printf("Type constructor '");
     182        symbol_print_fqn(ctor_to_symbol(ctor));
     183        printf("'.\n");
     184#endif
     185        if (ctor->titem == NULL)
     186                stype_ctor_header(stype, ctor);
     187
     188        stype_ctor_body(stype, ctor);
     189}
     190
     191/** Type constructor header.
     192 *
     193 * @param stype         Static typing object.
     194 * @param ctor          Constructor to type.
     195 */
     196void stype_ctor_header(stype_t *stype, stree_ctor_t *ctor)
     197{
     198        stree_symbol_t *ctor_sym;
     199        tdata_item_t *ctor_ti;
     200        tdata_fun_t *tfun;
     201        tdata_fun_sig_t *tsig;
     202
     203#ifdef DEBUG_TYPE_TRACE
     204        printf("Type constructor '");
     205        symbol_print_fqn(ctor_to_symbol(ctor));
     206        printf("' header.\n");
     207#endif
     208        if (ctor->titem != NULL)
     209                return; /* Constructor header has already been typed. */
     210
     211        ctor_sym = ctor_to_symbol(ctor);
     212
     213        /* Type function signature. */
     214        stype_fun_sig(stype, ctor_sym->outer_csi, ctor->sig, &tsig);
     215
     216        ctor_ti = tdata_item_new(tic_tfun);
     217        tfun = tdata_fun_new();
     218        ctor_ti->u.tfun = tfun;
     219        tfun->tsig = tsig;
     220
     221        ctor->titem = ctor_ti;
     222}
     223
     224/** Type constructor body.
     225 *
     226 * @param stype         Static typing object
     227 * @param ctor          Constructor
     228 */
     229static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor)
     230{
     231#ifdef DEBUG_TYPE_TRACE
     232        printf("Type constructor '");
     233        symbol_print_fqn(ctor_to_symbol(ctor));
     234        printf("' body.\n");
     235#endif
     236        assert(stype->proc_vr == NULL);
     237
     238        stype->proc_vr = stype_proc_vr_new();
     239        stype->proc_vr->proc = ctor->proc;
     240        list_init(&stype->proc_vr->block_vr);
     241
     242        stype_block(stype, ctor->proc->body);
     243
     244        free(stype->proc_vr);
     245        stype->proc_vr = NULL;
    157246}
    158247
     
    197286}
    198287
     288/** Type enum.
     289 *
     290 * @param stype         Static typing object
     291 * @param enum_d        Enum to type
     292 */
     293void stype_enum(stype_t *stype, stree_enum_t *enum_d)
     294{
     295        tdata_item_t *titem;
     296        tdata_enum_t *tenum;
     297
     298        (void) stype;
     299
     300#ifdef DEBUG_TYPE_TRACE
     301        printf("Type enum '");
     302        symbol_print_fqn(enum_to_symbol(enum_d));
     303        printf("'.\n");
     304#endif
     305        if (enum_d->titem == NULL) {
     306                titem = tdata_item_new(tic_tenum);
     307                tenum = tdata_enum_new();
     308                titem->u.tenum = tenum;
     309                tenum->enum_d = enum_d;
     310
     311                enum_d->titem = titem;
     312        } else {
     313                titem = enum_d->titem;
     314        }
     315}
     316
    199317/** Type function.
    200318 *
     
    457575        case st_for: stype_for(stype, stat->u.for_s); break;
    458576        case st_raise: stype_raise(stype, stat->u.raise_s); break;
     577        case st_break: stype_break(stype, stat->u.break_s); break;
    459578        case st_return: stype_return(stype, stat->u.return_s); break;
    460579        case st_exps: stype_exps(stype, stat->u.exp_s, want_value); break;
     
    506625{
    507626        stree_expr_t *ccond;
     627        list_node_t *ifc_node;
     628        stree_if_clause_t *ifc;
    508629
    509630#ifdef DEBUG_TYPE_TRACE
    510631        printf("Type 'if' statement.\n");
    511632#endif
    512         /* Convert condition to boolean type. */
    513         stype_expr(stype, if_s->cond);
    514         ccond = stype_convert(stype, if_s->cond, stype_boolean_titem(stype));
    515 
    516         /* Patch code with augmented expression. */
    517         if_s->cond = ccond;
    518 
    519         /* Type the @c if block */
    520         stype_block(stype, if_s->if_block);
     633        ifc_node = list_first(&if_s->if_clauses);
     634
     635        /* Walk through all if/elif clauses. */
     636
     637        while (ifc_node != NULL) {
     638                /* Get if/elif clause */
     639                ifc = list_node_data(ifc_node, stree_if_clause_t *);
     640
     641                /* Convert condition to boolean type. */
     642                stype_expr(stype, ifc->cond);
     643                ccond = stype_convert(stype, ifc->cond,
     644                    stype_boolean_titem(stype));
     645
     646                /* Patch code with augmented expression. */
     647                ifc->cond = ccond;
     648
     649                /* Type the @c if/elif block */
     650                stype_block(stype, ifc->block);
     651
     652                ifc_node = list_next(&if_s->if_clauses, ifc_node);
     653        }
    521654
    522655        /* Type the @c else block */
     
    545678        while_s->cond = ccond;
    546679
     680        /* While is a breakable statement. Increment counter. */
     681        stype->proc_vr->bstat_cnt += 1;
     682
    547683        /* Type the body of the loop */
    548684        stype_block(stype, while_s->body);
     685
     686        stype->proc_vr->bstat_cnt -= 1;
    549687}
    550688
     
    559697        printf("Type 'for' statement.\n");
    560698#endif
     699        /* For is a breakable statement. Increment counter. */
     700        stype->proc_vr->bstat_cnt += 1;
     701
    561702        stype_block(stype, for_s->body);
     703
     704        stype->proc_vr->bstat_cnt -= 1;
    562705}
    563706
     
    573716#endif
    574717        stype_expr(stype, raise_s->expr);
     718}
     719
     720/** Type @c break statement */
     721static void stype_break(stype_t *stype, stree_break_t *break_s)
     722{
     723#ifdef DEBUG_TYPE_TRACE
     724        printf("Type 'break' statement.\n");
     725#endif
     726        (void) break_s;
     727
     728        /* Check whether there is an active statement to break from. */
     729        if (stype->proc_vr->bstat_cnt == 0) {
     730                printf("Error: Break statement outside of while or for.\n");
     731                stype_note_error(stype);
     732        }
    575733}
    576734
     
    588746        printf("Type 'return' statement.\n");
    589747#endif
    590         stype_expr(stype, return_s->expr);
     748        if (return_s->expr != NULL)
     749                stype_expr(stype, return_s->expr);
    591750
    592751        /* Determine the type we need to return. */
     
    599758
    600759                /* XXX Memoize to avoid recomputing. */
    601                 run_texpr(stype->program, outer_sym->outer_csi,
    602                     fun->sig->rtype, &dtype);
     760                if (fun->sig->rtype != NULL) {
     761                        run_texpr(stype->program, outer_sym->outer_csi,
     762                            fun->sig->rtype, &dtype);
     763
     764                        if (return_s->expr == NULL) {
     765                                printf("Error: Return without a value in "
     766                                    "function returning value.\n");
     767                                stype_note_error(stype);
     768                        }
     769                } else {
     770                        dtype = NULL;
     771
     772                        if (return_s->expr != NULL) {
     773                                printf("Error: Return with a value in "
     774                                    "value-less function.\n");
     775                                stype_note_error(stype);
     776                        }
     777                }
    603778                break;
    604779        case sc_prop:
     
    606781                assert(prop != NULL);
    607782
    608                 if (stype->proc_vr->proc != prop->getter) {
    609                         printf("Error: Return statement in "
    610                             "setter.\n");
    611                         stype_note_error(stype);
     783                if (stype->proc_vr->proc == prop->getter) {
     784                        if (return_s->expr == NULL) {
     785                                printf("Error: Return without a value in "
     786                                    "getter.\n");
     787                                stype_note_error(stype);
     788                        }
     789                } else {
     790                        if (return_s->expr == NULL) {
     791                                printf("Error: Return with a value in "
     792                                    "setter.\n");
     793                                stype_note_error(stype);
     794                        }
    612795                }
    613796
     
    620803        }
    621804
    622         /* Convert to the return type. */
    623         cexpr = stype_convert(stype, return_s->expr, dtype);
    624 
    625         /* Patch code with the augmented expression. */
    626         return_s->expr = cexpr;
     805        if (dtype != NULL && return_s->expr != NULL) {
     806                /* Convert to the return type. */
     807                cexpr = stype_convert(stype, return_s->expr, dtype);
     808
     809                /* Patch code with the augmented expression. */
     810                return_s->expr = cexpr;
     811        }
    627812}
    628813
     
    714899
    715900        if (src == NULL) {
    716                 printf("Error: Conversion source is not valid.\n");
     901                cspan_print(expr->cspan);
     902                printf(" Error: Conversion source is not valid.\n");
    717903                stype_note_error(stype);
    718904                return expr;
     
    738924        }
    739925
     926        if (src->tic == tic_tebase) {
     927                stype_convert_failure(stype, expr, dest);
     928                printf("Invalid use of reference to enum type in "
     929                    "expression.\n");
     930                return expr;
     931        }
     932
    740933        if (src->tic != dest->tic) {
    741                 stype_convert_failure(stype, src, dest);
     934                stype_convert_failure(stype, expr, dest);
    742935                return expr;
    743936        }
     
    756949                expr = stype_convert_tdeleg(stype, expr, dest);
    757950                break;
     951        case tic_tebase:
     952                /* Conversion destination should never be enum-base */
     953                assert(b_false);
     954        case tic_tenum:
     955                expr = stype_convert_tenum(stype, expr, dest);
     956                break;
    758957        case tic_tfun:
    759958                assert(b_false);
     
    788987        /* Check if both have the same tprimitive class. */
    789988        if (src->u.tprimitive->tpc != dest->u.tprimitive->tpc)
    790                 stype_convert_failure(stype, src, dest);
     989                stype_convert_failure(stype, expr, dest);
    791990
    792991        return expr;
     
    795994/** Convert expression of primitive type to object type.
    796995 *
    797  * This function implements autoboxing. It modified the code.
     996 * This function implements autoboxing. It modifies the code by inserting
     997 * the boxing operation.
    798998 *
    799999 * @param stype         Static typing object
     
    8281028        case tpc_string: bp_sym = bi->boxed_string; break;
    8291029        case tpc_resource:
    830                 stype_convert_failure(stype, src, dest);
     1030                stype_convert_failure(stype, expr, dest);
    8311031                return expr;
    8321032        }
     
    8341034        /* Target type must be boxed @a src or Object */
    8351035        if (csi_sym != bp_sym && csi_sym != bi->gf_class)
    836                 stype_convert_failure(stype, src, dest);
     1036                stype_convert_failure(stype, expr, dest);
    8371037
    8381038        /* Patch the code to box the primitive value */
     
    8411041        bexpr = stree_expr_new(ec_box);
    8421042        bexpr->u.box = box;
     1043        bexpr->titem = dest;
    8431044
    8441045        /* No action needed to optionally convert boxed type to Object */
     
    9011102                } else {
    9021103                        /* No match */
    903                         stype_convert_failure(stype, src, dest);
     1104                        stype_convert_failure(stype, expr, dest);
    9041105                        return expr;
    9051106                }
     
    9161117                if (tdata_item_equal(carg, darg) != b_true) {
    9171118                        /* Diferent argument type */
    918                         stype_convert_failure(stype, src, dest);
     1119                        stype_convert_failure(stype, expr, dest);
    9191120                        printf("Different argument type '");
    9201121                        tdata_item_print(carg);
     
    9311132        if (ca_n != NULL || da_n != NULL) {
    9321133                /* Diferent number of arguments */
    933                 stype_convert_failure(stype, src, dest);
     1134                stype_convert_failure(stype, expr, dest);
    9341135                printf("Different number of arguments.\n");
    9351136                return expr;
     
    9591160        /* Compare rank and base type. */
    9601161        if (src->u.tarray->rank != dest->u.tarray->rank) {
    961                 stype_convert_failure(stype, src, dest);
     1162                stype_convert_failure(stype, expr, dest);
    9621163                return expr;
    9631164        }
     
    9661167        if (tdata_item_equal(src->u.tarray->base_ti,
    9671168            dest->u.tarray->base_ti) != b_true) {
    968                 stype_convert_failure(stype, src, dest);
     1169                stype_convert_failure(stype, expr, dest);
    9691170        }
    9701171
     
    10041205        /* Both must be the same delegate. */
    10051206        if (sdeleg->deleg != ddeleg->deleg) {
    1006                 stype_convert_failure(stype, src, dest);
     1207                stype_convert_failure(stype, expr, dest);
     1208                return expr;
     1209        }
     1210
     1211        return expr;
     1212}
     1213
     1214/** Convert expression of enum type to enum type.
     1215 *
     1216 * @param stype         Static typing object
     1217 * @param expr          Expression
     1218 * @param dest          Destination type
     1219 */
     1220static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
     1221    tdata_item_t *dest)
     1222{
     1223        tdata_item_t *src;
     1224        tdata_enum_t *senum, *denum;
     1225
     1226#ifdef DEBUG_TYPE_TRACE
     1227        printf("Convert enum type.\n");
     1228#endif
     1229        src = expr->titem;
     1230        assert(src->tic == tic_tenum);
     1231        assert(dest->tic == tic_tenum);
     1232
     1233        senum = src->u.tenum;
     1234        denum = dest->u.tenum;
     1235
     1236        /*
     1237         * XXX How should enum types interact with generics?
     1238         */
     1239
     1240        /* Both must be of the same enum type (with the same declaration). */
     1241        if (senum->enum_d != denum->enum_d) {
     1242                stype_convert_failure(stype, expr, dest);
    10071243                return expr;
    10081244        }
     
    10431279
    10441280        if (!stype_fun_sig_equal(stype, ssig, dsig)) {
    1045                 stype_convert_failure(stype, src, dest);
     1281                stype_convert_failure(stype, expr, dest);
    10461282                return expr;
    10471283        }
     
    10751311        /* Currently only allow if both types are the same. */
    10761312        if (src->u.tvref->targ != dest->u.tvref->targ) {
    1077                 stype_convert_failure(stype, src, dest);
     1313                stype_convert_failure(stype, expr, dest);
    10781314                return expr;
    10791315        }
     
    10851321 *
    10861322 * @param stype         Static typing object
    1087  * @param src           Original type
     1323 * @param expr          Original expression
    10881324 * @param dest          Destination type
    10891325 */
    1090 static void stype_convert_failure(stype_t *stype, tdata_item_t *src,
     1326static void stype_convert_failure(stype_t *stype, stree_expr_t *expr,
    10911327    tdata_item_t *dest)
    10921328{
    1093         printf("Error: Cannot convert ");
    1094         tdata_item_print(src);
     1329        cspan_print(expr->cspan);
     1330        printf(" Error: Cannot convert ");
     1331        tdata_item_print(expr->titem);
    10951332        printf(" to ");
    10961333        tdata_item_print(dest);
     
    10991336        stype_note_error(stype);
    11001337}
     1338
     1339/** Box value.
     1340 *
     1341 * This function implements implicit boxing. It modifies the code by inserting
     1342 * the boxing operation.
     1343 *
     1344 * @param stype         Static typing object
     1345 * @param expr          Expression
     1346 * @return              Modified expression.
     1347 */
     1348stree_expr_t *stype_box_expr(stype_t *stype, stree_expr_t *expr)
     1349{
     1350        tdata_item_t *src;
     1351        builtin_t *bi;
     1352        stree_symbol_t *bp_sym;
     1353        stree_box_t *box;
     1354        stree_expr_t *bexpr;
     1355        tdata_object_t *tobject;
     1356
     1357#ifdef DEBUG_TYPE_TRACE
     1358        printf("Boxing.\n");
     1359#endif
     1360        src = expr->titem;
     1361        assert(src->tic == tic_tprimitive);
     1362
     1363        bi = stype->program->builtin;
     1364
     1365        /* Make compiler happy. */
     1366        bp_sym = NULL;
     1367
     1368        switch (src->u.tprimitive->tpc) {
     1369        case tpc_bool: bp_sym = bi->boxed_bool; break;
     1370        case tpc_char: bp_sym = bi->boxed_char; break;
     1371        case tpc_int: bp_sym = bi->boxed_int; break;
     1372        case tpc_nil: assert(b_false);
     1373        case tpc_string: bp_sym = bi->boxed_string; break;
     1374        case tpc_resource:
     1375                cspan_print(expr->cspan);
     1376                printf(" Error: Cannot use ");
     1377                tdata_item_print(expr->titem);
     1378                printf(" as an object.\n");
     1379
     1380                stype_note_error(stype);
     1381                return expr;
     1382        }
     1383
     1384        /* Patch the code to box the primitive value */
     1385        box = stree_box_new();
     1386        box->arg = expr;
     1387        bexpr = stree_expr_new(ec_box);
     1388        bexpr->u.box = box;
     1389        bexpr->titem = tdata_item_new(tic_tobject);
     1390        tobject = tdata_object_new();
     1391        bexpr->titem->u.tobject = tobject;
     1392
     1393        tobject->csi = symbol_to_csi(bp_sym);
     1394        assert(tobject->csi != NULL);
     1395
     1396        return bexpr;
     1397}
     1398
     1399
    11011400
    11021401/** Determine if two type signatures are equal.
     
    12961595
    12971596        stree_symbol_t *outer_sym;
     1597        stree_ctor_t *ctor;
    12981598        stree_fun_t *fun;
    12991599        stree_prop_t *prop;
     
    13141614#endif
    13151615
     1616        /* Make compiler happy. */
     1617        args = NULL;
     1618        varg = NULL;
     1619
    13161620        switch (outer_sym->sc) {
     1621        case sc_ctor:
     1622                ctor = symbol_to_ctor(outer_sym);
     1623                assert(ctor != NULL);
     1624                args = &ctor->sig->args;
     1625                varg = ctor->sig->varg;
     1626                break;
    13171627        case sc_fun:
    13181628                fun = symbol_to_fun(outer_sym);
     
    13311641                        setter_arg = prop->setter_arg;
    13321642                break;
    1333         default:
     1643        case sc_csi:
     1644        case sc_deleg:
     1645        case sc_enum:
     1646        case sc_var:
    13341647                assert(b_false);
    13351648        }
Note: See TracChangeset for help on using the changeset viewer.